ASPNET核心对象要点.docx

上传人:b****0 文档编号:17615703 上传时间:2023-07-27 格式:DOCX 页数:23 大小:88.81KB
下载 相关 举报
ASPNET核心对象要点.docx_第1页
第1页 / 共23页
ASPNET核心对象要点.docx_第2页
第2页 / 共23页
ASPNET核心对象要点.docx_第3页
第3页 / 共23页
ASPNET核心对象要点.docx_第4页
第4页 / 共23页
ASPNET核心对象要点.docx_第5页
第5页 / 共23页
ASPNET核心对象要点.docx_第6页
第6页 / 共23页
ASPNET核心对象要点.docx_第7页
第7页 / 共23页
ASPNET核心对象要点.docx_第8页
第8页 / 共23页
ASPNET核心对象要点.docx_第9页
第9页 / 共23页
ASPNET核心对象要点.docx_第10页
第10页 / 共23页
ASPNET核心对象要点.docx_第11页
第11页 / 共23页
ASPNET核心对象要点.docx_第12页
第12页 / 共23页
ASPNET核心对象要点.docx_第13页
第13页 / 共23页
ASPNET核心对象要点.docx_第14页
第14页 / 共23页
ASPNET核心对象要点.docx_第15页
第15页 / 共23页
ASPNET核心对象要点.docx_第16页
第16页 / 共23页
ASPNET核心对象要点.docx_第17页
第17页 / 共23页
ASPNET核心对象要点.docx_第18页
第18页 / 共23页
ASPNET核心对象要点.docx_第19页
第19页 / 共23页
ASPNET核心对象要点.docx_第20页
第20页 / 共23页
亲,该文档总共23页,到这儿已超出免费预览范围,如果喜欢就下载吧!
下载资源
资源描述

ASPNET核心对象要点.docx

《ASPNET核心对象要点.docx》由会员分享,可在线阅读,更多相关《ASPNET核心对象要点.docx(23页珍藏版)》请在冰点文库上搜索。

ASPNET核心对象要点.docx

ASPNET核心对象要点

浅谈ASP.NET核心对象

想当初在只使用WebForms框架并以服务端为中心的开发模式时,发现ASP.NET好复杂。

一大堆服务端控件,各有各的使用方法,有些控件的事件也很重要,必须在合适地时机去响应,还真有些复杂。

后来逐渐发现这些复杂的根源其实就是服务器控件相关的抽象逻辑。

随着Ajax越用越多,可能有些人也做过这些事情:

【新建一个ashx文件,读取一些用户的输入数据,Form,QueryString,然后调用业务逻辑代码,将处理后的结果序列化成JSON字符串再发给客户端】,这样也能完成一次请求。

不知大家有没有做过这类事情,反正我是做过的。

慢慢地,我也嫌烦了,这些事情中除了调用业务逻辑部分,都是些体力活嘛。

于是想,写点代码把这些事情交给它们去做吧,我只处理与请求有关的数据处理就好了。

终于,我写了个简陋的框架,并自称为【我的Ajax服务端框架】以及【我的MVC框架】。

写完这些东西后,发现ASP.NET的东西变少了,但是仍可以实现很多功能。

其实,我们可以从另一角度来看ASP.NET,它就是一个底层框架平台,它负责接收HTTP请求(从IIS传入),将请求分配给一个线程,再把请求放到它的处理管道中,由一些其它的【管道事件订阅者】来处理它们,最后将处理结果返回给客户端。

而WebForms或者MVC框架,都属于ASP.NET平台上的【管道事件订阅者】而已,WebService也是哦。

如果你不想受限于WebForms或者MVC框架,或者您还想用ASP.NET做点其它的事情,比如:

自己的服务框架,就像WebService那样。

但希望用其它更简单的序列化方式来减少网络流量,或者还有加密要求。

那么了解ASP.NET提供了哪些功能就很有必要了。

本文将站在ASP.NET平台的角度,来看看ASP.NET的一些基础功能。

虽然不会涉及任何其它上层框架,但所讲述的内容其实是适合其它上层框架的。

前面我说到:

ASP.NET负责接收请求,并将请求分配给一个线程来执行。

最终执行什么呢?

当然就是我们的处理逻辑。

但我们在处理时,用户输入的数据又是从哪里来的呢?

