你必须知道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 ...
随机推荐
- 测试了几款 C# 脚本引擎 , Jint , Jurassic , Nlua, ClearScript
测试类 public class Script_Common { public string read(string filename) { return System.IO.File.ReadAll ...
- EF6(CodeFirst)+MySql开发脱坑指南
废话 话说当年,在一个春光明媚的晌午,邂逅了迷人的丁香姑娘,从此拜倒在了她的石榴裙下,至今不能自拔,这位丁香姑娘就是ORM思想. 所谓ORM思想,我的理解就是根据一定的规则,把程序中的对象和数据库中的 ...
- 使用SQL生成DateTime.Ticks
在项目中我需要使用到一个随机数(Random Number),该随机数将作为 Hashtable 中的 Key 用于唯一索引数据,所以需要保持单机唯一性. 同时该随机数还需要具备可排序性以便对数据进行 ...
- 把 Notepad++ 打造成一款易用的C#脚本编辑器
以前一直用Linqpad在写小程序脚本,但是Linqpad自动完成功能要收费,且不开源,这样的话就不方便扩展了.今天在 http://csscriptnpp.codeplex.com/ 发现了一款C# ...
- Linux下安装Apache并以mod_wsgi方式部署django站点
源码编译方式安装Apache 首先下载Apache源码压缩包,地址为http://mirror.bit.edu.cn/apache/httpd/ 继续下载apr和apr-util压缩包,地址为http ...
- 2种方式解决nginx负载下的Web API站点里swagger无法使用
Web API接口站点,引入了swagger来实时生成在线的api文档,也便于api接口的在线测试.swagger:The World's Most Popular Framework for API ...
- 爱上MVC~AuthorizeAttribute验证不通过如何停止当前上下文
回到目录 我们知道mvc里有一些过滤器,AuthorizeAttribute用来做授权,一般在用户授权方面可以使用它,当使用没有登陆,我们直接跳到登陆页,这是没有问题的,可我要说的是,当用户对某个Ac ...
- jQuery监听文本框值改变触发事件(propertychange)
完整代码: <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w ...
- SlickUpload Upload to disk
The file upload stream provider is a built-in SlickUpload provider that uses the filesystem for uplo ...
- XML学习笔记6——XPath语言
在上一篇笔记的结尾,我们接触到了两个用于选择XML文档中特定范围的元素<selector>和<field>,这两个元素的取值都是XPath表达式,那么,什么是XPath呢?简单 ...