你必须知道ASP.NET知识------从IIS到httpmodule(第一篇)
一、写在前面
最近有时间,顺便将这系列洗完,接着上文:IIS各个版本知识总结
这篇文章原本计划写到HttpHandler为止,但限于篇幅就写到httpmodule
本文有不足之处,求指正,希望我能将它分析透彻.
二、回顾--我们还是从IIS说起
从上文(IIS各个版本知识总结)可以很清楚地意思到经典模式和集成模式的区别:集成模式是一个伟大的改进,让IIS集成了.NET功能(不在依靠之前IIS版本的aspnet_ISPAI.DLL).
所以,对于我们所开发的ASP.NET程序而言,这些完全不必知道;但运行环境自己必须知道发生了什么情况.
所以两者的主要区别在于:从w3wp.exe初始化httpapplication这一阶段.
三、看看经典模式(包括IIS6)的过程

IIS的处理进程到w3wp这一阶段后,iis会通过com的方式创建AppManagerAppDomainFactory对象,AppManagerAppDomainFactory会
在Create方法中创建ISAPIRuntime对象.代码如下.
using System;
using System.Globalization;
using System.IO;
using System.Runtime.InteropServices;
using System.Runtime.Remoting;
using System.Security.Permissions;
using System.Web.Util;
namespace System.Web.Hosting
{
[SecurityPermission(SecurityAction.LinkDemand, Unrestricted = true)]
public sealed class AppManagerAppDomainFactory : IAppManagerAppDomainFactory
{
private ApplicationManager _appManager;
public AppManagerAppDomainFactory()
{
this._appManager = ApplicationManager.GetApplicationManager();
this._appManager.Open();
}
[return: MarshalAs(UnmanagedType.Interface)]
public object Create(string appId, string appPath)
{
object result;
try
{
if (appPath[] == '.')
{
FileInfo fileInfo = new FileInfo(appPath);
appPath = fileInfo.FullName;
}
if (!StringUtil.StringEndsWith(appPath, '\\'))
{
appPath += "\\";
}
ISAPIApplicationHost appHost = new ISAPIApplicationHost(appId, appPath, false);
ISAPIRuntime iSAPIRuntime = (ISAPIRuntime)this._appManager.CreateObjectInternal(appId, typeof(ISAPIRuntime), appHost, false, null);
iSAPIRuntime.StartProcessing();
result = new ObjectHandle(iSAPIRuntime);
}
catch (Exception)
{
throw;
}
return result;
}
public void Stop()
{
this._appManager.Close();
}
internal static string ConstructSimpleAppName(string virtPath)
{
if (virtPath.Length <= )
{
return "root";
}
return virtPath.Substring().ToLower(CultureInfo.InvariantCulture).Replace('/', '_');
}
}
}
最终将流程交由ProcessRequest处理,代码如下.接着如红色处,由HttpRuntime.ProcessRequestNoDemand(iSAPIWorkerRequest)处理
public int ProcessRequest(IntPtr ecb, int iWRType)
{
IntPtr intPtr = IntPtr.Zero;
if (iWRType == )
{
intPtr = ecb;
ecb = UnsafeNativeMethods.GetEcb(intPtr);
}
ISAPIWorkerRequest iSAPIWorkerRequest = null;
int result;
try
{
bool useOOP = iWRType == ;
//注:internal abstract class ISAPIWorkerRequest : HttpWorkerRequest
iSAPIWorkerRequest = ISAPIWorkerRequest.CreateWorkerRequest(ecb, useOOP);
iSAPIWorkerRequest.Initialize();
string appPathTranslated = iSAPIWorkerRequest.GetAppPathTranslated();
string appDomainAppPathInternal = HttpRuntime.AppDomainAppPathInternal;
if (appDomainAppPathInternal == null || StringUtil.EqualsIgnoreCase(appPathTranslated, appDomainAppPathInternal))
{
HttpRuntime.ProcessRequestNoDemand(iSAPIWorkerRequest);
result = ;
}
else
{
HttpRuntime.ShutdownAppDomain(ApplicationShutdownReason.PhysicalApplicationPathChanged, SR.GetString("Hosting_Phys_Path_Changed", new object[]
{
appDomainAppPathInternal,
appPathTranslated
}));
result = ;
}
}
catch (Exception ex)
{
//..................................
}
return result;
}
ISAPIWorkerRequest是对请求信息的一层C++封装.
四、HttpRuntime中发生的事情
接着上面 HttpRuntime.ProcessRequestNoDemand(iSAPIWorkerRequest);
internal static void ProcessRequestNoDemand(HttpWorkerRequest wr)
{
RequestQueue requestQueue = HttpRuntime._theRuntime._requestQueue;
wr.UpdateInitialCounters();
if (requestQueue != null)
{
wr = requestQueue.GetRequestToExecute(wr);
}
if (wr != null)
{
HttpRuntime.CalculateWaitTimeAndUpdatePerfCounter(wr);
wr.ResetStartTime();
HttpRuntime.ProcessRequestNow(wr);
}
}
internal static void ProcessRequestNow(HttpWorkerRequest wr)
{
HttpRuntime._theRuntime.ProcessRequestInternal(wr);
}
我们看到方法进入
private void ProcessRequestInternal(HttpWorkerRequest wr)
其结构如下
private void ProcessRequestInternal(HttpWorkerRequest wr)
{
Interlocked.Increment(ref this._activeRequestCount);
if (this._disposingHttpRuntime)
{
try
{
wr.SendStatus(, "Server Too Busy");
wr.SendKnownResponseHeader(, "text/html; charset=utf-8");
byte[] bytes = Encoding.ASCII.GetBytes("<html><body>Server Too Busy</body></html>");
wr.SendResponseFromMemory(bytes, bytes.Length);
wr.FlushResponse(true);
wr.EndOfRequest();
}
finally
{
Interlocked.Decrement(ref this._activeRequestCount);
}
return;
}
HttpContext httpContext;
try
{
httpContext = new HttpContext(wr, false);
}
catch
{
try
{
wr.SendStatus(, "Bad Request");
wr.SendKnownResponseHeader(, "text/html; charset=utf-8");
byte[] bytes2 = Encoding.ASCII.GetBytes("<html><body>Bad Request</body></html>");
wr.SendResponseFromMemory(bytes2, bytes2.Length);
wr.FlushResponse(true);
wr.EndOfRequest();
return;
}
finally
{
Interlocked.Decrement(ref this._activeRequestCount);
}
}
wr.SetEndOfSendNotification(this._asyncEndOfSendCallback, httpContext);
HostingEnvironment.IncrementBusyCount();
try
{
try
{
this.EnsureFirstRequestInit(httpContext);
}
catch
{
if (!httpContext.Request.IsDebuggingRequest)
{
throw;
}
}
httpContext.Response.InitResponseWriter();
IHttpHandler applicationInstance = HttpApplicationFactory.GetApplicationInstance(httpContext);
if (applicationInstance == null)
{
throw new HttpException(SR.GetString("Unable_create_app_object"));
}
if (EtwTrace.IsTraceEnabled(, ))
{
EtwTrace.Trace(EtwTraceType.ETW_TYPE_START_HANDLER, httpContext.WorkerRequest, applicationInstance.GetType().FullName, "Start");
}
if (applicationInstance is IHttpAsyncHandler)
{
IHttpAsyncHandler httpAsyncHandler = (IHttpAsyncHandler)applicationInstance;
httpContext.AsyncAppHandler = httpAsyncHandler;
httpAsyncHandler.BeginProcessRequest(httpContext, this._handlerCompletionCallback, httpContext);
}
else
{
applicationInstance.ProcessRequest(httpContext);
this.FinishRequest(httpContext.WorkerRequest, httpContext, null);
}
}
catch (Exception e)
{
httpContext.Response.InitResponseWriter();
this.FinishRequest(wr, httpContext, e);
}
}
传说中的HttpApplication就是在这里初始化的.
IHttpHandler applicationInstance = HttpApplicationFactory.GetApplicationInstance(httpContext);//因为HttpApplication实现了IHttpHandler接口
最终通过BuildManager.GetGlobalAsaxType()获取对应的Global.asax所告知的类型进行HttpApplication的实例化.
internal static IHttpHandler GetApplicationInstance(HttpContext context)
{
if (HttpApplicationFactory._customApplication != null)
{
return HttpApplicationFactory._customApplication;
}
if (context.Request.IsDebuggingRequest)
{
return new HttpDebugHandler();
}
HttpApplicationFactory._theApplicationFactory.EnsureInited();
HttpApplicationFactory._theApplicationFactory.EnsureAppStartCalled(context);
return HttpApplicationFactory._theApplicationFactory.GetNormalApplicationInstance(context);
}
private HttpApplication GetNormalApplicationInstance(HttpContext context)
{
HttpApplication httpApplication = null;
lock (this._freeList)
{
if (this._numFreeAppInstances > )
{
httpApplication = (HttpApplication)this._freeList.Pop();
this._numFreeAppInstances--;
if (this._numFreeAppInstances < this._minFreeAppInstances)
{
this._minFreeAppInstances = this._numFreeAppInstances;
}
}
}
if (httpApplication == null)
{
httpApplication = (HttpApplication)HttpRuntime.CreateNonPublicInstance(this._theApplicationType);
using (new ApplicationImpersonationContext())
{
httpApplication.InitInternal(context, this._state, this._eventHandlerMethods);//注意:这里是主战场
}
}
if (AppSettings.UseTaskFriendlySynchronizationContext)
{
httpApplication.ApplicationInstanceConsumersCounter = new CountdownTask();
httpApplication.ApplicationInstanceConsumersCounter.Task.ContinueWith(delegate(Task _, object o)
{
HttpApplicationFactory.RecycleApplicationInstance((HttpApplication)o);
}, httpApplication, TaskContinuationOptions.ExecuteSynchronously);
}
return httpApplication;
}
五、主战场中的发生的事情
internal void InitInternal(HttpContext context, HttpApplicationState state, MethodInfo[] handlers)
{
this._state = state;
PerfCounters.IncrementCounter(AppPerfCounter.PIPELINES);
try
{
try
{
this._initContext = context;
this._initContext.ApplicationInstance = this;
context.ConfigurationPath = context.Request.ApplicationPathObject;
using (new DisposableHttpContextWrapper(context))
{
if (HttpRuntime.UseIntegratedPipeline)
{
try
{
context.HideRequestResponse = true;
this._hideRequestResponse = true;
this.InitIntegratedModules();
goto IL_6B;
}
finally
{
context.HideRequestResponse = false;
this._hideRequestResponse = false;
}
}
this.InitModules();
IL_6B:
if (handlers != null)
{
this.HookupEventHandlersForApplicationAndModules(handlers);
}
this._context = context;
if (HttpRuntime.UseIntegratedPipeline && this._context != null)
{
this._context.HideRequestResponse = true;
}
this._hideRequestResponse = true;
try
{
this.Init();
}
catch (Exception error)
{
this.RecordError(error);
}
}
if (HttpRuntime.UseIntegratedPipeline && this._context != null)
{
this._context.HideRequestResponse = false;
}
this._hideRequestResponse = false;
this._context = null;
this._resumeStepsWaitCallback = new WaitCallback(this.ResumeStepsWaitCallback);
if (HttpRuntime.UseIntegratedPipeline)
{
this._stepManager = new HttpApplication.PipelineStepManager(this);
}
else
{
this._stepManager = new HttpApplication.ApplicationStepManager(this);
}
this._stepManager.BuildSteps(this._resumeStepsWaitCallback);
}
finally
{
this._initInternalCompleted = true;
context.ConfigurationPath = null;
this._initContext.ApplicationInstance = null;
this._initContext = null;
}
}
catch
{
throw;
}
}
待续................................
六、求关注、求推荐
兄台给点鼓励吧 O(∩_∩)O~,你的鼓励是我继续写好这一系列的理由
你必须知道ASP.NET知识------从IIS到httpmodule(第一篇)的更多相关文章
- Java基础知识常见面试题汇总第一篇
[Java面试题系列]:Java基础知识常见面试题汇总 第一篇 文中面试题从茫茫网海中精心筛选,如有错误,欢迎指正! 1.前言 参加过社招的同学都了解,进入一家公司面试开发岗位时,填写完个人信息后 ...
- 你必须知道ASP.NET知识------关于动态注册httpmodule(对不起汤姆大叔)
一.关于动态注册的问题 很多人看过汤姆大叔的MVC之前的那点事儿系列(6):动态注册HttpModule ,其实汤姆大叔没有发现httpmodule动态注册的根本机制在哪里. 亦即:怎么动态注册?为什 ...
- 使用Asp.Net Core MVC 开发项目实践[第一篇:项目结构说明]
先从下图看整体项目结构: Mango.Manager: 为后台管理项目 Mango.Web: 为前台项目 Mango.Framework.Core: 为常用的基础操作类项目 Mango.Framewo ...
- 【Java面试题系列】:Java基础知识常见面试题汇总 第一篇
文中面试题从茫茫网海中精心筛选,如有错误,欢迎指正! 1.前言 参加过社招的同学都了解,进入一家公司面试开发岗位时,填写完个人信息后,一般都会让先做一份笔试题,然后公司会根据笔试题的回答结果,确定 ...
- ASP.NET页面与IIS底层交互和工作原理详解
转载自:http://www.cnblogs.com/lidabo/archive/2012/03/13/2393200.html 第一回: 引言 我查阅过不少Asp.Net的书籍,发现大多数作者都是 ...
- ASP.NET页面与IIS底层交互和工作原理详解(第一回)
引言 我查阅过不少Asp.Net的书籍,发现大多数作者都是站在一个比较高的层次上讲解Asp.Net.他们耐心.细致地告诉你如何一步步拖放控件.设置控件属性.编写CodeBehind代码,以实现某个特定 ...
- asp相关知识整理
WWW----World Wide Web(万维网) URL----Uniform Resource Locator(统一资源定位符) HTTP----Hyper Text Transfer Prot ...
- asp.net发布到IIS中出现错误:处理程序“PageHandlerFactory-Integrated”在其模块列表中有一个错误模块“ManagedPipelineHandler”
asp.net发布到IIS中出现错误:处理程序“PageHandlerFactory-Integrated”在其模块列表中有一个错误模块“ManagedPipelineHandler” http:// ...
- ASP.NET知识集
ASP.NET知识集 编辑删除转载2015-06-23 16:31:55 标签:it //删除指定行数据时,弹出询问对话框 ((LinkButton)(e.Row.Cell[7].Controls[0 ...
随机推荐
- 网页集成paypal支付
在网站中集成paypal支付有两种方式: 1.通过paypal账户的按钮创建工具 进入paypal 商户账号,选择创建按钮工具,有包括添加到购物车.购买.租用三类按钮. 之后会生成一段代码,直接将代码 ...
- PSP
PSP2.1 Time(%) Planning 10 l Estimate 10 Development 90 l Analysis 10 l Design Spec 5 l Design Revie ...
- [.net 面向对象编程基础] (13) 面向对象三大特性——多态
[.net 面向对象编程基础] (13) 面向对象三大特性——多态 前面两节,我们了解了面向对象的的封装和继承特性,面向对象还有一大特性就是多态.比起前面的封装和继承,多态这个概念不是那么好理解.我们 ...
- Java集合List模拟“洗牌”操作
Collection工具类为操作List集合提供了几个有用的方法: reverse().shuffle().sort().swap().rotate(). 小例子: 使用shuffle(),方法模拟洗 ...
- C#实现的等额本息法、按月付息到期还本法、一次性还本付息法
你若懂行,那便有用,如下: void Main(){ var x = DengEBenXi.Compute(11111, 12, 3); x.Dump(); var y = AnYu ...
- 给UINavigationBar自定义颜色
self.navigationController.navigationBar.barTintColor = RGB(55, 46, 41);
- 将不确定变成确定~Uri文本文件不用浏览器自动打开,而是下载到本地
回到目录 这个标题有点长,简单来说就是,对于一个文件下载来说,是否可以提示用户,让它去保存,而不是将它在浏览器中打开,在浏览器中打开有个致命问题,那就是,如果你的页面编码和文件的编码不一致时,打开的就 ...
- struts2学习笔记之十三:自定义过滤器
Struts2的拦截器 1.Struts2的拦截器只能拦截Action,拦截器是AOP的一种思路,可以使我们的系统架构 更松散(耦合度低),可以插拔,容易互换,代码不改变的情况下很容易满足客户需求 其 ...
- atitit 短信接口规范与短信解决方案.docx
atitit 短信接口规范与短信解决方案.docx 1.1. 国内比较著名的短信提供商1 1.2. 短信接口规范1 1.3. 短信sdk构成1 1.4. 短信的实现1 1.5. SmsServiceY ...
- C#学习系列-抽象方法与虚拟方法的区别
参考:http://www.microsoftvirtualacademy.com/Content/ViewContent.aspx?et=9851&m=9838&ct=31054 如 ...