只能是HTTP请求。

但它又可分为二个部分:

请求头和请求体。

在ASP.NET中,我们并不需要去分析请求头和请求体,比如:

我们可以直接访问QueryString,Form就可以得到用户传过来的数据了,然而QueryString其实是放在请求头上,在请求头上的还有Cookie,Form以及PostFile则放在请求体中。

如果对这些内容不清楚的可以参考我的博客:

【细说Cookie】和【细说Form(表单)】。

在我这二篇博客中,您应该可以看出:

要是让您从请求头请求体中读取这些数据,还是很麻烦的。

幸好,ASP.NET做为底层平台,在每次处理请求时,都将这些数据转成方便我们处理的对象了。

今天我将只谈这些基础对象以及它们可以实现的功能。

在我的眼里,ASP.NET有三大核心对象:

HttpContext,HttpRequest,HttpResponse。

除此之外,还有二个对象虽然称不上核心,但仍然比较重要:

HttpRuntime,HttpServerUtility

事实上,这些类的实例在其它的一些类型中也经常被引用到,从出现的频率也可以看出它们的重要性。

中国人喜欢把较重要的东西放在最后,做为压轴出场。

今天我也将按照这个风俗习惯做为这些对象的出场顺序来分别说说它们有哪些【重要的功能】。

HttpRuntime

第一个出场的是HttpRuntime,其实这个对象算是整个ASP.NET平台最核心的对象,从名字可以看出它的份量。

但它包含的很多方法都不是public类型的,它在整个请求的处理过程中,做了许多默默无闻但非常重要的工作。

反而公开的东西并不多,因此需要我们掌握的东西也较少。

不能让它做为压轴出场就让它第一个出场吧。

这就是我的想法。

HttpRuntime公开了一个方法静态UnloadAppDomain(),这个方法可以让我们用代码重新启动网站。

通常用于用户通过程序界面修改了一个比较重要的参数,这时需要重启程序了。

HttpRuntime还公开了一个大家都熟知的静态属性Cache。

可能有些人认为他/她在使用Page.Cache或者HttpContext.Cache,事实上后二个属性都是HttpRuntime.Cache的【快捷方式】。

HttpRuntime.Cache是个非常强大的东西,主要用于缓存一些数据对象,提高程序性能。

虽然缓存实现方式比较多,一个static变量也算是能起到缓存的作用,但HttpRuntime.Cache的功能绝不仅限于一个简单的缓存集合,如果说实现“缓存项的滑动过期和绝对过期”算是小儿科的话,缓存依赖的功能应该可以算是个强大的特性吧。

更有意义的是:

它缓存的内容还可以在操作系统内存不足时能将一些缓存项释放(可指定优先级),从而获得那些对象的内存,并能在移除这些缓项时能通知您的代码。

可能有人认为当内存不足时自动释放一些缓存对象容易啊,使用WeakReference类来包装一下就可以了。

但WeakReference不提供移除时的通知功能。

HttpRuntime.Cache还有个非常酷的功能是:

它并非只能在ASP.NET环境中使用,也能在其它编程模型中使用,比如大家熟知的WinForm编程模型。

如何使用呢,直接访问HttpRuntime.Cache这个静态属性肯定是不行的。

我们只要在程序初始化时创建一个HttpRuntime的实例,当然还要保证它不会被GC回收掉。

然后就可以像在ASP.NET中一样使用HttpRuntime.Cache了,就这么简单。

是的,就是这样简单,您就可以在其它编程模型中使用Cache的强大功能:

线程安全的集合,2种过期时间的选择,缓存依赖,内存不足时自动释放且有回调通知。

这里我还想说说缓存依赖。

我曾经见过一个使用场景:

有人从一堆文件(分为若干类别)中加载数据到Cache中,但是他为了想在这些数据文件修改时能重新加载,而采用创建线程并轮询文件的最后修改时间的方式来实现,总共开了60多个线程,那些线程每隔15去检查各自所“管辖”的文件是否已修改。

如果您也是这样处理的,我今天就告诉您:

真的没必要这么复杂,您只要在添加缓存项时创建一个CacheDependency的实例并调用相应的重载方法就可以了。

具体CacheDependency有哪些参数,您还是参考一下MSDN吧。

