Contents tagged with Modules

  • Injecting Content in an ASP.NET Web Forms Page From a Module

    Modules are a great extensibility mechanism because they allow us to glimpse into a request and to do something before the response is sent back.

    Sometimes, you may want to change the page – add some contents, change the properties of controls, etc. – in a module, so that you can reproduce the behavior for all (or some) pages in an easily reusable way. For that, ASP.NET offers a great number of events, that compose the request lifecycle.

    Say you want to inject custom content to the page; you might be surprised to find that if even if you choose what appears to be a right event, the injected content does not show up!

    Here’s the right way to do it: you need to hookup the Page’s Init event (PreInit won’t work) and do the change from there. For example:

       1: public class InjectModule : IHttpModule
       2: {
       3:     #region IHttpModule Members
       5:     public void Dispose() {}
       7:     public void Init(HttpApplication context)
       8:     {
       9:         context.PreRequestHandlerExecute += this.OnPreRequestHandlerExecute;
      10:     }
      12:     private void OnPreRequestHandlerExecute(Object sender, EventArgs e)
      13:     {
      14:         var app = sender as HttpApplication;
      16:         if ((app != null) && (app.Context != null))
      17:         {
      18:             var page = app.Context.CurrentHandler as Page;
      20:             if (page != null)
      21:             {
      22:                 page.Init += (s, args) =>
      23:                 {
      24:                     var p = (s as Page);
      26:                     if (p.Header != null)
      27:                     {
      28:                         p.Header.Controls.Add(new LiteralControl("<script type=\"text/javascript\">window.alert('Hello, World!')</script>"));
      29:                     }
      31:                     if (p.Form != null)
      32:                     {
      33:                         p.Form.Controls.Add(new LiteralControl("Hello, World!"));
      34:                     }
      35:                 };
      36:             }
      37:         }
      38:     }
      40:     #endregion
      41: }

    I am using the PreRequestHandlerExecute event because here the page is already built and the CurrentHandler property because of any possible transfers.


  • ASP.NET Web Forms Extensibility: Modules

    Next in the series is modules. So, what is a module, and what does it do?

    A module is some class that implements IHttpModule. This is a very simple interface, which only defines two methods:

    • Init: this is the “body” of the module, where you place it’s logic (more on this later), called when the application is started (typically, upon the first request, unless you are doing application initialization);
    • Dispose: called when the application shuts down.

    A module is typically statically registered on the Web.config file, although I have talked in the past on how to register modules dynamically. While a module usually does not actually do anything by itself, it is useful for registering event handlers for ASP.NET application lifetime events, such as Error, BeginRequest, EndRequest and their likes. Please note that there is no event for the Start occurrence (normally handled on the custom Global class on an Application_Start method), you can just use the Init method for that, since it is called upon application startup.

    Out of the box ASP.NET includes a number of modules, which you can find on the global Web.config file, located in %WINDIR%\Microsoft.NET\Framework64\v4.0.30319\Config, some of which you are free to disable, that is, remove on you local Web.config file:

       1: <!-- for IIS < 7 -->
       2: <httpModules>
       3:    <remove name="PassportAuthentication" />
       4: </httpModules>
       5: <!-- for IIS 7+ -->
       6: <system.webServer>
       7:   <modules>
       8:     <remove name="PassportAuthentication" />
       9:   </modules>
      10: </system.webServer>

    As you can see from the above snippet, one such module is PassportAuthentication, implemented by PassportAuthenticationModule, one that is marked as deprecated in current versions of .NET. Now, there are two sections where modules can be registered, one for IIS versions prior to 7, and the other for recent versions. Of course, if you only use one of them, do forget about the other section.

    A simple module implementation would be:

       1: public class FooterModule : IHttpModule
       2: {
       3:     void IHttpModule.Init(HttpApplication context)
       4:     {
       5:         context.EndRequest += (sender, e)
       6:         {
       7:             HttpContext.Current.Response.Write(String.Format("<p>Generated at {0}</p>", DateTime.UtcNow));
       8:         };
       9:     }
      11:     void IHttpModule.Dispose()
      12:     {
      13:     }
      14: }

    This module registers an event handler for the EndRequest event, which, when called, outputs a string to the response. Nothing to be done on disposing, in this case, but a typical use case would be to release any sort of “heavy” module-held resources when the application shuts down. Please be careful to perform operations only when you can, for example, session is only available after the AcquireRequestState event is raised (and, of course, only for handlers implementing IRequiresSessionState), caller identity is only set after the AuthenticateRequest and authorization is only confirmed after AuthorizeRequest.

    You should favor writing code that handles an event in a module as opposed to having a similar method on Global.asax.cs because a module is more portable – you can even reuse it between different assemblies.

    Once you are finished, you need to register your module on Web.config, to have it being set up automatically. You have to give it a unique name and add an entry like the following:

       1: <!-- for IIS < 7 -->
       2: <system.web>
       3:     <httpModules>
       4:         <add name="MyModule" type="MyNamespace.MyModule, MyAssembly"/>
       5:     </httpModules>
       6: </system.web>
       7: <!-- for IIS 7+ -->
       8: <system.webServer>
       9:     <modules runAllManagedModulesForAllRequests="true">
      10:         <add name="MyModule" type="MyNamespace.MyModule, MyAssembly"/>
      11:     </modules>
      12: </system.webServer>

    Next, handlers and routes! Winking smile


  • Adding Modules Dynamically to ASP.NET

    As you may already know, ASP.NET 4.0 brought along with it a new mechanism to execute methods before the application start event (the Application_Start method): the PreApplicationStartMethodAttribute. This attribute, when applied to an assembly, indicates a method which is to be run before the application starts. If your web application references any assembly which has this attribute, it will run the method it declares, throwing an exception it if is not found.