在asp.net 2.0(fx2.0)中,采用了和asp.net 1.1(fx1.1)不同的编译模型。在fx1.1中,Page_Load事件的挂接是写在CodeBehind的代码中的,到了fx2.0,采用了partial关键字后,估计是编译器自动产生了代码,再和codefile中的代码合并。
fx2.0的编译模式在大多数情况下效果不错,代码文件也变得更简洁了。但一旦使用页面继承时,问题就出来了。
在fx1.1中,可以写如下代码
public class BasePage:Page
{
override protected void OnInit(EventArgs e)
{
InitializeComponent();
base.OnInit(e);
}
private void InitializeComponent()
{
this.Load += new System.EventHandler(this.My_Page_Load);
}
protected void My_Page_Load(object sender, EventArgs e)
{
// do somthing public...
PageLoadEvent(sender,e);
}
protected virtual void PageLoadEvent(object sender, EventArgs e) { }
}
public class FooPage:BasePage
{
protected void Page_Load(object sender, EventArgs e)
{
}
protected override void PageLoadEvent(object sender, EventArgs e)
{
// do something here...
}
}
在fx1.1中,这么写没什么问题,FooPage中的Page_Load不会被执行,一切都很正常。
但在fx2.0中,首先,我不能自己挂接Page_Load事件了,因为编译器接管这事了。如果想实现fx1.1中的类似功能,只能这么写了:
public class BasePage:Page
{
protected void Page_Load(object sender, EventArgs e)
{
// do somthing public...
PageLoadEvent(sender,e);
}
protected virtual void PageLoadEvent(object sender, EventArgs e) { }
}
public class FooPage:BasePage
{
protected void Page_Load(object sender, EventArgs e)
{
}
protected override void PageLoadEvent(object sender, EventArgs e)
{
// do something here...
}
}
在2.0的代码中,必须写Page_Load,这样才会被编译器自动挂接,没法自定义了,这倒不是什么问题,只需遵守2.0的规矩好了,但在FooPage中就出问题了,在FooPage中一旦写了Page_Load,就会覆盖BasePage中的Page_Load,而编译器只会发出warning,说FooPage中的Page_Load隐藏了BasePage中的Page_Load,这样的继承是很危险的,子类的设计者很可能在不经意间覆盖了父类的逻辑。在这个例子中,一旦FooPage中定义了Page_Load,那么在PageLoadEvent就不会被执行了(假设FooPage的设计者并不是BasePage的设计者)。
有可能在2.0中有选项,使得与1.1完全兼容,但我试了一下,发现不管怎么改,只要在代码中有Page_Load,编译器铁定会挂接Page_Load事件。
解决方法:
在其他的方法中进行验证。
virtual protected void PageLoadEvent( object sender, System.EventArgs e )
{
}
protected override void OnPreInit( EventArgs e )
{
ValidateSession();
base.OnPreInit( e );
}
/// <summary>
/// 验证用户信息
/// </summary>
public void ValidateSession()
{
//如果后台管理界面超时
if (HttpContext.Current.Session["UserId"] == null || string.IsNullOrEmpty(HttpContext.Current.Session["UserId"].ToString()))
{
Response.Write("<script>alert('登录状态过期,请重新登录');top.window.location='/admin/login.aspx';</script>");
HttpContext.Current.Response.End();
return;
//Response.Redirect("~/admin/login.aspx",true);
}
}