The little Thing before MVC series (6): Dynamic registration HttpModule (reprint)

Source: Internet
Author: User

What happened before MVC series (6): Dynamic registration HttpModule

Article content

With the previous chapters, we know that HttpApplication initializes all the httpmodules that are registered in the configuration file at initialization, so there is a question of whether the HttpModule can be dynamically loaded before initialization, rather than just read from the Web. config.

The answer is yes, when ASP. NET MVC3 publishes a Microsoft.Web.Infrastructure.dll file that provides the ability to dynamically register HttpModule, then how is it registered? Let's go to the source code of the MVC3 to see the DLL.

Note: The DLL location is under C:\Program Files\Microsoft Asp.net\asp.net Web Pages\v1.0\assemblies\

We found a static class dynamicmoduleutility with a Registermodule method that caught my attention:

//Call from Preappstart to dynamically register a ihttpmodule, just as if you had added it to the//<modules> section in Web. config.[SecuritySafeCritical] Public Static voidregistermodule (Type moduletype) {if(Dynamicmodulereflectionutil.fx45registermoduledelegate! =NULL) {         //The Fx45 helper exists, so just call it directly.dynamicmodulereflectionutil.fx45registermoduledelegate (Moduletype); }    Else {         //Use private reflection to perform the hookup.Legacymoduleregistrar.registermodule (Moduletype); } }

Through the code and comments we can see that this method is to let us dynamically register IHttpModule, and because. Net4.5 already has helper class support, so it can be used directly, other versions use Legacymoduleregistrar.registermodule to dynamically register IHttpModule. And this method is divided into IIS6 and IIS7 integration or Classic mode, the code is generally consistent, we will only analyze the IIS6 version of the code:

