你必须知道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 ...
随机推荐
- Github注册账户
这是注册页面: 注册完后应该会受到邮件,但我一直没有收到,换了邮箱也没有用 ± 账户可以登上去却没办法创建仓库.
- gtest 1.7编译错误:std:tr1:tuple模板参数过多的解决方案
在gtest/gtest.h文件中添加如下代码 #define _VARIADIC_MAX 10
- 用 C 扩展 python
本文介绍如何用 C 语言来扩展 python.所举的例子是,为 python 添加一个设置字符串到 windows 的剪切板(Clipboard)的功能.我在写以下代码的时候用到的环境是:window ...
- 渣渣小本求职复习之路每天一博客系列——数据库基础(MySQL)(5)
前情回顾:昨天学习了MySQL中索引的设计与使用,还了解了一些常见的SQL注入攻击的手段以及防范方法,一般来说,在面试的时候如果不是要求比较高,基本就够用了. 今天碰见一个拿了TP-LINK的offe ...
- UDP Client—Linux
#include <stdio.h> #include <netinet/ip.h> int main(int argc,char *argv[]) { #define PER ...
- C#入门基础三四
数组:数组是一组具有相同类型的值的集合,可以通过索引来访问数组中的元素. 声明数组的语法: A.数据类型 [] 数组名称: B.数据类型 [] 数组名称 = new 数据类型[数组大小]; C.int ...
- Java关于流知识总结
流总结: 一.流的分类: 数据单位:字节流 字符流 方向: 输出流 输入流 角色: 节点流 套节流 字节流:以Stream结尾. 字符流:以Reader 和Writer 结尾. 输入流:所有带有 ...
- [Spring框架]Spring开发实例: XML+注解.
前言: 本文为自己学习Spring记录所用, 文章内容包括Spring的概述已经简单开发, 主要涉及IOC相关知识, 希望能够对新入门Spring的同学有帮助, 也希望大家一起讨论相关的知识. 一. ...
- Atitit 作用域的理解attilax总结
Atitit 作用域的理解attilax总结 1.1. 作用域是指对某一变量和方法具有访问权限的代码空间, 1 1.2. 作用域的使用提高了程序逻辑的局部性,增强程序的可靠性,减少名字冲突.1 1.3 ...
- salesforce 零基础学习(二十)简单APP制作
本篇参考链接:https://developer.salesforce.com/trailhead/project/salesforce_developer_workshop 本篇讲述的是最简单的AP ...