这里我只告诉您:

它能在一个文件或者目录,或者多个文件在修改时,自动通知Cache将缓存项清除,而且还可以设置到依赖其它的缓存项,甚至能将这些依赖关系组合使用,非常强大。

可能还有人会担心往Cache里放入太多的东西会不会影响性能,因此有人还想到控制缓存数量的办法。

我只想说:

缓存容器决定一个对象的保存位置是使用Hash算法的,并不会因为缓存项变多而影响性能,更有趣的是ASP.NET的Cache的容器还并非只有一个,它能随着CPU的数量而调整,看这个架式,应该在设计Cache时还想到了高并发访问的性能问题。

如果这时你还在统计缓存数量并手工释放某些缓存项,我只能说您在写损害性能的代码。

HttpServerUtility,HttpUtility

不要觉得奇怪,这次我一下子请了二个对象出场了。

由于HttpServerUtility的实例通常以Server的属性公开,但它的提供一些Encode,Decode方法其实调用的是HttpUtility类的静态方法。

所以我就把它们俩一起请出来了。

HttpUtility公开了一些静态方法,如:

HtmlEncode(),应该是使用频率比较高的方法,用于防止注入攻击,它负责安全地生成一段HTML代码。

有时我们还需要生成一个URL,那么UrlEncode()方法就能派上用场了,因为URL中并不能包含所有字符,所以要做相应的编码。

HttpUtility还有一个方法HtmlAttributeEncode(),它也是用于防止注入攻击,安全地输出一个HTML属性。

在.net4中,HttpUtility还提供了另一个方法:

JavaScriptStringEncode(),也是为了防止注入攻击,安全地在服务端输出一段JS代码。

HttpUtility还公开了一些静态方法,如:

HtmlDecode(),UrlDecode(),通常来说,我们并不需要使用它们。

尤其是UrlDecode,除非您要自己的框架,一般来说,在我们访问QueryString,Form时,已经做过UrlDecode了,您就不用再去调用了。

HttpServerUtility除了公开了比较常用的Encode,Decode方法外,还公开了一个非常有用的方法:

Execute(),是的,它非常有用,尤其是您需要在服务端获取一个页面或者用户控件的HTML输出时。

如果您对这个功能有兴趣可以参考我的博客:

【我的Ajax服务端框架-(4)JS直接请求ascx用户控件】

HttpRequest

现在总算轮到第一个核心对象出场了。

MSDN给它作了一个简短的解释:

“使ASP.NET能够读取客户端在Web请求期间发送的HTTP值。

这个解释还算是到位的。

HttpRequest的实例包含了所有来自客户端的所有数据,我们可以把这些数据看成是输入数据,Handler以及Module就相当于是处理过程,HttpResponse就是输出了。

在HttpRequest包含的所有输入数据中,有我们经常使用的QueryString,Form,Cookie,它还允许我们访问一些HTTP请求头、浏览器的相关信息、请求映射的相关文件路径、URL详细信息、请求的方法、请求是否已经过身份验证,是否为SSL等等。

HttpRequest的公开属性绝大部分都是比较重要的,这里就简单地列举一下吧。

// 获取服务器上 ASP.NET 应用程序的虚拟应用程序根路径。

 

public string ApplicationPath { get;} 

// 获取应用程序根的虚拟路径,并通过对应用程序根使用波形符 (~) 表示法(例如,以“~/page.aspx”的形式)使该路径成为相对路径。

 

public string AppRelativeCurrentExecutionFilePath { get;} 

// 获取或设置有关正在请求的客户端的浏览器功能的信息。

 

public HttpBrowserCapabilities Browser { get;set;} 

// 获取客户端发送的 cookie 的集合。

 

public HttpCookieCollection Cookies { get;} 

// 获取当前请求的虚拟路径。

 

public string FilePath { get;} 

// 获取采用多部分 MIME 格式的由客户端上载的文件的集合。

 

 public HttpFileCollection Files { get;} 

// 获取或设置在读取当前输入流时要使用的筛选器。

 

public Stream Filter { get;set;} 

// 获取窗体变量集合。

 

public NameValueCollection Form { get;} 

// 获取 HTTP 头集合。

 

public NameValueCollection Headers { get;} 

// 获取客户端使用的 HTTP 数据传输方法(如 GET、POST 或 HEAD)。

 