Private Static voidaddmoduletoclassicpipeline (Type moduletype) {//This works by essentially adding a new entry to the //In ~/web.config.     Need to set the collection to Read+write and we do this. //httpmodulessection = Runtimeconfig.getappconfig ().     httpmodules; //httpModulesSection.Modules.bReadOnly = false; //HttpModulesSection.Modules.Add (New Httpmoduleaction (...)); //httpModulesSection.Modules.bReadOnly = true;httpmodulessection httpmodulessection=NULL; Try {         ObjectAppConfig =_reflectionutil.getappconfig (); Httpmodulessection=_reflectionutil.gethttpmodulesfromappconfig (appConfig); _reflectionutil.setconfigurationelementcollectionreadonlybit (Httpmodulessection.modules,false /*value*/); Dynamicmoduleregistryentry NewEntry=createdynamicmoduleregistryentry (Moduletype); HTTPMODULESSECTION.MODULES.ADD (Newhttpmoduleaction (Newentry.name, Newentry.type)); }     finally {        if(Httpmodulessection! =NULL) {_reflectionutil.setconfigurationelementcollectionreadonlybit (Httpmodulessection.modules,true /*value*/); }    } }

The comments on the above code are very important, as we can see from the comments that the method starts with Runtimeconfig.getappconfig (). HttpModules Gets the HttpModules collection, and then adds the new httpmodule that need to be registered in the collection, That means that HttpApplication must add the HttpModule that need to be registered to the collection before initializing all HttpModule, which is the cycle? HttpApplication before is hostingenvironment, that is not here can register? We go to the class to see the relevant code, in the Initialize method suddenly found a seemingly familiar code buildmanager.callprestartinitmethods (), the code is as follows:

//Call appinitialize, unless the flag says does it (e.g. CBM scenario).//Also, don ' t call it if Hostinginit failed (VSWhidbey 210495)if(!httpruntime.hostinginitfailed) {Try{ buildmanager.callprestartinitmethods ();          if((Hostingflags & hostingenvironmentflags.dontcallappinitialize) = =0) {Buildmanager.callappinitializemethod (); }    }     Catch(Exception e) {//could throw compilation errors in ' Code '-report them with first HTTP requestHttpruntime.initializationexception =e; if((Hostingflags & hostingenvironmentflags.throwhostinginiterrors)! =0) {             Throw; }    }}

By going to the BuildManager class to see the details of the method, we finally found the following method:

Internal StaticIcollection<methodinfo> Getprestartinitmethodsfromassemblycollection (ienumerable<assembly>assemblies) {List<MethodInfo> methods =NewList<methodinfo>(); foreach(Assembly Assemblyinchassemblies) {preapplicationstartmethodattribute[] attributes=NULL; Try{  attributes  = (preapplicationstartmethodattribute[]) assembly. GetCustomAttributes (typeof(Preapplicationstartmethodattribute), Inherit: true );  }        Catch {             //GetCustomAttributes invokes the constructors of the attributes, so it's possible that they might throw unexpected ex             Ceptions. //(DEV10 bug 831981)        }         if(Attributes! =NULL&& attributes. Length! =0) {Debug.Assert (attributes. Length==1); Preapplicationstartmethodattribute attribute= attributes[0]; Debug.Assert (Attribute!=NULL); MethodInfo Method=NULL; //Ensure the Type on the attribute are in the same assembly as the attribute itself            if(attribute. Type! =NULL&&! String.IsNullOrEmpty (attribute. MethodName) && attribute. type.assembly = =Assembly) {Method=Findprestartinitmethod (attribute. Type, attribute.            MethodName); }            if(Method! =NULL) { methods.            Add (method); }             Else {                 Throw NewHttpException (SR. GetString (SR. Invalid_preapplicationstartmethodattribute_value, assembly. FullName, (attribute. Type!=NULL?attribute. Type.FullName:String.Empty), attribute.            MethodName)); }        }     }    returnmethods;} 

The method is found to find all the assemblies under the application, and if the assembly is marked as a Preapplicationstartmethodattribute attribute, the method (static method) specified in the attribute is executed and the code of the class is checked:

[AttributeUsage (attributetargets.assembly, AllowMultiple =false)]      Public Sealed classPreapplicationstartmethodattribute:attribute {Private ReadOnlyType _type; Private ReadOnly string_methodname;  PublicPreapplicationstartmethodattribute (Type type,stringmethodName) {_type=type; _methodname=MethodName; }          PublicType type {Get{return_type;} }          Public stringMethodName {Get{return_methodname;} }    }

At this time, the heart should know, we can specify a static method name, and then in this method to register a custom HttpModule by the following code (note that we can only use one time):

Dynamicmoduleutility.registermodule (typeof(CustomModule));

Let's do a test. The result of our analysis is not correct, first create a custom HttpModule, the code is as follows:

 Public classcustommodule:ihttpmodule{ Public voidInit (HttpApplication context) {context. BeginRequest+=NewEventHandler (context_beginrequest); }    voidContext_beginrequest (Objectsender, EventArgs e) {HttpApplication AP= Sender asHttpApplication; if(AP! =NULL) {ap. Response.Write ("Uncle Tom tested Preapplicationstartmethod through! <br/>"); }    }     Public voidDispose () {// Nothing    }}

Then create a class to register the HttpModule with a static method:

 Public classpreapplicationstartcode{Private Static BOOLhasloaded;  Public Static voidPrestart () {if(!hasloaded) {hasloaded=true; //Note The dynamic registration here, this static method in Microsoft.Web.Infrastructure.DynamicModuleHelperDynamicmoduleutility.registermodule (typeof(CustomModule)); }    }}

Next, to install the requirement to add an attribute to the program, the code is as follows:

[Assembly:preapplicationstartmethod (typeof"prestart")]

Finally, compile and run, you will find all the pages at the top of our specified text (Uncle Tom Test Preapplicationstartmethod pass!) ), as follows:

This confirms that our analysis is correct, how is this function good, There is no need to define your HttpModule in the Web. config every time, and we will be more convenient to encapsulate our own libraries later, without having to specify code in the site assembly to launch our own packaged separate class libraries, because we can use this method to automate the registration function in our own class library. In the next section, we will introduce a super-strong class library developed using this feature.

Note: The same assembly can only use this feature once to invoke a static method.

Synchronization and recommendations

This article has been synchronized to the directory index: Thelittle Thing before MVC series

MVC before the point of the series of articles, including the original, translation, reprint and other types of articles, if it is useful to you, please recommend supporting a, to the power of the uncle writing.

Original link This article by Bean John Blog Backup expert remote One click release

The little Thing before MVC series (6): Dynamic registration HttpModule (reprint)

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.