2.1请求的处理参数——上下文对象HttpContext
Asp.net在服务器上创建了HttpRequest类型的对象以表示请求参数,HttpResponse类型的对象以表示回应的处理对象。HttpContext中的常用属性:
HttpContext提供了一些底层的方法,在编写HttpModule的时候非常有用。RewritePath方法用于将HttpRequest中的原始请求地址替换为指定的地址,以便在后面的处理中,使用ASP.NET认为请求的实际地址是这个新的地址。这个方法在使用无Cookie的会话中非常有用,使用它将嵌入在URL中的SessionID取出来,将URL地址修正为一个普通的URL。
2.2应用程序对象HttpApplication
在ASP.NET内部,HttpRuntime管理一个定义在System.Web命名空间下的HttpApplicationFactory类的实例,HttpApplicationFactory通过工厂模式管理HttpApplication对象,在HttpApplicationFactory内部维护了一个HttpApplication对象池,使得被创建的HttpApplication对象可以被重复使用。但是,每一个HttpApplication对象每一次仅仅用于处理一个请求。
处理管道,就是处理复杂问题的时候,将处理的过程分解为多个处理步骤,这种经过多个步骤的处理方式称为处理管道。
对于一个管道来说,它往往要暴露出大量的事件,通过这些事件,提供程序猿的扩展机智。ComponentModel.Component类中,提供了处理多个事件的基础:Events属性,它的类型为System.ComponentModel.EventHandlerList,这是一个线性的字典。
在类中定义多个事件,并创建一个处理管道:
/// <summary>
/// 定义多个事件,并创建一个处理管道
/// </summary>
public class ProcessPipeling : System.ComponentModel.Component
{
/// <summary>
/// 开始事件
/// </summary>
private static readonly object startEvent = new object();
/// <summary>
/// 前一个进程事件
/// </summary>
private static readonly object preProcessEvent = new object();
/// <summary>
/// post事件
/// </summary>
private static readonly object postProcessEvent = new object();
/// <summary>
/// 结束事件
/// </summary>
private static readonly object endEvent = new object();
/// <summary>
/// 开始事件属性
/// </summary>
public event EventHandler StartProcess
{
add { this.Events.AddHandler(startEvent,value); }
remove { this.Events.RemoveHandler(startEvent, value); }
}
/// <summary>
/// 前一个进程事件
/// </summary>
public event EventHandler PreProcessEvent
{
add { this.Events.AddHandler(preProcessEvent, value); }
remove { this.Events.RemoveHandler(preProcessEvent, value); }
}
/// <summary>
/// post事件
/// </summary>
public event EventHandler PostProcessEvent
{
add { this.Events.AddHandler(postProcessEvent, value); }
remove { this.Events.RemoveHandler(postProcessEvent, value); }
}
/// <summary>
/// 结束事件
/// </summary>
public event EventHandler EndEvent
{
add { this.Events.AddHandler(endEvent, value); }
remove { this.Events.RemoveHandler(endEvent, value); }
}
protected void OnStartProcess(EventArgs e)
{
if (this.Events[startEvent] != null)
{
var eventHandler = this.Events[startEvent] as EventHandler;
if (eventHandler != null)
{
eventHandler(this, e);
}
}
}
protected void OnPreProcess(EventArgs e)
{
if (this.Events[preProcessEvent] != null)
{
var eventHandler = this.Events[preProcessEvent] as EventHandler;
if (eventHandler != null)
{
eventHandler(this, e);
}
}
}
protected void OnPostProcess(EventArgs e)
{
if (this.Events[postProcessEvent] != null)
{
var eventHandler = this.Events[postProcessEvent] as EventHandler;
if (eventHandler != null)
{
eventHandler(this, e);
}
}
}
protected void OnEndProcess(EventArgs e)
{
if (this.Events[endEvent] != null)
{
var eventHandler = this.Events[endEvent] as EventHandler;
if (eventHandler != null)
{
eventHandler(this, e);
}
}
}
public void Process()
{
Console.WriteLine("开始处理");
this.OnStartProcess(EventArgs.Empty);
Console.WriteLine("准备处理");
this.OnPreProcess(EventArgs.Empty);
Console.WriteLine("正在处理中");
this.OnPostProcess(EventArgs.Empty);
Console.WriteLine("处理完成");
Console.WriteLine("结束处理");
this.OnEndProcess(EventArgs.Empty);
}
}
//调用方式:
static void process_start(object sender, EventArgs e)
{
Console.WriteLine("开始处理的事件处理……");
}
static void process_PreProcess(object sender, EventArgs e)
{
Console.WriteLine("处理前的事件处理……");
}
static void process_PostProcess(object sender, EventArgs e)
{
Console.WriteLine("处理后的事件处理……");
}
static void process_EndProcess(object sender, EventArgs e)
{
Console.WriteLine("处理完成后的事件处理……");
}
static void Main(string[] args)
{
var process = new ProcessPipeling();
process.StartProcess += process_start;
process.PreProcessEvent += process_PreProcess;
process.PostProcessEvent += process_PostProcess;
process.EndEvent += process_EndProcess;
process.Process();
Console.ReadKey();
}
HttpApplication的处理管道,这种类型的对象实例不是由程序员来创建的,是有ASP.NET帮助我们创建的。
HttpApplication采用处理管道的方法进行处理,将处理的过程分为过个步骤,每个步骤通过事件的形式暴露给程序猿,这些事件按照规定的处理顺序依次出发,程序猿通过编写事件处理方法就可以自定义每一个请求的扩展处理过程。
对于HttpApplication来说,提供了19个标准事件:
AuthenticateRequest表示开始检查用户的身份,而PostAuthenticateRequest则表示用户身份已经检查完成,检查后的用户可以通过HttpContext的User属性获取到。这个属性的类型为System.Security.Principal.IPrincipal,IPrincipal又有一个名为Identity,类型为System.Security.Principal.IIdentity的属性,IIdentity有一个类型为bool类型的属性IsAuthenticated,表示当前请求的用户是否已经被验证,或者说确定了用户是否是匿名用户,IsAuthenticated如果为false,那么表示一个匿名用户,如果为true,IIdentity类型为string的Name属性,就是当前请求的用户名。
当ASP.NET获取用户的身份之后,根据当前请求的用户身份,开始请求权限的检查工作。当第4个时间AuthorizeRequest触发的时候,表示开始进行用户的权限检查,而第5个时间PostAuthorizeRequest则标志着已经完成了用户权限的检查工作。如果用户没有通过安全检查,一般情况下,将跳过剩下的时间,直接触发EndRequest事件结束。
当用户获取了请求的权限,那么服务器开始准备用最快的方式来使用户得到回应的结果。ResolveRequestCache事件标志着到从前缓存的结果中进行检查,看看是否可以直接从以前缓存的结果中直接取得处理的结果,PostResolveRequestCache表示缓存检查的结束。
当不能从缓存中获取结果的时候,必须通过一次处理来计算出当前请求的结果。用于处理请求以得到结果的对象称为处理程序Handler,在ASP.NET中提供了许多的处理程序。PostMapRequestHandler事件表示ASP.NET已经获取了这个处理程序,HttpContext的Handler属性就表示这个处理程序对象。得到处理程序后,还不能马上开始进行处理,这是由于处理请求还需要许多与这个请求有关的数据,Session提供基于会话的状态管理,由于HTTP协议的无状态性,状态管理的问题是Web开发的一个核心问题。AcquireRequestState事件给程序猿提供了一个切入点,PostAcquireRequestState事件则表示已经完成了用户数据的获取工作,可以在处理中使用了。PreRequestHandlerExecute事件用来通知程序员,处理程序就要开始进行处理工作了,如果在用户的状态已经获取之后,还有需要在处理程序处理之前进行的工作,那么就在这个事件中处理。
ReleaseRequestState事件通知程序员需要释放这些状态数据,PostReleaseRequestState则表示已经释放完成。在处理完成之后,如果希望将这次处理的结果缓存起来,以便于在后续的请求中可以直接使用这个结果,UpdateRequestCache事件提供了这个处理机会,PostUpdateRequestCache则表示缓存已经更新完成。
LogRequest表示将这次请求记入日志中,PostLogRequest表示完成了日志工作。
如果我们还需要从HttpApplication前面的时间向后面的时间处理程序传递一些参数,那么可以通过HttpContext的Items属性来完成。
HttpContext类中定义了一个Items属性,这是一个字典,定义如下:
Public IDictionary Items{get;}HttpContext对象将数据传递给后面的处理步骤,而不需要通过方法的参数或者对象的成员。这种传递参数的方式称为基于HttpContext的状态管理。
这种状态管理方式是ASP.Net中周琦最短的状态管理方式,有着极高的内存使用效率,仅仅能够用在服务端的一次处理过程中。