动态网站制作指南 [  QQ表情  ]
[ 投票调查 ]
[ 企业邮箱 ]
[ 网站空间 ]
网络编程 | 站长之家 | 网页制作 | 图形图象 | 操作系统 | 冲浪宝典 | 软件教学 | 网络办公 | 邮件系统 | 网络安全 | 认证考试 | 系统进程
ASP源码 | .Net源码 | PHP源码 | JSP源码 | JAVA源码 | CGI源码 | VB源码 | C++源码 | Delphi源码 | PB源码 | VF源码 | 汇编 | 服务器
电脑书籍下载:程序设计书籍 | 数据库教程书籍 | 平面与多媒体书籍 | 网络通讯书籍 | 系统管理书籍 | 网络安全书籍 | 认证考试书籍
Firefox | IE | Maxthon | 迅雷 | 电驴 | BitComet | FlashGet | QQ | QQ空间 | Vista | 输入法 | Ghost | Word | Excel | wps | Powerpoint
asp | .net | php | jsp | Sql | c# | Ajax | xml | Dreamweaver | FrontPages | Javascript | css | photoshop | fireworks | Flash | Cad | Discuz!
当前位置 > 网站建设学院 > 网络编程 > ASP.NET技巧
Tag:注入,存储过程,分页,安全,优化,xmlhttp,fso,jmail,application,session,防盗链,stream,无组件,组件,md5,乱码,缓存,加密,验证码,算法,cookies,ubb,正则表达式,水印,索引,日志,压缩,base64,url重写,上传,控件,Web.config,JDBC,函数,内存,PDF,迁移,结构,破解,编译,配置,进程,分词,IIS,Apache,Tomcat,phpmyadmin,Gzip,触发器,socket
网络编程:ASP教程,ASP.NET教程,PHP教程,JSP教程,C#教程,数据库,XML教程,Ajax,Java,Perl,Shell,VB教程,Delphi,C/C++教程,软件工程,J2EE/J2ME,移动开发
文章搜索服务
邮件订阅
输入你的邮件地址,
你将不会错过任何关于:
[ ASP.NET技巧 ]的信息



本月文章推荐
.ASP.NET 2.0-选用DataSet或Data.
..NET下生产图片验证码.
.关于Asp.net页面Page_Load被执行.
.获取网站的RSS聚合到自己的网页.
.TreeView使用笔记.
.如何获取当前程序文件的路径 Cur.
.如何在调用线程的时候传递参数.
.File.Delete不能删除文件的问题.
.asp.net StreamReader 创建文件.
.一个通用的分页类.
.ASP.NET 2.0 正式版中无刷新页面.
.如何在webform.aspx.cs中控制用户.
.分析ASP.NET服务器控件开发-控件.
.ASP.NET中随机数生成及应用.
..NET自动字符编码识别程序库 NCh.
.将多次查询的数据填充到同一数据.
.对.NET Framework 反射的反思.
.ASP.NET 2.0 里输出文本格式流.
.ASP.Net使用缓存技术提高效率.
.ASP.NET 2.0运行时简要分析.

ASP.NET 2.0中的输出缓存

发表日期:2006-12-18 |


Just about every ASP.NET application needs to keep track of data for a user's session. ASP.NET provides the HttpSessionState class to store session-state values. An instance of the HttpSessionState class for each HTTP request is accessible throughout your application using the static HttpContext.Current.Session property. Access to the same instance is made simpler on every Page and UserControl using the Session property of the Page or UserControl.

The HttpSessionState class provides a collection of key/value pairs, where the keys are of type String and the values are of type Object. This means that Session is extremely flexible and you can store just about any type of data in Session.

But (there is always a but) this flexibility does not come without a cost. The cost is the ease with which bugs can be introduced into your application. Many of the bugs that can be introduced will not be found by unit testing, and probably not by any form of structured testing. These bugs often only surface when the application has been deployed to the production environment. When they do surface it is often very difficult, if not impossible, to determine how they occured and be able to reproduce the bug. This means they are very expensive to fix.

This article presents a strategy to help prevent this type of bug. It uses a Design Pattern called a Facade, in that it wraps the very free interface provided by the HttpSessionState class (that can meet the requirements of any application) with a well designed and controlled interface that is purpose built for a specific application. If you are not familiar with Design Patterns or the Facade pattern, a quick internet search of "facade design pattern" will provide you with plenty of background. However, you do not have to understand design patterns in order to understand this article.

The example code shown in this article is written in C#, but the concepts are applicable to any .NET language.

What is the problem?
In this section of the article I will describe the problems with direct access to the HttpSessionState class, without the facade. I will describe the kinds of bugs that can be introduced.

The following shows the typical code written to access session-state variables.

// Save a session variable
Session["some string"] = anyOldObject;
// Read a session variable
DateTime startDate = (DateTime)Session["StartDate"];


The problems arise from the flexibile interface provided by HttpSessionState: the keys are just strings and the values are not strongly typed.

Using String Literals as Keys
If string literals are used as the keys, the string value of the key is not checked by the compiler. It is easy to create new session values by simple typing errors.

