在非XXX.aspx.cs文件中使用Response、Request对象,即在aspx文件的CodeFile文件(Code Behind分离的代码文件)之外使用Response、Request对象。
相信有过ASP.NET开发经验的网友对Response、Request对象绝对不陌生,它们的作用与好处并不是本文讨论的范围。通常我们在XXX.aspx.cs文件中直接使用Response、Request对象,比如我们有一个页面(通常指所谓的后台管理页面)需要登录才能访问,直接访问这个页面,如果程序检测到用户没有登录就跳转到登录页,代码如下:
protected
void
Page_Load(
object
sender, EventArgs e)
{
if
(Session[
"
UserName
"
]
!=
null
)
{
//
//
TODO: 在此处添加通过登录验证逻辑
//
}
else
{
Response.Redirect(
"
Login.aspx
"
);
}
}
可以看到上面我们使用了Response和Session对象,现在我们假设一下我们有好多页面都要用这样的代码对用户的登录情况进行判断,难道我们要重复在不同的页面上书写这段同样的代码吗,显然这很不科学,我们需要重构、重用代码。
通常我们把一些实用方法放在App_Code文件夹中供我们重复利用,那么这里的Session验证与转页面方法能不能封装在App_Code文件夹中的某个cs文件里呢?然后在需要调用的XXX.aspx.cs文件中像下面那样直接调用,那天我们要转向的登陆页面地址变了也只要改一下App_Code文件夹中的cs文件,而不用每个XXX.aspx.cs文件都要去重新修改:
protected
void
Page_Load(
object
sender, EventArgs e)
{
Accounts.CheckLogin();
}
上面Accounts.CheckLogin();方法负责检测用户登录,内部包含了跳转页面处理逻辑。
我们先来分析一下,在自动生成的XXX.aspx.cs文件中我们可以看到下面这样的代码。
public
partial
class
_Default : System.Web.UI.Page
{
protected
void
Page_Load(
object
sender, EventArgs e)
{
Response.Write(
"
Some text!
"
);
}
}
在Visual Studio中将鼠标移到“Response”上面,IDE提示这里的“Response”对象是System.Web.UI.Page成员,这是不是意味着我们在App_Code文件夹中的cs文件创建一个类,并让这个类继承自System.Web.UI.Page这个类,然后就可以一样像在XXX.aspx.cs文件中那样直接使用Response和Session等对象呢?比如像下面那样(App_Code/ Accounts.cs):
public
class
Accounts : System.Web.UI.Page
{
public
Accounts()
{
Response.Write(
"
Some text!
"
);
}
}
上面的代码仅管编译能通过,但真正把程序运行起来后,你会发现报错了,报“响应在此上下文中不可用”。这里有一个“上下文”的概念,英文译为“Context”,下面的“HttpContext”则是“Http上下文”的意思。这里之所以会报错,据MSDN介绍,由于HTTP的无状态特性,Web应用程序需要跟踪上下文片段。比如在XXX.aspx.cs文件中可以用“Request.Url”获取当前请求的URL信息,而你如果把Request.Url这个方法直接定义在App_Code文件夹中的某个cs文件里,然后在外面直接调用,程序就不知道你要的是那个页的Response,即没有参考环境,因为App_Code文件夹的cs文件是不直接提供给浏览器访问的。微软提供的Context实用对象实现了方法调用处上下文的动态封装。即我们在外面定义的含有Response对象的方法,这个方法在那个页面(通常为aspx页面)被调用,就能准确获取到当前请求页的上下文对象集合,相当好用。
然后我们把代码改成这样:
public
class
Accounts
{
public
Accounts()
{
HttpContext.Current.Response.Write(
"
Some text!
"
);
}
}
现在一切正常了,这里的HttpContext是System.Web名字空间下的。通过HttpContext.Current我们还可以点出下面常见的对象或类:
HttpContext.Current.Response
HttpContext.Current.Request
HttpContext.Current.Server
HttpContext.Current.Request.Cookies
另外还包含以下对象:Application、ApplicationInstance、Cache、Error、Items、Trace、User,具体使用方法可以自己去参考MSDN并试验。
读到这里,相信你应该恍然大悟,也应该知道自己该如何做了。下面是我做的一个Demo,一共3个cs文件,代码很简单,一看就明白,后面提供实例源码下载。
1、App_Code/ Accounts.cs
///
<summary>
///
用户登录、登出类
///
</summary>
public
class
Accounts
{
public
Accounts()
{
//
//
TODO: 在此处添加构造函数逻辑
//
}
public
static
void
CheckLogin()
{
if
(HttpContext.Current.Session[
"
UserName
"
]
==
null
)
HttpContext.Current.Response.Redirect(
"
Login.aspx
"
);
}
public
static
void
CheckLogin(
string
goUrl)
{
if
(HttpContext.Current.Session[
"
UserName
"
]
==
null
)
HttpContext.Current.Response.Redirect(goUrl);
}
public
static
void
Login(
string
userName,
string
passWord)
{
if
(userName
==
"
admin
"
&&
passWord
==
"
admin888
"
)
{
HttpContext.Current.Session[
"
UserName
"
]
=
userName;
HttpContext.Current.Response.Redirect(
"
Default.aspx
"
);
}
else
{
HttpContext.Current.Response.Redirect(
"
Login.aspx
"
);
}
}
public
static
void
Logout()
{
HttpContext.Current.Session[
"
UserName
"
]
=
null
;
HttpContext.Current.Response.Redirect(
"
Default.aspx
"
);
}
public
static
void
Logout(
string
goUrl)
{
HttpContext.Current.Session[
"
UserName
"
]
=
null
;
HttpContext.Current.Response.Redirect(goUrl);
}
}
2、Default.aspx.cs
protected
void
Page_Load(
object
sender, EventArgs e)
{
Accounts.CheckLogin();
this
.UserName.Text
=
Session[
"
UserName
"
].ToString();
}
protected
void
Logout_Click(
object
sender, EventArgs e)
{
Accounts.Logout();
}
3、Login.aspx.cs
protected
void
Page_Load(
object
sender, EventArgs e)
{
}
protected
void
btnLogin_Click(
object
sender, EventArgs e)
{
Accounts.Login(
this
.UserName.Text,
this
.PassWord.Text);
}
我对App_Code/ Accounts.cs下的几个方法进行了重载,以便灵活调用。下面代码是在页面一加载的时候用Accounts.CheckLogin();先检查用户登录情况,只有登录成功本方法后面代码才有机会运行,因为不成功直接被转页面了。
protected
void
Page_Load(
object
sender, EventArgs e)
{
Accounts.CheckLogin();
this
.UserName.Text
=
Session[
"
UserName
"
].ToString();
}
源代码下载: HttpContext Demo.rar