public string HttpMethod { get;} 

// 获取传入的 HTTP 实体主体的内容。

 

public Stream InputStream { get;} 

// 获取一个值,该值指示是否验证了请求。

 

public bool IsAuthenticated { get;} 

// 获取当前请求的虚拟路径。

 

public string Path { get;} 

// 获取 HTTP 查询字符串变量集合。

 

 public NameValueCollection QueryString { get;} 

// 获取当前请求的原始 URL。

 

public string RawUrl { get;} 

// 获取有关当前请求的 URL 的信息。

 

public Uri Url { get;} 

// 从 QueryString、Form、Cookies 或 ServerVariables 集合中获取指定的对象。

 

public string this[string key] { get;} 

// 将指定的虚拟路径映射到物理路径。

 

// 参数:

 virtualPath:

 当前请求的虚拟路径(绝对路径或相对路径)。

 

// 返回结果:

 由 virtualPath 指定的服务器物理路径。

 

public string MapPath(string virtualPath); 

下面我来说说一些不被人注意的细节。

HttpRequest的QueryString,Form属性的类型都是NameValueCollection,它个集合类型有一个特点:

允许在一个键下存储多个字符串值。

以下代码演示了这个特殊的现象:

protected void Page_Load(object sender, EventArgs e) 

string[] allkeys = Request.QueryString.AllKeys; 

if( allkeys.Length == 0 ) 