Session["received"] = 27;...
Session["recieved"] = 32;


In the code above, two separate session values have been saved.

Most bugs like this will be identified by unit testing – but not always. It may not always be apparent that the value has not changed as expected.

We can avoid this kind of bug by using constants:

private const string received = "received";...
Session[received] = 27;...
Session[received] = 32;


No Type Checking
There is no type checking of the values being stored in session variables. The compiler cannot check correctness of what is being stored.

Consider the following code:

Session["maxValue"] = 27;...
int maxValue = (int)Session["maxValue"];


Elsewhere the following code is used to update the value.

Session["maxValue"] = 56.7;


If the code to read the "maxValue" session variable into the maxValue int variable is executed again there will be an InvalidCastException thrown.

Most bugs like this will be identified by unit testing – but not always.

Re-using a Key Unintentionally
Even when we define constants on each page for the session keys, it is possible to unintentionally use the same key across pages. Consider the following example:

Code on one page:

private const string edit = "edit";...
Session[edit] = true;


Code on a second page, displayed after the first page:

private const string edit = "edit";...
if ((bool)Session[edit])
{
    ...
}


Code on a third, unrelated, page:

private const string edit = "edit";...
Session[edit] = false;


If the third page is displayed for some reason before the second page is displayed, the value may not be what was expected. The code will probably strill run, but the results will be wrong.

Usually this bug will NOT be picked up in testing. It is only when a user does some particular combination of page navigation (or opening a new browser window) that the bug manifests.

At its worst, no one is aware that the bug has manifested, we may just end up modifying data to an unintended value.

Re-using a Key Unintentionally - again
In the example above, the same data type was stored in the session variable. Because there is no type checking of what gets stored, the problem of incompatible data types can also occur.

Code on one page:

Session["FollowUp"] = "true";


Code on a second page:

Session["FollowUp"] = 1;


Code on a third page:

Session["FollowUp"] = true;


When the bug manifests there will be an InvalidCastException thrown.

Usually this bug will NOT be picked up in testing. It is only when a user does some particular combination of page navigation (or opening a new browser window) that the bug manifests.

What Can We Do?
The First Quick Fix
The first and most simple thing we can do is make sure we never use string literals for session keys. Always use constants and so avoid simple typing mistakes.

private const string limit = "limit";...
Session[limit] = 27;...
Session[limit] = 32;


However, when constants are defined locally (e.g. at page level) we might still re-use the same key unintentionally.

A Better Quick Fix
Rather than define constants on each page, group all session key constants into a single location and provide documentation that will appear in Intellisense. The documentation should clearly indicate what the session variable is used for. For example, define a class just for the session keys:

public static class SessionKeys
{
    /// <summary>
    ///     The maximum ...
    /// </summary>
    public const string Limit = "limit";
}

...

    Session[SessionKeys.Limit] = 27;


When you need a new session variable, if you choose a name that has already been used you will know this when you add the constant to the SessionKeys class. You can see how it is currently being used and can determine if you should be using a different key.

However, we are still not ensuring consistency of data type.

A Much Better Way - Using a Facade
Only access the HttpSessionState from within one single static class in your application - the facade. There must be no direct access to the Session property from within code on pages or controls, and no direct access to HttpContext.Current.Session other than from within the facade

All session variables will be exposed as properties of the facade class.

This has the same advantages as using a single class for all the session keys, plus the following advantages:

Strong typing of what gets put into session variables.
No need for casting in code where session variables are used.
All the benefits of property setters to validate what gets put into session variables (more than just type).
All the benefits of property getters when accessing session variables. For example, initialising a variable the first time it is accessed.
An Example Session Facade Class
Here is an example class to implement the Session facade for an application called MyApplication.

 Collapse
/// <summary>
///     MyApplicationSession provides a facade to the ASP.NET Session object.
///     All access to Session variables must be through this class.
/// </summary>
public static class MyApplicationSession
{
    # region Private Constants
    //---------------------------------------------------------------------
    private const string userAuthorisation = "UserAuthorisation";
    private const string teamManagementState = "TeamManagementState";
    private const string startDate = "StartDate";
    private const string endDate = "EndDate";
    //---------------------------------------------------------------------
    # endregion

    # region Public Properties
    //---------------------------------------------------------------------
    /// <summary>
    ///     The Username is the domain name and username of the current user.
    /// </summary>
    public static string Username
    {
        get { return HttpContext.Current.User.Identity.Name; }
    }


    /// <summary>
    ///     UserAuthorisation contains the authorisation information for
    ///     the current user.
    /// </summary>
    public static UserAuthorisation UserAuthorisation
    {
        get
        {
            UserAuthorisation userAuth
                     = (UserAuthorisation)HttpContext.Current.Session[userAuthorisation];

            // Check whether the UserAuthorisation has expired
            if (
                 userAuth == null ||
                 (userAuth.Created.AddMinutes(
                    MyApplication.Settings.Caching.AuthorisationCache.CacheExpiryMinutes))
                     < DateTime.Now
               )
            {
                userAuth = UserAuthorisation.GetUserAuthorisation(Username);
                UserAuthorisation = userAuth;
            }

            return userAuth;
        }

        private set
        {
            HttpContext.Current.Session[userAuthorisation] = value;
        }
    }

