深入解析Asp.NET架构
2007-09-07 16:39
387 查看
首先我们来说一下Asp.net工作原理。
具体描述下这样的:首先客户请求WEB页。然后WEB服务寻找指令文件(.aspx),而这 时就是aspnet_isapi.dll这个动态连接库来处理。接着Asp.net代码被发送到公共语言运行时进行编译。接着HTML流返回给浏览器和 令。最后由浏览器处理HTML并显示页面。
什么是ISAPI呢?
在Internet时代的开端,客户端的需求非常有限;.htm文件就可以满足他们的需求。但是,随着时间的流逝,客户端需求的扩充超越了.htm文件或静态文件所包含的功能。
开 发者需要扩充或扩展Web服务器的功能。Web服务器厂商设计了不同的解决方案,但是都遵循同一个主题“向Web服务器插入某些组件”。所有的Web服务 器补充技术都允许开发者建立并插入组件以增强Web服务器的功能。微软公司提出了ISAPI(Internet服务器API),网景公司提出了NSAPI (网景服务器API)等等。ISAPI是一种重要的技术,它允许我们增强与ISAPI兼容的Web服务器(IIS就是一种与ISAPI兼容的Web服务 器)的能力。我们使用下面的组件达到这个目的:
1,ISAPI扩展:ISAPI扩展是使用Win32动态链接库来实现的。你可以把ISAPI扩展看作是一个普通的应用程序。ISAPI扩展的处理目标是http请求。
2,ISAPI过滤器:客户端每次向服务器发出请求的时候,请求要经过过滤器。客户端不需要在请求中指定过滤器,只需要简单地把请求发送给Web服务器,接着Web服务器把请求传递给相关的过滤器。接下来过滤器可能修改请求,执行某些登录操作等等。
ASP.NET请求的处理过程:
ASP.NET请求处理过程是基于管道模型的,在模型中ASP.NET把http请求传递给管道中的所 有模块。每个模块都接收http请求并有完全控制权限。模块可以用任何自认为适合的方式来处理请求。一旦请求经过了所有HTTP模块,就最终被HTTP处 理程序处理。HTTP处理程序对请求进行一些处理,并且结果将再次经过管道中HTTP模块。
ISAPI的筛选器:
IIS本身是不支持动态页面的,也就是说它仅仅支持静态html页面的内容,对于如.asp,.aspx,. cgi,.php等,IIS并不会处理这些标记,它就会把它当作文本,丝毫不做处理发送到客户端。为了解决这个问题。IIS有一种机制,叫做ISAPI的 筛选器,它是一个标准组件(COM组件)。
Asp.net服务在注册到IIS的时候,会把每个扩展可以处理的文件扩展名注册到IIS里面(如: *.ascx、*.aspx等)。扩展启动后,就根据定义好的方式来处理IIS所不能处理的文件,然后把控制权跳转到专门处理代码的进程中让这个进程开始 处理代码,生成标准的HTML代码,生成后把这些代码加入到原有的Html中,最后把完整的Html返回给IIS,IIS再把内容发送到客户端。
HttpModule:
HttpModule实现了ISAPI Filter的功能,是通过对IhttpModule接口的继承来处理。
HTTP模块是实现了System.Web.IhttpModule接口的.NET组件。这些组件通过在某些事件中注册自身,把自己插入ASP.NET请求处理管道。当这些事件发生的时候,ASP.NET调用对请求有兴趣的HTTP模块,这样该模块就能处理请求了。
HttpModule的实现:
1. 编写一个类,实现IhttpModule接口。
2. 实现Init 方法,并且注册需要的方法。
3. 实现注册的方法。
4. 实现Dispose方法,如果需要手工为类做一些清除工作,可以添加Dispose方法的实现,但这不是必需的,通常可以不为Dispose方法添加任何代码。
5. 在Web.config文件中,注册您编写的类。
下边我们来看例子,HttpModule的实现:
首先添加一个类库,然后在引用里引用System.Web和System.Security这两个命名空间。然后写个类,代码如下:
1
using System;
2
using System.Collections.Generic;
3
using System.Text;
4
using System.Web;
5
using System.Security.Principal;
6
namespace Httplibrary
7
{
8
public class SecurityModules : IHttpModule
9
{
10
public void Init(HttpApplication r_objApplication)
11
{
12
// 向Application 对象注册事件处理程序,核心部分。
13
r_objApplication.AuthenticateRequest += new EventHandler(this.AuthenticateRequest);
14
}
15
public void Dispose()
16
{
17
18
}
19
private void AuthenticateRequest(object r_objSender, EventArgs r_objEventArgs)
20
{
21
// 鉴别用户的凭证,并找出用户角色。
22
HttpApplication objApp = (HttpApplication)r_objSender;
23
HttpContext objContext = (HttpContext)objApp.Context;
24
if ((objApp.Request["userid"] == null) || (objApp.Request["password"] == null))
25
{
26
objContext.Response.Write("用户名和密码为空,验证失败!");
27
objContext.Response.End();
28
}
29
string userid = "";
30
userid = objApp.Request["userid"].ToString();
31
string password = "";
32
password = objApp.Request["password"].ToString();
33
string[] strRoles;
34
strRoles = AuthenticateAndGetRoles(userid, password);
35
if ((strRoles == null) || (strRoles.GetLength(0) == 0))
36
{
37
objContext.Response.Write("用户名或密码错误!");
38
objApp.CompleteRequest();//终止一个Http请求
39
40
}
41
GenericIdentity objIdentity = new GenericIdentity(userid, "CustomAuthentication");
42
objContext.User = new GenericPrincipal(objIdentity, strRoles);
43
}
44
private string[] AuthenticateAndGetRoles(string r_strUserID, string r_strPassword)
45
{
46
string[] strRoles = null;
47
if ((r_strUserID.Equals("Zhangsan")) && (r_strPassword.Equals("111")))
48
{
49
strRoles = new String[1];
50
strRoles[0] = "Administrator";
51
}
52
else if ((r_strUserID.Equals("Lisi")) && (r_strPassword.Equals("222")))
53
{
54
strRoles = new string[1];
55
strRoles[0] = "User";
56
}
57
return strRoles;
58
}
59
}
60
}
编译一下,下边做测试页面,很简单,放一个label,text=“测试页面”如果成功则显示测试页面。然后在web.config里面配置,这里很重要。添加 注意注释部分。
<httpModules>
<!--注意我这里的Httplibrary是你添加引用的那个DLL的文件名.Httplibrary.SecurityModules
中前边部分是你那个类的名称空间,后边的是你建的类的名字。-->
<add name=" Test1 " type="Httplibrary.SecurityModules,Httplibrary"/>
</httpModules>
然后添加 这个节点,这个大家应该都能明白。
<authorization>
<deny users="?"/>
</authorization>
然 后启动测试页面。刚启动开始后页面一定显示“用户名和密码为空,验证失败!”呵呵,别忘记了咱们这就是目的,然后在你的地址栏后边添加?userid= Zhangsan&password=111这行字。然后就会显示“测试页面”这几个字。大家可以多输入几个名字单步调试一下就明白了。
WebConfig设置
<httpModules>
<add type=“classname,assemblyname”
name=“modulename”/>
<remove name=“modulename”/>
<clear/>
</httpModules>
子标记说明:
<add>将HttpModule 类添加到应用程序。请注意,如果以前已指定了相同的谓词/路径组合(例如在父目录的Web.config 文件中),则对的第二个调用将重写以前的设置。
<remove>从应用程序移除HttpModule 类。
<clear>从应用程序移除所有HttpModule 映射。
深入研究HttpModule
HttpModule通过对HttpApplication对象的一系列事件的处理来对HTTP处理管道施加影响,这些事件在HttpModule的Init方法中进行注册,包括:
BeginRequest
AuthenticateRequest
AuthorizeRequest
ResolveRequestCache
AcquireRequestState
PreRequestHandlerExecute
PostRequestHandlerExecute
ReleaseRequestState
UpdateRequestCache
EndRequest
我们都可以对以上事件进行重新定义,注意时重新定义不时覆盖。我们看一个例子,多个HttpModule的实现,建立两个类库,什么都相同就是类名不相同,引入相应的命名空间后我们编写这个类,代码如下:
1
using System;
2
using System.Collections.Generic;
3
using System.Text;
4
using System.Web;
5
namespace HttpModuleTest1
6
{
7
public class Test1Module:IHttpModule
8
{
9
public Test1Module()
10
{
11
}
12
public string ModuleName
13
{
14
get
15
{
16
return "Test1Module";
17
}
18
}
19
public void Init(HttpApplication application)
20
{
21
application.BeginRequest += new EventHandler(myBeginRequest);
22
application.EndRequest += new EventHandler(myEndRequest);
23
application.PreRequestHandlerExecute += new EventHandler(myPreRequestHandlerExecute);
24
application.PostRequestHandlerExecute += new EventHandler(myPostRequestHandlerExecute);
25
application.ReleaseRequestState += new EventHandler(myReleaseRequestState);
26
application.AcquireRequestState += new EventHandler(myAcquireRequestState);
27
application.AuthenticateRequest += new EventHandler(myAuthenticateRequest);
28
application.AuthorizeRequest += new EventHandler(myAuthorizeRequest);
29
application.ResolveRequestCache += new EventHandler(myResolveRequestCache);
30
application.PreSendRequestHeaders += new EventHandler(myPreSendRequestHeaders);
31
application.PreSendRequestContent += new EventHandler(myPreSendRequestContent);
32
}
33
private void myBeginRequest(object source, EventArgs e)
34
{
35
HttpApplication application = (HttpApplication)source;
36
HttpContext context = application.Context;
37
context.Response.Write("Test1Module:Beggining of Request<br>");
38
}
39
private void myEndRequest(object source, EventArgs e)
40
{
41
HttpApplication application = (HttpApplication)source;
42
HttpContext context = application.Context;
43
context.Response.Write("Test1Module:End of Request<br>");
44
}
45
private void myPreRequestHandlerExecute(object source, EventArgs e)
46
{
47
HttpApplication application = (HttpApplication)source;
48
HttpContext context = application.Context;
49
context.Response.Write("Test1Module:Application_RequestHandlerExecute:<br>");
50
}
51
private void myPostRequestHandlerExecute(object source, EventArgs e)
52
{
53
HttpApplication application = (HttpApplication)source;
54
HttpContext context = application.Context;
55
context.Response.Write("Test1Module:Application_PostRequestHandlerExecute:<br>");
56
}
57
private void myReleaseRequestState(object source, EventArgs e)
58
{
59
HttpApplication application = (HttpApplication)source;
60
HttpContext context = application.Context;
61
context.Response.Write("Test1Module:Application_ReleaseRequestState:<br>");
62
}
63
private void myAcquireRequestState(object source, EventArgs e)
64
{
65
HttpApplication application = (HttpApplication)source;
66
HttpContext context = application.Context;
67
context.Response.Write("Test1Module:Application_ReleaseRequestState:<br>");
68
}
69
private void myAuthenticateRequest(object source, EventArgs e)
70
{
71
HttpApplication application = (HttpApplication)source;
72
HttpContext context = application.Context;
73
context.Response.Write("Test1Module:Application_AuthenticateRequest:<br>");
74
}
75
private void myAuthorizeRequest(object source, EventArgs e)
76
{
77
HttpApplication application = (HttpApplication)source;
78
HttpContext context = application.Context;
79
context.Response.Write("Test1Module:Application_AuthorizeRequest:<br>");
80
}
81
private void myResolveRequestCache(object source, EventArgs e)
82
{
83
HttpApplication application = (HttpApplication)source;
84
HttpContext context = application.Context;
85
context.Response.Write("Test1Module:Application_ResolveRequestCache:<br>");
86
}
87
private void myPreSendRequestHeaders(object source, EventArgs e)
88
{
89
HttpApplication application = (HttpApplication)source;
90
HttpContext context = application.Context;
91
context.Response.Write("Test1Module:Application_PreSendRequestHeaders:<br>");
92
}
93
private void myPreSendRequestContent(object source, EventArgs e)
94
{
95
HttpApplication application = (HttpApplication)source;
96
HttpContext context = application.Context;
97
context.Response.Write("Test1Module:Application_PreSendRequestContent:<br>");
98
}
99
public void Dispose()
100
{
101
}
102
}
103
}
然后在web.config里添加,不明白的看注释部分。
<httpModules>
<!--注意我这里的Httplibrary是你添加引用的那个DLL的文件名.Httplibrary.SecurityModules
中前边部分是你那个类的名称空间,后边的是你建的类的名字。-->
<add name=" Test1 " type="Httplibrary.SecurityModules,Httplibrary"/>
<add name=" MultiTest1 " type="HttpModuleTest1.Test1Module, HttpModuleTest1" />
<add name=" MultiTest2" type="HttpModuleTest2.Test2Module, HttpModuleTest2" />
</httpModules>
还是用刚才那个测试页面,我们就可以观察到两个test的执行顺序。
我们具体分析一下就是这样的:
HttpRequest开始->进入HttpModule->HttpModule->
首次截获HttpRequest->HttpModule.BeginRequest->
HttpModule.AuthorizeRequest->HttpModule.ResolveRequestCache->
初始化HttpHandler->建立HttpHandler控制点->HttpModule继续处理。HttpHandler已经建立,此后Session可用->HttpModule.AcquireRequestState
->HttpModule.PreRequestHandlerExecute->进入HttpHandler处理HttpRequest
-> HttpHandler->HttpHandler.ProcessRequest->返回HttpModule,HttpHandler结 束,Session失效->HttpModule.PostRequestHandlerExecute-> HttpModule.ReleaseRequestState->
HttpModule.UpdateRequestCache->HttpModule.EndRequest->HttpModule.PreSendRequestHeaders->HttpModule.PreSendRequestContent->
将处理的数据返回客户端,处理结束。
HttpHandler:
HttpHandler实现了ISAPI Extention的功能,他处理请求(Request)的信息和发送响应(Response)。HttpHandler功能的实现通过实现IHttpHandler接口来达到。
HTTP 处理程序是实现了System.Web.IHttpHandler接口的.NET组件。任何实现了IHttpHandler接口的类都可以用于处理输入的 HTTP请求。HTTP处理程序与ISAPI扩展有些类似。HTTP处理程序和ISAPI扩展的差别在于在URL中可以使用HTTP处理程序的文件名称直 接调用它们,与ISAPI扩展类似。
HttpHandler的实现,实现我们的HTTP处理程序包含以下步骤:
编写一个实现IHttpHandler接口的类。
在web.config或machine.config文件中注册这个处理程序。
在Internet服务管理器中把文件扩展(你想要处理的文件扩展名)映射到ASP.NETISAPI扩展DLL(aspnet_isapi.dll)上。
我们来看一个例子,打开IIS服务器,属性,主目录下有个配置,里面你就可以找到你的程序所执行文件所要调用的.dll文件。我们可以看到. aspx就是C:/WINDOWS/Microsoft.NET/Framework/v2.0.50727/aspnet_isapi.dll这个文件
来执行的。这里还可以添加你自己任意定义任意扩展名文件,定义了后你的服务器就可以认识这些人间,注意只是你的服务器,别人的不认识。这时候大家就会对网络上流行的各式各样的后缀名不奇怪了吧,可以自己定义的。
我们自己定义一个带.xxx后缀的。
添加一个类库,引用的相应的命名空间,
1
using System;
2
using System.Collections.Generic;
3
using System.Text;
4
using System.Web;
5
namespace MyHandler
6
{
7
public class NewHandler:IHttpHandler
8
{
9
public NewHandler()
10
{
11
// TODO: 此处添加构造逻辑
12
}
13
Implementation of IHttpHandler#region Implementation of IHttpHandler
14
/**//// <summary>
15
/// http处理程序的核心。我们调用这个方法来处理http请求。
16
/// </summary>
17
/// <param name="context"></param>
18
public void ProcessRequest(System.Web.HttpContext context)
19
{
20
HttpResponse objResponse = context.Response;
21
objResponse.Write("<html><body><h1>Hello xxx ! ");
22
objResponse.Write("</body></html>");
23
}
24
/**//// <summary>
25
/// 我们调用这个属性来决定http处理程序的实例是否可以用于处理相同其它类型的请求。
26
/// HTTP处理程序可以返回true或false来表明它们是否可以重复使用。
27
/// </summary>
28
public bool IsReusable
29
//
30
{
31
get
32
{
33
return true;
34
}
35
}
36
#endregion
37
}
38
}
然后再web.config里面配置相应节点:这里不懂的参考前边的,XXX就是我们刚才定义那个后缀名。
<httpHandlers>
<add verb="*" path="*.xxx"
type="MyHandler.NewHandler,MyHandler" />
</httpHandlers>
然后添加一个测试页面,就可以了。
HttpHandler之间的关系是这样的:
发送一个Http请求,然后判断是否存在自定义的HttpHandler,如果存在的话由自定义的HttpHandler处理Http请求,否则由系统默认的HttpHandler处理
Http请求。
在HttpHandler中访问Session:
不能直接通过HttpContext访问。
必须实现IRequiresSessionState接口。
IRequiresSessionState接口指定目标HTTP处理程序接口具有对会话状态值的读写访问权限。这是一个标记接口,没有任何方法。
怎样实现呢,我们还是来看例子吧:添加类库,引用相应的命名空间。
1
using System;
2
using System.Web;
3
using System.Web.SessionState;
4
namespace MyHandler
5
{
6
public class NewHandlerSession : IHttpHandler, IRequiresSessionState
7
{
8
public NewHandlerSession()
9
{
10
// TODO: 此处添加构造逻辑
11
}
12
Implementation of IHttpHandler#region Implementation of IHttpHandler
13
/**//// <summary>
14
/// http处理程序的核心。我们调用这个方法来处理http请求。
15
/// </summary>
16
/// <param name="context"></param>
17
public void ProcessRequest(System.Web.HttpContext context)
18
{
19
HttpResponse objResponse = context.Response;
20
HttpRequest objRequest = context.Request;
21
HttpSessionState objSession = context.Session;
22
objResponse.Write("欢迎使用自定义HttpHandler!<br>");
23
objSession["Test"] = "Session 测试!<br>";
24
objResponse.Write("Session的值为:" + objSession["Test"].ToString());
25
}
26
/**//// <summary>
27
/// 我们调用这个属性来决定http处理程序的实例是否可以用于处理相同其它类型的请求。
28
/// HTTP处理程序可以返回true或false来表明它们是否可以重复使用。
29
/// </summary>
30
public bool IsReusable
31
//
32
{
33
get
34
{
35
return true;
36
}
37
}
38
#endregion
39
}
40
}
然后配置Web.config的节点:
<httpHandlers>
<!--<add verb="*" path="*.xxx"
type="MyHandler.NewHandler,MyHandler" />-->
<add verb="*" path="*"
type="MyHandler.NewHandlerSession,MyHandlerSession" />
</httpHandlers>
这样就可以了。
这里还有一个定时器实现的例子。
ASP.NET事件模型机制:
ASP.NET之所以对于以前的ASP是一个革命性的巨变,在很大程度上是由于ASP.NET技术是一种完全基于事件驱动的全新技术。
在ASP.NET中事件的触发和处理分别是在客户端和服务器段进行的。
ASP.NET中,如果频繁和服务器进行事件信息的传递,会大大降低服务器的处理效率和性能,因而有些事件如OnMouseOver没有提供。
但提供了Change事件。为了提高效率它们被缓存在客户端。等到再一次事件信息被发送到服务器端时一同发送回去。
具体描述下这样的:首先客户请求WEB页。然后WEB服务寻找指令文件(.aspx),而这 时就是aspnet_isapi.dll这个动态连接库来处理。接着Asp.net代码被发送到公共语言运行时进行编译。接着HTML流返回给浏览器和 令。最后由浏览器处理HTML并显示页面。
什么是ISAPI呢?
在Internet时代的开端,客户端的需求非常有限;.htm文件就可以满足他们的需求。但是,随着时间的流逝,客户端需求的扩充超越了.htm文件或静态文件所包含的功能。
开 发者需要扩充或扩展Web服务器的功能。Web服务器厂商设计了不同的解决方案,但是都遵循同一个主题“向Web服务器插入某些组件”。所有的Web服务 器补充技术都允许开发者建立并插入组件以增强Web服务器的功能。微软公司提出了ISAPI(Internet服务器API),网景公司提出了NSAPI (网景服务器API)等等。ISAPI是一种重要的技术,它允许我们增强与ISAPI兼容的Web服务器(IIS就是一种与ISAPI兼容的Web服务 器)的能力。我们使用下面的组件达到这个目的:
1,ISAPI扩展:ISAPI扩展是使用Win32动态链接库来实现的。你可以把ISAPI扩展看作是一个普通的应用程序。ISAPI扩展的处理目标是http请求。
2,ISAPI过滤器:客户端每次向服务器发出请求的时候,请求要经过过滤器。客户端不需要在请求中指定过滤器,只需要简单地把请求发送给Web服务器,接着Web服务器把请求传递给相关的过滤器。接下来过滤器可能修改请求,执行某些登录操作等等。
ASP.NET请求的处理过程:
ASP.NET请求处理过程是基于管道模型的,在模型中ASP.NET把http请求传递给管道中的所 有模块。每个模块都接收http请求并有完全控制权限。模块可以用任何自认为适合的方式来处理请求。一旦请求经过了所有HTTP模块,就最终被HTTP处 理程序处理。HTTP处理程序对请求进行一些处理,并且结果将再次经过管道中HTTP模块。
ISAPI的筛选器:
IIS本身是不支持动态页面的,也就是说它仅仅支持静态html页面的内容,对于如.asp,.aspx,. cgi,.php等,IIS并不会处理这些标记,它就会把它当作文本,丝毫不做处理发送到客户端。为了解决这个问题。IIS有一种机制,叫做ISAPI的 筛选器,它是一个标准组件(COM组件)。
Asp.net服务在注册到IIS的时候,会把每个扩展可以处理的文件扩展名注册到IIS里面(如: *.ascx、*.aspx等)。扩展启动后,就根据定义好的方式来处理IIS所不能处理的文件,然后把控制权跳转到专门处理代码的进程中让这个进程开始 处理代码,生成标准的HTML代码,生成后把这些代码加入到原有的Html中,最后把完整的Html返回给IIS,IIS再把内容发送到客户端。
HttpModule:
HttpModule实现了ISAPI Filter的功能,是通过对IhttpModule接口的继承来处理。
HTTP模块是实现了System.Web.IhttpModule接口的.NET组件。这些组件通过在某些事件中注册自身,把自己插入ASP.NET请求处理管道。当这些事件发生的时候,ASP.NET调用对请求有兴趣的HTTP模块,这样该模块就能处理请求了。
HttpModule的实现:
1. 编写一个类,实现IhttpModule接口。
2. 实现Init 方法,并且注册需要的方法。
3. 实现注册的方法。
4. 实现Dispose方法,如果需要手工为类做一些清除工作,可以添加Dispose方法的实现,但这不是必需的,通常可以不为Dispose方法添加任何代码。
5. 在Web.config文件中,注册您编写的类。
下边我们来看例子,HttpModule的实现:
首先添加一个类库,然后在引用里引用System.Web和System.Security这两个命名空间。然后写个类,代码如下:
1
using System;
2
using System.Collections.Generic;
3
using System.Text;
4
using System.Web;
5
using System.Security.Principal;
6
namespace Httplibrary
7
{
8
public class SecurityModules : IHttpModule
9
{
10
public void Init(HttpApplication r_objApplication)
11
{
12
// 向Application 对象注册事件处理程序,核心部分。
13
r_objApplication.AuthenticateRequest += new EventHandler(this.AuthenticateRequest);
14
}
15
public void Dispose()
16
{
17
18
}
19
private void AuthenticateRequest(object r_objSender, EventArgs r_objEventArgs)
20
{
21
// 鉴别用户的凭证,并找出用户角色。
22
HttpApplication objApp = (HttpApplication)r_objSender;
23
HttpContext objContext = (HttpContext)objApp.Context;
24
if ((objApp.Request["userid"] == null) || (objApp.Request["password"] == null))
25
{
26
objContext.Response.Write("用户名和密码为空,验证失败!");
27
objContext.Response.End();
28
}
29
string userid = "";
30
userid = objApp.Request["userid"].ToString();
31
string password = "";
32
password = objApp.Request["password"].ToString();
33
string[] strRoles;
34
strRoles = AuthenticateAndGetRoles(userid, password);
35
if ((strRoles == null) || (strRoles.GetLength(0) == 0))
36
{
37
objContext.Response.Write("用户名或密码错误!");
38
objApp.CompleteRequest();//终止一个Http请求
39
40
}
41
GenericIdentity objIdentity = new GenericIdentity(userid, "CustomAuthentication");
42
objContext.User = new GenericPrincipal(objIdentity, strRoles);
43
}
44
private string[] AuthenticateAndGetRoles(string r_strUserID, string r_strPassword)
45
{
46
string[] strRoles = null;
47
if ((r_strUserID.Equals("Zhangsan")) && (r_strPassword.Equals("111")))
48
{
49
strRoles = new String[1];
50
strRoles[0] = "Administrator";
51
}
52
else if ((r_strUserID.Equals("Lisi")) && (r_strPassword.Equals("222")))
53
{
54
strRoles = new string[1];
55
strRoles[0] = "User";
56
}
57
return strRoles;
58
}
59
}
60
}
编译一下,下边做测试页面,很简单,放一个label,text=“测试页面”如果成功则显示测试页面。然后在web.config里面配置,这里很重要。添加 注意注释部分。
<httpModules>
<!--注意我这里的Httplibrary是你添加引用的那个DLL的文件名.Httplibrary.SecurityModules
中前边部分是你那个类的名称空间,后边的是你建的类的名字。-->
<add name=" Test1 " type="Httplibrary.SecurityModules,Httplibrary"/>
</httpModules>
然后添加 这个节点,这个大家应该都能明白。
<authorization>
<deny users="?"/>
</authorization>
然 后启动测试页面。刚启动开始后页面一定显示“用户名和密码为空,验证失败!”呵呵,别忘记了咱们这就是目的,然后在你的地址栏后边添加?userid= Zhangsan&password=111这行字。然后就会显示“测试页面”这几个字。大家可以多输入几个名字单步调试一下就明白了。
WebConfig设置
<httpModules>
<add type=“classname,assemblyname”
name=“modulename”/>
<remove name=“modulename”/>
<clear/>
</httpModules>
子标记说明:
<add>将HttpModule 类添加到应用程序。请注意,如果以前已指定了相同的谓词/路径组合(例如在父目录的Web.config 文件中),则对的第二个调用将重写以前的设置。
<remove>从应用程序移除HttpModule 类。
<clear>从应用程序移除所有HttpModule 映射。
深入研究HttpModule
HttpModule通过对HttpApplication对象的一系列事件的处理来对HTTP处理管道施加影响,这些事件在HttpModule的Init方法中进行注册,包括:
BeginRequest
AuthenticateRequest
AuthorizeRequest
ResolveRequestCache
AcquireRequestState
PreRequestHandlerExecute
PostRequestHandlerExecute
ReleaseRequestState
UpdateRequestCache
EndRequest
我们都可以对以上事件进行重新定义,注意时重新定义不时覆盖。我们看一个例子,多个HttpModule的实现,建立两个类库,什么都相同就是类名不相同,引入相应的命名空间后我们编写这个类,代码如下:
1
using System;
2
using System.Collections.Generic;
3
using System.Text;
4
using System.Web;
5
namespace HttpModuleTest1
6
{
7
public class Test1Module:IHttpModule
8
{
9
public Test1Module()
10
{
11
}
12
public string ModuleName
13
{
14
get
15
{
16
return "Test1Module";
17
}
18
}
19
public void Init(HttpApplication application)
20
{
21
application.BeginRequest += new EventHandler(myBeginRequest);
22
application.EndRequest += new EventHandler(myEndRequest);
23
application.PreRequestHandlerExecute += new EventHandler(myPreRequestHandlerExecute);
24
application.PostRequestHandlerExecute += new EventHandler(myPostRequestHandlerExecute);
25
application.ReleaseRequestState += new EventHandler(myReleaseRequestState);
26
application.AcquireRequestState += new EventHandler(myAcquireRequestState);
27
application.AuthenticateRequest += new EventHandler(myAuthenticateRequest);
28
application.AuthorizeRequest += new EventHandler(myAuthorizeRequest);
29
application.ResolveRequestCache += new EventHandler(myResolveRequestCache);
30
application.PreSendRequestHeaders += new EventHandler(myPreSendRequestHeaders);
31
application.PreSendRequestContent += new EventHandler(myPreSendRequestContent);
32
}
33
private void myBeginRequest(object source, EventArgs e)
34
{
35
HttpApplication application = (HttpApplication)source;
36
HttpContext context = application.Context;
37
context.Response.Write("Test1Module:Beggining of Request<br>");
38
}
39
private void myEndRequest(object source, EventArgs e)
40
{
41
HttpApplication application = (HttpApplication)source;
42
HttpContext context = application.Context;
43
context.Response.Write("Test1Module:End of Request<br>");
44
}
45
private void myPreRequestHandlerExecute(object source, EventArgs e)
46
{
47
HttpApplication application = (HttpApplication)source;
48
HttpContext context = application.Context;
49
context.Response.Write("Test1Module:Application_RequestHandlerExecute:<br>");
50
}
51
private void myPostRequestHandlerExecute(object source, EventArgs e)
52
{
53
HttpApplication application = (HttpApplication)source;
54
HttpContext context = application.Context;
55
context.Response.Write("Test1Module:Application_PostRequestHandlerExecute:<br>");
56
}
57
private void myReleaseRequestState(object source, EventArgs e)
58
{
59
HttpApplication application = (HttpApplication)source;
60
HttpContext context = application.Context;
61
context.Response.Write("Test1Module:Application_ReleaseRequestState:<br>");
62
}
63
private void myAcquireRequestState(object source, EventArgs e)
64
{
65
HttpApplication application = (HttpApplication)source;
66
HttpContext context = application.Context;
67
context.Response.Write("Test1Module:Application_ReleaseRequestState:<br>");
68
}
69
private void myAuthenticateRequest(object source, EventArgs e)
70
{
71
HttpApplication application = (HttpApplication)source;
72
HttpContext context = application.Context;
73
context.Response.Write("Test1Module:Application_AuthenticateRequest:<br>");
74
}
75
private void myAuthorizeRequest(object source, EventArgs e)
76
{
77
HttpApplication application = (HttpApplication)source;
78
HttpContext context = application.Context;
79
context.Response.Write("Test1Module:Application_AuthorizeRequest:<br>");
80
}
81
private void myResolveRequestCache(object source, EventArgs e)
82
{
83
HttpApplication application = (HttpApplication)source;
84
HttpContext context = application.Context;
85
context.Response.Write("Test1Module:Application_ResolveRequestCache:<br>");
86
}
87
private void myPreSendRequestHeaders(object source, EventArgs e)
88
{
89
HttpApplication application = (HttpApplication)source;
90
HttpContext context = application.Context;
91
context.Response.Write("Test1Module:Application_PreSendRequestHeaders:<br>");
92
}
93
private void myPreSendRequestContent(object source, EventArgs e)
94
{
95
HttpApplication application = (HttpApplication)source;
96
HttpContext context = application.Context;
97
context.Response.Write("Test1Module:Application_PreSendRequestContent:<br>");
98
}
99
public void Dispose()
100
{
101
}
102
}
103
}
然后在web.config里添加,不明白的看注释部分。
<httpModules>
<!--注意我这里的Httplibrary是你添加引用的那个DLL的文件名.Httplibrary.SecurityModules
中前边部分是你那个类的名称空间,后边的是你建的类的名字。-->
<add name=" Test1 " type="Httplibrary.SecurityModules,Httplibrary"/>
<add name=" MultiTest1 " type="HttpModuleTest1.Test1Module, HttpModuleTest1" />
<add name=" MultiTest2" type="HttpModuleTest2.Test2Module, HttpModuleTest2" />
</httpModules>
还是用刚才那个测试页面,我们就可以观察到两个test的执行顺序。
我们具体分析一下就是这样的:
HttpRequest开始->进入HttpModule->HttpModule->
首次截获HttpRequest->HttpModule.BeginRequest->
HttpModule.AuthorizeRequest->HttpModule.ResolveRequestCache->
初始化HttpHandler->建立HttpHandler控制点->HttpModule继续处理。HttpHandler已经建立,此后Session可用->HttpModule.AcquireRequestState
->HttpModule.PreRequestHandlerExecute->进入HttpHandler处理HttpRequest
-> HttpHandler->HttpHandler.ProcessRequest->返回HttpModule,HttpHandler结 束,Session失效->HttpModule.PostRequestHandlerExecute-> HttpModule.ReleaseRequestState->
HttpModule.UpdateRequestCache->HttpModule.EndRequest->HttpModule.PreSendRequestHeaders->HttpModule.PreSendRequestContent->
将处理的数据返回客户端,处理结束。
HttpHandler:
HttpHandler实现了ISAPI Extention的功能,他处理请求(Request)的信息和发送响应(Response)。HttpHandler功能的实现通过实现IHttpHandler接口来达到。
HTTP 处理程序是实现了System.Web.IHttpHandler接口的.NET组件。任何实现了IHttpHandler接口的类都可以用于处理输入的 HTTP请求。HTTP处理程序与ISAPI扩展有些类似。HTTP处理程序和ISAPI扩展的差别在于在URL中可以使用HTTP处理程序的文件名称直 接调用它们,与ISAPI扩展类似。
HttpHandler的实现,实现我们的HTTP处理程序包含以下步骤:
编写一个实现IHttpHandler接口的类。
在web.config或machine.config文件中注册这个处理程序。
在Internet服务管理器中把文件扩展(你想要处理的文件扩展名)映射到ASP.NETISAPI扩展DLL(aspnet_isapi.dll)上。
我们来看一个例子,打开IIS服务器,属性,主目录下有个配置,里面你就可以找到你的程序所执行文件所要调用的.dll文件。我们可以看到. aspx就是C:/WINDOWS/Microsoft.NET/Framework/v2.0.50727/aspnet_isapi.dll这个文件
来执行的。这里还可以添加你自己任意定义任意扩展名文件,定义了后你的服务器就可以认识这些人间,注意只是你的服务器,别人的不认识。这时候大家就会对网络上流行的各式各样的后缀名不奇怪了吧,可以自己定义的。
我们自己定义一个带.xxx后缀的。
添加一个类库,引用的相应的命名空间,
1
using System;
2
using System.Collections.Generic;
3
using System.Text;
4
using System.Web;
5
namespace MyHandler
6
{
7
public class NewHandler:IHttpHandler
8
{
9
public NewHandler()
10
{
11
// TODO: 此处添加构造逻辑
12
}
13
Implementation of IHttpHandler#region Implementation of IHttpHandler
14
/**//// <summary>
15
/// http处理程序的核心。我们调用这个方法来处理http请求。
16
/// </summary>
17
/// <param name="context"></param>
18
public void ProcessRequest(System.Web.HttpContext context)
19
{
20
HttpResponse objResponse = context.Response;
21
objResponse.Write("<html><body><h1>Hello xxx ! ");
22
objResponse.Write("</body></html>");
23
}
24
/**//// <summary>
25
/// 我们调用这个属性来决定http处理程序的实例是否可以用于处理相同其它类型的请求。
26
/// HTTP处理程序可以返回true或false来表明它们是否可以重复使用。
27
/// </summary>
28
public bool IsReusable
29
//
30
{
31
get
32
{
33
return true;
34
}
35
}
36
#endregion
37
}
38
}
然后再web.config里面配置相应节点:这里不懂的参考前边的,XXX就是我们刚才定义那个后缀名。
<httpHandlers>
<add verb="*" path="*.xxx"
type="MyHandler.NewHandler,MyHandler" />
</httpHandlers>
然后添加一个测试页面,就可以了。
HttpHandler之间的关系是这样的:
发送一个Http请求,然后判断是否存在自定义的HttpHandler,如果存在的话由自定义的HttpHandler处理Http请求,否则由系统默认的HttpHandler处理
Http请求。
在HttpHandler中访问Session:
不能直接通过HttpContext访问。
必须实现IRequiresSessionState接口。
IRequiresSessionState接口指定目标HTTP处理程序接口具有对会话状态值的读写访问权限。这是一个标记接口,没有任何方法。
怎样实现呢,我们还是来看例子吧:添加类库,引用相应的命名空间。
1
using System;
2
using System.Web;
3
using System.Web.SessionState;
4
namespace MyHandler
5
{
6
public class NewHandlerSession : IHttpHandler, IRequiresSessionState
7
{
8
public NewHandlerSession()
9
{
10
// TODO: 此处添加构造逻辑
11
}
12
Implementation of IHttpHandler#region Implementation of IHttpHandler
13
/**//// <summary>
14
/// http处理程序的核心。我们调用这个方法来处理http请求。
15
/// </summary>
16
/// <param name="context"></param>
17
public void ProcessRequest(System.Web.HttpContext context)
18
{
19
HttpResponse objResponse = context.Response;
20
HttpRequest objRequest = context.Request;
21
HttpSessionState objSession = context.Session;
22
objResponse.Write("欢迎使用自定义HttpHandler!<br>");
23
objSession["Test"] = "Session 测试!<br>";
24
objResponse.Write("Session的值为:" + objSession["Test"].ToString());
25
}
26
/**//// <summary>
27
/// 我们调用这个属性来决定http处理程序的实例是否可以用于处理相同其它类型的请求。
28
/// HTTP处理程序可以返回true或false来表明它们是否可以重复使用。
29
/// </summary>
30
public bool IsReusable
31
//
32
{
33
get
34
{
35
return true;
36
}
37
}
38
#endregion
39
}
40
}
然后配置Web.config的节点:
<httpHandlers>
<!--<add verb="*" path="*.xxx"
type="MyHandler.NewHandler,MyHandler" />-->
<add verb="*" path="*"
type="MyHandler.NewHandlerSession,MyHandlerSession" />
</httpHandlers>
这样就可以了。
这里还有一个定时器实现的例子。
ASP.NET事件模型机制:
ASP.NET之所以对于以前的ASP是一个革命性的巨变,在很大程度上是由于ASP.NET技术是一种完全基于事件驱动的全新技术。
在ASP.NET中事件的触发和处理分别是在客户端和服务器段进行的。
ASP.NET中,如果频繁和服务器进行事件信息的传递,会大大降低服务器的处理效率和性能,因而有些事件如OnMouseOver没有提供。
但提供了Change事件。为了提高效率它们被缓存在客户端。等到再一次事件信息被发送到服务器端时一同发送回去。
相关文章推荐
- .NET/ASP.NET Routing路由(深入解析路由系统架构原理)
- .NET/ASP.NET Routing路由(深入解析路由系统架构原理)
- 深入解析ASP.NET架构
- [ASP.NET学习笔记之十六]深入解析ASP.NET架构
- 深入解析ASP.NET架构
- .NET/ASP.NET Routing路由(深入解析路由系统架构原理)
- 深入解析ASP.NET架构
- 第二十九讲 深入解析ASP.NET架构
- 从零开始学习 ASP.NET MVC 1.0 (三) Controller/Action 深入解析与应用实例 【转】
- .NET/ASP.NETMVC Controller 控制器(一:深入解析控制器运行原理)
- ASP.NET 3.5 MVC 架构与实战笔记6 HtmlHelper控件解析
- .NET/ASP.NET MVC Controller 控制器(深入解析控制器运行原理)
- 什么是asp.net ---对asp.net架构的初次解析
- 从零开始学习 ASP.NET MVC 1.0 (三) Controller/Action 深入解析与应用实例
- 深入剖析微软ASP.NET Ajax中的数据绑定架构上篇之二
- asp.net mvc 项目架构解析
- ASP.NET MVC架构与实战系列之三:MVC控件解析
- 深入解析javascript与asp.net对Cookie操作的异同,以及如何共用(一)。
- 开始读《道不远人--深入解析ASP.NET 2.0控件开发>>
- 【翻译】深入解析Web服务器和ASP.NET应用程序生命周期