Ext.Net 1.2.0_分析 Ext.Net.ResourceHandler 资源处理程序
本文内容
-
概述
-
Ext.Net.ResourceHandler 资源处理程序
-
参考资料
概述
页面依赖 Ext.Net. ResourceManager 控件初始化其资源,将 CSS 和脚本的引用和内容加入到页面。
若在页面引用 Ext.Net. ResourceManager 控件,如下所示:
那么,页面呈现的内容如下所示:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<link rel="stylesheet" type="text/css" href="/extjs/resources/css/ext-all-embedded-css/ext.axd?v=17083" />
<title>
</title>
<script type="text/javascript" src="/extjs/adapter/ext/ext-base-js/ext.axd?v=17083"></script>1:
2: <script type="text/javascript" src="/extjs/ext-all-js/ext.axd?v=17083">1: </script>
2: <script type="text/javascript" src="/extnet/extnet-core-js/ext.axd?v=17083">1: </script>
2: <script type="text/javascript" src="/extnet/locale/ext-lang-zh-CN-js/ext.axd?v=17083">1: </script>
2: <script type="text/javascript">3: //<![CDATA[4: Ext.net.ResourceMgr.init({id:"ResourceManager1",BLANK_IMAGE_URL:"/extjs/resources/images/default/s-gif/ext.axd",aspForm:"form1",theme:"blue"});Ext.onReady(function(){Ext.QuickTips.init();});5: //]]>6:
</script>1:
2: </head>
3: <body>
4: <form name="form1" method="post" action="WebForm2.aspx" id="form1">5: <div>
6: <input type="hidden" name="__EVENTTARGET" id="__EVENTTARGET" value="" />7: <input type="hidden" name="__EVENTARGUMENT" id="__EVENTARGUMENT" value="" />8: <input type="hidden" name="__VIEWSTATE" id="__VIEWSTATE" value="/wEPDwUKMTkzNTgyMzk4N2QYAQUeX19Db250cm9sc1JlcXVpcmVQb3N0QmFja0tleV9fFgEFEFJlc291cmNlTWFuYWdlcjFtzMaC7eCHSStptAvkxOouI11aMQ==" />9: </div>
10:
11: <script type="text/javascript">12: //<![CDATA[13: var theForm = document.forms['form1'];14: if (!theForm) {15: theForm = document.form1;
16: }
17: function __doPostBack(eventTarget, eventArgument) {18: if (!theForm.onsubmit || (theForm.onsubmit() != false)) {19: theForm.__EVENTTARGET.value = eventTarget;
20: theForm.__EVENTARGUMENT.value = eventArgument;
21: theForm.submit();
22: }
23: }
24: //]]></script>
<div>
<input type="hidden" name="__EVENTVALIDATION" id="__EVENTVALIDATION" value="/wEWAgLl9M/1DQLk1b+VAvPeIxQnrPccjp0QWBmQuJLa1QHw" />
</div>
</form>
</body>
</html>
可以看到,页面头增加了几个资源引用和资源内容。这些资源都是 Ext.Net 的嵌入资源。但这些对于一个 Ajax 框架远远不够,仅仅是个开始。当用户再次请求资源时,如何处理这些资源?下面主要说明 Ext.Net.ResourceHanlder 如何管理自己的内嵌资源。
Ext.Net.ResourceHandler 资源管理程序
Web.config 文件
先看下使用 Ext.Net 时,对 Web.config 文件的配置。如下所示:
<?xml version="1.0"?>
<configuration>
<configSections>
<section name="extnet" type="Ext.Net.GlobalConfig" requirePermission="false" />
</configSections>
<extnet scriptMode="Release" /> <!-- See Property Options in README.txt -->
<!--
The following system.web section is only requited for running ASP.NET AJAX under Internet
Information Services 6.0 (or earlier). This section is not necessary for IIS 7.0 or later.
-->
<system.web>
<httpHandlers>
<add path="*/ext.axd" verb="*" type="Ext.Net.ResourceHandler" validate="false" />
</httpHandlers>
<httpModules>
<add name="DirectRequestModule" type="Ext.Net.DirectRequestModule, Ext.Net" />
</httpModules>
</system.web>
<!--
The system.webServer section is required for running ASP.NET AJAX under Internet Information Services 7.0.
It is not necessary for previous version of IIS.
-->
<system.webServer>
<validation validateIntegratedModeConfiguration="false"/>
<modules>
<add
name="DirectRequestModule"
preCondition="managedHandler"
type="Ext.Net.DirectRequestModule, Ext.Net"
/>
</modules>
<handlers>
<add
name="DirectRequestHandler"
verb="*"
path="*/ext.axd"
preCondition="integratedMode"
type="Ext.Net.ResourceHandler"
/>
</handlers>
</system.webServer>
</configuration>
其中,
- <add path="*/ext.axd" verb="*" type="Ext.Net.ResourceHandler" validate="false" /> 是任何包含 "*/ext.axd" 的 HTTP 请求,都会调用 Ext.Net.ResourceHandler 处理程序。
- <add name="DirectRequestModule" type="Ext.Net.DirectRequestModule, Ext.Net" /> 是在每次发出 HTTP 请求时,都会调 Ext.Net.DirectRequestModule 处理模块。该模块作为 ASP.NET 请求管道的一部分调用,在整个请求过程中访问生命周期事件。该模块使你可以检查传入和传出的请求并根据该请求进行操作。
Ext.Net.ResourceHandler 资源处理程序
Ext.Net.ResourceHandler 资源处理程序位于 Ext.Net 的 Core 目录。该处理程序处理任何包含 "*/ext.axd" 的 HTTP 请求。注意,它处理的单个请求。也就是说,对于页面头中的每项包含 "*/ext.axd" 的资源都会调用该处理程序,如
<script type="text/javascript" src="/extjs/adapter/ext/ext-base-js/ext.axd?v=17083"></script> 和
<script type="text/javascript" src="/extjs/ext-all-js/ext.axd?v=17083"></script> 等。其类图如下所示:
我们只需关心该处理程序的 Public 方法。其中 ProcessRequest 方法最重要。代码如下:
public override void ProcessRequest(HttpContext context)
{
this.context = context;
string file = this.context.Request.RawUrl;
bool isInitScript = file.Contains("extnet/extnet-init-js/ext.axd?");
if (!ResourceHandler.IsSourceModified(context.Request) && !isInitScript)
{
context.Response.SuppressContent = true;
context.Response.StatusCode = 304;
context.Response.StatusDescription = "Not Modified";
context.Response.AddHeader("Content-Length", "0");
return;
}
this.SetResponseCache(context);
if (isInitScript)
{
string key = file.RightOfRightmostOf('?');
if (key.IsNotEmpty())
{
try
{
string script = this.context.Session[key].ToString();
this.context.Session.Remove(key);
CompressionUtils.GZipAndSend(script);
}
catch (NullReferenceException)
{
throw new InitializationScriptNotFoundException("The Ext.NET initialization script was not found.");
}
}
}
else
{
try
{
this.sm = new ResourceManager();
this.compress = CompressionUtils.IsGZipSupported && this.sm.GZip;
this.SetWebResourceName(file);
this.stream = this.GetType().Assembly.GetManifestResourceStream(this.webResource);
string ext = this.webResource.RightOfRightmostOf('.');
this.compress = this.compress && !this.IsImage(ext);
switch (ext)
{
case "js":
this.WriteFile("text/javascript");
break;
case "css":
this.WriteFile("text/css");
break;
case "gif":
this.WriteImage("image/gif");
break;
case "png":
this.WriteImage("image/png");
break;
case "jpg":
case "jpeg":
this.WriteImage("image/jpg");
break;
}
}
catch (Exception e)
{
string s = this.IsDebugging ? e.ToString() : e.Message;
context.Response.StatusDescription = s.Substring(0, Math.Min(s.Length, 512));
this.context.Response.Redirect(Page.ClientScript.GetWebResourceUrl(this.sm.GetType(), this.webResource));
}
finally
{
if (this.stream != null)
{
this.stream.Close();
}
}
}
}
当用户初次请求页面时,该处理程序还不会执行。因为,那时页面关于嵌入资源(包括 CSS 和脚本)才刚刚添加。可当用户再次请求该页面时,对所有的嵌入资源就会调用这个处理程序。该方法的伪代码如下:
public override void ProcessRequest(HttpContext context)
{
if (若该资源为 “extnet-init.js”,且该资源未改动)
{
// 因为,作为嵌入在程序集的资源 !ResourceHandler.IsSourceModified 肯定为false。
// 则响应客户端HTTPCODE 为304——Not Modified,并返回。
}
// 设置该资源的缓存信息
if (若该资源为 “extnet-init.js”)
{
// 则从当前 HTTP 请求的回话中删除,并以压缩方式发送给客户端。
}
else
{
// 判断是否支持压缩 GZIP
// 从程序集获得嵌入资源,并以“压缩”方式发送 CSS 和脚本文件,以“非压缩”方式发送图像给客户端
}
}
参考资料
MSDN HTTP 处理程序和 HTTP 模块概述 http://msdn.microsoft.com/zh-cn/library/bb398986(v=VS.90).aspx
利用 IHttpHandler 自定义 HTTP 处理程序 http://www.cnblogs.com/liuning8023/archive/2011/11/29/2268445.html
.NET Framework IHttpHandler http://msdn.microsoft.com/zh-cn/library/system.web.ihttphandler(v=VS.90).aspx
IIS 5.0 和 6.0 的 ASP.NET 应用程序生命周期概述 http://msdn.microsoft.com/zh-cn/library/ms178473.aspx