    /// <summary>
    ///     TeamManagementState is used to store the current state of the
    ///     TeamManagement.aspx page.
    /// </summary>
    public static TeamManagementState TeamManagementState
    {
        get
        {
            return (TeamManagementState)HttpContext.Current.Session[teamManagementState];
        }

        set
        {
            HttpContext.Current.Session[teamManagementState] = value;
        }
    }

    /// <summary>
    ///     StartDate is the earliest date used to filter records.
    /// </summary>
    public static DateTime StartDate
    {
        get
        {
            if (HttpContext.Current.Session[startDate] == null)
                return DateTime.MinValue;
            else
                return (DateTime)HttpContext.Current.Session[startDate];
        }

        set
        {
            HttpContext.Current.Session[startDate] = value;
        }
    }

    /// <summary>
    ///     EndDate is the latest date used to filter records.
    /// </summary>
    public static DateTime EndDate
    {
        get
        {
            if (HttpContext.Current.Session[endDate] == null)
                return DateTime.MaxValue;
            else
                return (DateTime)HttpContext.Current.Session[endDate];
        }

        set
        {
            HttpContext.Current.Session[endDate] = value;
        }
    }
    //---------------------------------------------------------------------
    # endregion
}


The class demonstrates the use of property getters that can provide default values if a value has not been explicitly stored. For example, the StartDate property provides DateTime.MinValue as a default.

The property getter for the UserAuthorisation property provides a simple cache of the UserAuthorisation class instance, ensuring that the instance in the session variables is kept up to date. This property also shows the use of a private setter, so that the value in the session variable can only be set under the control of facade class.

The Username property demonstrates a value that may once have been stored as a session variable but is no longer stored this way.

The following code shows how a session variable can be accessed through the facade. Note that there is not need to do any casting in this code.

// Save a session variable
MyApplicationSession.StartDate = DateTime.Today.AddDays(-1);
// Read a session variable
DateTime startDate = MyApplicationSession.StartDate;


Additional Benefits
An additional benefit of the facade design pattern is that it hides the internal implemention from the rest of the application. Perhaps in the future you may decide to use another mechanism of implementing session-state, other than the built-in ASP.NET HttpSessionState class. You only need to change the internals of the facade - you do not need to change anything else in the rest of the application.

Summary
The use of a facade for HttpSessionState provides a much more robust way to access session variables. This is a very simple technique to implement, but with great benefit.

上一篇:MSBuild, NAnt, NUnit, MSTest所带来的不爽 人气:3849
下一篇:下载文件出现提示框或者直接显示在浏览器中 人气:3422
浏览全部asp.net的内容 Dreamweaver插件下载 常用网页广告代码全集
  最新网站源码 最新软件下载
2008-7-19 Roclog v3.1.4 SP1
2008-7-19 马克斯CMS(Maxcms) v1.1 Build 0
2008-7-19 乐学LBBS无限级目录图片直读系统
2008-7-19 PHP在线考试系统PPExam v1.2.5
2008-7-19 APJE私服发布系统 v2.0
2008-7-19 寻觅图书管理系统 v1.12
2008-7-19 寻觅学校管理系统
2008-7-19 义乌网站目录baidu新闻订阅 v1.0
2008-7-19 牛仔IIS日志蜘蛛爬行记录分析器
2008-7-19 UltraEdit 简体中文增强版 14.10
2008-7-19 CentOS 5.2 i386 LiveCD
2008-7-19 Snapture多功能相机 v1.4
2008-7-19 iAcces中文输入法 v1.0Build016
2008-7-19 Cookbook烹饪秘籍 v2.5
2008-7-19 苹果专用DVD转换工具 v1.1.59汉化
2008-7-19 Modem修复软件ZiPhone修改版04.0
2008-7-19 AgileMessenger即时通讯工具美化
2008-7-19 Sketches画图软件 v0.7b6破解版


  发表评论
姓 名: 验证码:
内 容:
[ 汉字翻译拼音 ] [ 广告代码 ] [ 符号对照表 ] [ 进制转换 ] [ 经典小工具 ] [ 个税计算 ] [ 汉字简繁转换 ] [ 普通单位换算 ] [ 公制单位换算 ]
[ 生辰老黄历 ] [ 国内电话区号 ] [ 国家代码与域名缩写 ] [ 文字加密解密 ] [ 健康查询 ] [ 万年历 ] [ 手机号码查询 ] [ ip搜索 ] [ Google PR查询 ]
业务联系 | 广告刊登 | 频道合作 | 投稿荐稿 | 联系方式 | 加入收藏 | RSS订阅
Copyright © 2000-2008 www.knowsky.com All rights reserved | 网络实名:动态网站制作指南 | 沪ICP备05001343号
ホームページ制作 不動産検索システム 求人情報
防水工事·改修工事 フットサル大会 探偵