先来分析asp.net处理一个web请求的过程。学习asp.net技术,除了翻看人家的文档(这是最基本的,知识就是知识,不懂的基本知识无法深入学习),还应当自己学会琢磨,动手实习。
当我们从客户端发出一个web请求后,到达web服务器,由web服务器处理或者转给asp.net框架处理。如果不存在web服务器(采用asp.net的缺省web处理),那你可以参鄙人的《CASSINI源代码分析》http://blog.csdn.net/shanhe/archive/2004/11/10/176422.aspx和 《实现自己的ASP.NET宿主系统》http://blog.csdn.net/shanhe/archive/2004/05/27/5429.aspx。
假设请求到了asp.net的框架,系统回怎么处理呢?
Asp.net系统框架自身有一个http处理的逻辑。这个逻辑由machine.config的 名为httpRuntime的节指定
<httpHandlers>。。。</httpHandlers>
告诉asp.net框架一个应用程序的http处理程序缺省情况下该如何决定处理逻辑。所谓如何处理是指http 谓词(Verb)和资源的位置(Path)组合决定的请求的处理。
例如:
<add
verb="*"
path="*.aspx"
type="System.Web.UI.PageHandlerFactory" />
告诉asp.net在处理任何”.aspx”的文件的任何请求(post/get/head/put)时候都应该使用System.Web.UI.PageHandlerFactory类处理请求。这个类是系统框架缺省类,遵循System.Web.IhttpHandler接口(但是由MS官方实现)。如果你在研究透aspx页框架后,你可以自己写一个aspx页工厂处理程序,签名后加入全局应用程序,再修改此处即可让aspx页面没处理时是按照自己实现的逻辑进行(你甚至可以不遵循页面控件实现逻辑,虽然那样并无太大意义)。
我们来做个实验:我们利用浏览器发出对.config文件的请求(譬如web.config),却省情况下asp.net会报告错误,但是假若我们删除machine.config中的
<add
verb="*"
path="*.config"
type="System.Web.HttpForbiddenHandler" />
并保存。重新请求该文件后,那么会看到浏览器可以读取到此文件并可显示。重新加上该节,重新请求会看到系统报告错误。这充分说明了http处理工厂是根据配置文件进行处理的。据此类推,我们可以阅读machine.config的其他相关配直节,充分理解系统缺省处理逻辑是如何处理web请求(具体为合法的http请求)的。另外,web.config也可以据此增加/删除指定http处理程序。参考MSDN,我们发现,任何一个HTTP处理程序实际上是实现了System.Web.IhttpHandler接口的asp.net类。接口应当实现一个属性和一个借口方法:
公共属性
IsReusable 获取一个值,该值指示其他请求是否可以使用 IHttpHandler 实例。决定了此处理程序是否可以重用(通常克服用意味着系统性能的提高)
公共方法
ProcessRequest 通过实现 IHttpHandler 接口的自定义 HttpHandler 启用 HTTP Web 请求的处理。也就是处理实现。
假设我们写好了一个http处理程序,如何让他发挥作用呢?譬如,我们需要禁止asp.net下载.info文件,我们应该进行如下处理:
第一步,在web服务器上增加指示,让asp.net处理此扩展名。具体为:
打开IIS(假设web服务器是IIS),找到应用程序,配置,应用程序映射,添加映射,在可执行文件中输入当前.net版本的aspnet_isapi.dll(如C:\WINNT\Microsoft.NET\Framework\v1.0.3705\aspnet_isapi.dll),扩展名输入.info,谓词全部,检查文件是否存在。经过这些步骤,确保IIS不会自作多情处理.info文件,而让给aspnet_isapi.dll处理,后者则会将请求交给asp.net进行处理。
第二步,在machine.config或者web.config中加入相映配置节。都是在<System.Web〉中的加入<httphandler>子节,按照格式指定,譬如:
<httphandlers>
…
<add verb=”*” path=”*.info” type=” System.Web.HttpForbiddenHandler”>
…
</httphandlers>
经过上述节配置,.info文件会被保护起来,任何企图访问都会被告知“无法提供此类型的页。”;如果换成你自己的类,则被asp.net框架所调用来处理.info请求。
下面来实现一个http处理程序例子,我们增加一个扩展名.img,img文件根据参数生成一个图片,譬如我们向asp.net框架请求 abc.img,那么系统返回content为image/jpg格式的图片,图片内容为abc
源代码如下:
using System;
using System.Web ;
using System.Drawing;
using System.Drawing.Drawing2D ;
using System.Drawing.Imaging ;
namespace ImyWeb
{
public class IMG : System.Web.IHttpHandler
{
public IMG()
{}
public bool IsReusable
{
get{ return true;}
}
public void ProcessRequest(HttpContext context)
{
string vstr=_getViewString(context);
context.Response.ContentType ="image/jpeg";
Image img=new Bitmap(128,128,PixelFormat.Format32bppArgb );
Graphics g=Graphics.FromImage(img);
Brush backBrush=new SolidBrush(Color.Gray ); //灰色
Brush textBrush=new SolidBrush(Color.Black );
g.FillRectangle(backBrush,0,0,128,128);
Font ft=new Font( "Arial",32);
g.DrawString(vstr,ft,textBrush,new RectangleF(0,0,128,128),new StringFormat(StringFormatFlags.NoWrap ));
img.Save(context.Response.OutputStream,ImageFormat.Jpeg );
context.Response .Flush();
backBrush.Dispose();
textBrush.Dispose();
g.Dispose();
img.Dispose();
return ;
}
//************//
private string _getViewString(HttpContext context)
{
string str= context.Request.RawUrl ;
int l1=str.LastIndexOf("/");
int l2=str.LastIndexOf(".");
return str.Substring(l1+1,l2-l1-1);
}
}
}
编译后,得到应用程序为myHttpHandler.dll。
现在,我们需要告诉asp.net应用程序(假设我们的web应用程序在localHost/webApp1下),如何处理.img文件了:
第一步,在web服务器上增加指示,让asp.net处理此.img的扩展名(让IIS歇着吧,不要插手asp.net的事了,让asp.net处理*.img了)
第二,在web.config中的<system.web>节中增加:
<httpHndlers>
<add verb="*" path="*.img" type="IBuySpy.IMG,IMGHttphandler" />
</httpHndlers>
为了能够让asp.net程序能够定位到应用程序集,将myHttpHandler.dll拷贝到web应用程序的bin目录
接下来,我们测试:在测试的web应用程序WebApp1下随意请求一个.img的资源,将会得到一个jpg图片。http://localhost/WebApp1/test.img