Response.Redirect( 

Request.RawUrl + "?

aa=1&bb=2&cc=3&aa=" + HttpUtility.UrlEncode("5,6,7"), true); 

StringBuilder sb = new StringBuilder(); 

foreach( string key in allkeys ) 

sb.AppendFormat("{0} = {1}", 

HttpUtility.HtmlEncode(key), HttpUtility.HtmlEncode(Request.QueryString[key])); 

this.labResult.Text = sb.ToString(); 

页面最终显示结果如下(注意键值为aa的结果):

说明:

1.HttpUtility.ParseQueryString(string)这个静态方法能帮助我们解析一个URL字符串,返回的结果也是NameValueCollection类型。

2.NameValueCollection是一个不区分大小写的集合。

HttpRequest有一个Cookies属性,MSDN给它的解释是:

“获取客户端发送的Cookie的集合。

”,这次MSDN的解释就不完全准确了。

请看如下代码:

protected void Page_Load(object sender, EventArgs e) 

string key = "Key1"; 

HttpCookie c = new HttpCookie(key, DateTime.Now.ToString()); 

Response.Cookies.Add(c); 

HttpCookie cookie = Request.Cookies[key]; 

if( cookie !

= null ) 

this.labResult.Text = cookie.Value; 

Response.Cookies.Remove(key); 

这段代码的运行结果就是【能显示当前时间】,我就不贴图了。

如果写成如下形式:

protected void Page_Load(object sender, EventArgs e) 

string key = "Key1"; 

HttpCookie cookie = Request.Cookies[key]; 

if( cookie !

= null ) 

this.labResult.Text = cookie.Value; 

HttpCookie c = new HttpCookie(key, DateTime.Now.ToString()); 

Response.Cookies.Add(c); 

Response.Cookies.Remove(key); 

此时就读不到Cookie了。

这也提示我们:

Cookie的读写次序可能会影响我们的某些判断。

HttpRequest还有二个用于方便获取HTTP数据的属性Params,Item,后者是个默认的索引器。

这二个属性都可以让我们方便地根据一个KEY去【同时搜索】QueryString、Form、Cookies或ServerVariables这4个集合。

通常如果请求是用GET方法发出的,那我们一般是访问QueryString去获取用户的数据,如果请求是用POST方法提交的,我们一般使用Form去访问用户提交的表单数据。

而使用Params,Item可以让我们在写代码时不必区分是GET还是POST。

这二个属性唯一不同的是:

Item是依次访问这4个集合,找到就返回结果,而Params是在访问时,先将4个集合的数据合并到一个新集合(集合不存在时创建),然后再查找指定的结果。

为了更清楚地演示这们的差别,请看以下示例代码:

 

Item结果:

<%= this.ItemValue %>

 

Params结果:

<%= this.ParamsValue %>

 

 

" method="post"> 

 

 

 

 

public partial class ShowItem :

 System.Web.UI.Page 

protected string ItemValue; 

protected string ParamsValue; 

protected void Page_Load(object sender, EventArgs e) 

string[] allkeys = Request.QueryString.AllKeys; 

if( allkeys.Length == 0 ) 

Response.Redirect("ShowItem.aspx?

name=abc", true); 

ItemValue = Request["name"]; 

ParamsValue = Request.Params["name"]; 

页面在未提交前浏览器的显示:

点击提交按钮后,浏览器的显示:

差别很明显,我也不多说了。

说下我的建议吧:

尽量不要使用Params,不光是上面的结果导致的判断问题,没必要多创建一个集合出来吧,而且更糟糕的是写Cookie后,也会更新集合。

HttpRequest还有二个很【低调】的属性:

InputStream,Filter,这二位的能量很巨大,却不经常被人用到。

HttpResponse也有这二个对应的属性,本文的后面部分将向您展示它们的强大功能。

HttpResponse

我们处理HTTP请求的最终目的只有一个:

向客户端返回结果。

而所有需要向客户端返回的操作都要调用HttpResponse的方法。

它提供的功能集中在操作HTTP响应部分,如:

响应流,响应头。

我把一些认为很重要的成员简单列举了一下:

// 获取网页的缓存策略(过期时间、保密性、变化子句)。

 

public HttpCachePolicy Cache { get;} 

// 获取或设置输出流的 HTTP MIME 类型。

默认值为“text/html”。

 

public string ContentType { get;set;} 

// 获取响应 Cookie 集合。

 

public HttpCookieCollection Cookies { get;} 

// 获取或设置一个包装筛选器对象,该对象用于在传输之前修改 HTTP 实体主体。

 

public Stream Filter { get;set;} 

// 启用到输出 Http 内容主体的二进制输出。

 

public Stream OutputStream { get;} 

// 获取或设置返回给客户端的输出的 HTTP 状态代码。

默认值为 200 (OK)。

 

public int StatusCode { get;set;} 

// 将 HTTP 头添加到输出流。

 

public void AppendHeader(string name, string value); 

// 将当前所有缓冲的输出发送到客户端,停止该页的执行,并引发EndRequest事件。

 

public void End(); 

// 将客户端重定向到新的 URL。

指定新的 URL 并指定当前页的执行是否应终止。

 

public void Redirect(string url, bool endResponse); 

// 将指定的文件直接写入 HTTP 响应输出流,而不在内存中缓冲该文件。

 

public void TransmitFile(string filename); 

// 将 System.Object 写入 HTTP 响应流。

 

public void Write(object obj); 

这些成员都有简单的解释,应该了解它们。

这里请关注一下属性StatusCode。

我们经常用JQuery来实现Ajax,比如:

使用ajax()函数,虽然你可以设置error回调函数,但是,极有可能在服务端即使抛黄页了,也不会触发这个回调函数,除非是设置了dataType="json",这时在解析失败时,才会触发这个回调函数,如果是dataType="html",就算是黄页了,也能【正常显示】。

怎么办?

在服务端发生异常不能返回正确结果时,请设置StatusCode属性,比如:

Response.StatusCode=500;

HttpContext

终于轮到大人物出场了。

应该可以这么说:

有了HttpRequest,HttpResponse分别控制了输入输出,就应该没有更重要的东西了。

但我们用的都是HttpRequest,HttpResponse的实例,它们在哪里创建的呢,哪里保存有它们最原始的引用呢?

答案当然是:

HttpContext。

没有老子哪有儿子,就这么个关系。

更关键的是:

这个老子还很牛,【在任何地方都能找到它】,而且我前面提到另二个实力不错的选手(HttpServerUtility和Cache),也都是它的手下。

因此,任何事情,找到它就算是有办法了。

你说它是不是最牛。

不仅如此,在ASP.NET的世界,还有黑白二派。

Module像个土匪,什么请求都要去“检查”一下,Handler更像白道上的人物,点名了只做某某事。

展开阅读全文
相关资源
猜你喜欢
相关搜索
资源标签

当前位置:首页 > 表格模板 > 合同协议

copyright@ 2008-2023 冰点文库 网站版权所有

经营许可证编号:鄂ICP备19020893号-2