Thursday, January 22, 2015

Application Life Cycle/ HTTP Application/ HTTP Module/Custom HTTP Module/ Page Life Cycle in ASP.NET



Ever you wondered ... how HTTP module works, how global.asax funcitons get called, if custom http modules are used, does it invoke global functions ? how http pipeline behaves in that case.

How IIS redirects user request to ASP.Net engine.. How app domain is created.. how HTTP context is created..

There are asyncHandller and Module to be discussed in later post....


Application Environment Graphic

The life cycle of an ASP.NET application starts with a request sent by a browser to the Web server (for ASP.NET applications, typically IIS). ASP.NET is an ISAPI extension under the Web server. When a Web server receives a request, it examines the file-name extension of the requested file, determines which ISAPI extension should handle the request, and then passes the request to the appropriate ISAPI extension. ASP.NET handles file name extensions that have been mapped to it, such as .aspx, .ascx, .ashx, and .asmx.

Little More about ISAPI Extention.

Click To expand

Read; It seems that the FormsAuthenticationModule gets handled first. This module is normally earlier than any custom module in the ASP.NET pipeline, - have to research.. not sure...





The ASP.NET ISAPI library (Aspnet_isapi.dll) runs inside the IIS process address space (Inetinfo.exe). It dispatches requests to the HttpRuntime object within the ASP.NET worker process (Aspnet_wp.exe). The following set of actions occurs in response to each Web request received by ASP.NET:
  • The HttpRuntime object examines the request and forwards it to an instance of an HttpApplication object.
    There is at least one HttpApplication object instance per application domain (the objects are pooled) and one application domain per IIS virtual directory. The initial request for a file in a particular virtual directory results in a new application domain and a new HttpApplication object being created.
  • A list of HTTP modules is read from Machine.config (they are contained within the <httpModules> element). Additional custom HTTP modules can be added to Web.config for a specific application. The default <httpModules> element within Machine.config is shown in the following code snippet.
    <httpModules>
      <add name="OutputCache" 
           type="System.Web.Caching.OutputCacheModule"/>
      <add name="Session" 
           type="System.Web.SessionState.SessionStateModule"/>
      <add name="WindowsAuthentication" 
           type="System.Web.Security.WindowsAuthenticationModule"/>
      <add name="FormsAuthentication" 
           type="System.Web.Security.FormsAuthenticationModule"/>
      <add name="PassportAuthentication" 
           type="System.Web.Security.PassportAuthenticationModule"/>
      <add name="UrlAuthorization" 
           type="System.Web.Security.UrlAuthorizationModule"/>
      <add name="FileAuthorization" 
           type="System.Web.Security.FileAuthorizationModule"/>
    </httpModules>
The authentication modules hook the AuthenticateRequest event, while the authorization modules hook the AuthorizeRequest event.
The request passes through every module in the pipeline, although only a single authentication module is loaded. This depends on the configuration of the <authentication> element in Web.config. For example, the <authentication> element that follows results in theWindowsAuthenticationModule being loaded.
  • <authentication mode="Windows" />
    • 
      
    • The activated authentication module is responsible for creating an IPrincipal object and storing it in the HttpContext.User property. This is vital, because the downstream authorization modules use this IPrincipal object in order to make authorization decisions.
In the absence of authentication (for example, where anonymous access is enabled within IIS and ASP.NET is configured with <authentication mode=”None” />), there’s a special non configured module that puts a default anonymous principal into the HttpContext.User property. As a result,HttpContext.User is always non-null after authentication.
If you implement a custom authentication module, code within the custom module must create an IPrincipal object and store it in HttpContext.User,
When the UrlAuthorizationModule is called, it checks for an <authorization> tag in Machine.config and Web.config. If present, it retrieves theIPrincipal object from HttpContext.User and checks to see whether the user is authorized to access the requested resource using the specified verb (GET, POST, and so on).
  • If the user is not authorized, the UrlAuthorizationModule calls HttpApplication.CompleteRequest, which aborts normal message processing. TheUrlAuthorizationModule returns an HTTP 401 status code.


Read: ASP.NET will not perform authentication or authorization checks on requests for .htm files. Therefore, even if a file contains only static content, if you want ASP.NET to check authentication, create the file using a file name extension mapped to ASP.NET, such as .aspx.

When ASP.NET receives the first request for any resource in an application, a class named ApplicationManager creates an application domain

After the application domain has been created and the HostingEnvironment object instantiated, ASP.NET creates and initializes core objects such as HttpContextHttpRequest, andHttpResponse. The HttpContext class contains objects that are specific to the current application request, such as the HttpRequest and HttpResponse objects.

After all core application objects have been initialized, the application is started by creating an instance of the HttpApplication class. If the application has a Global.asax file, ASP.NET instead creates an instance of the Global.asax class that is derived from the HttpApplication class and uses the derived class to represent the application.

The Application_Start and Application_End methods are special methods that do not represent HttpApplication events. ASP.NET calls them once for the lifetime of the application domain, not for eachHttpApplication instance.


must read:

It seems that the FormsAuthenticationModule gets handled first. This module is normally earlier than any custom module in the ASP.NET pipeline,

A diagram representation of above said;






so it goes on invoking method defined in global.asax as per modules registered in machine/web config file.


Lets Add Custom HTTP Module

M- Module
H - Handler
P - Page

A good article by , on Codeproject:

so from above , we knew the pipeline structure which looks like diagrammatically as mentioned below.



SectionEventDescription
HttpModuleBeginRequestThis event signals a new request; it is guaranteed to be raised on each request.
HttpModuleAuthenticateRequestThis event signals that ASP.NET runtime is ready to authenticate the user. Any authentication code can be injected here.
HttpModuleAuthorizeRequestThis event signals that ASP.NET runtime is ready to authorize the user. Any authorization code can be injected here.
HttpModuleResolveRequestCacheIn ASP.NET, we normally use outputcache directive to do caching. In this event, ASP.NETruntime determines if the page can be served from the cache rather than loading the patch from scratch. Any caching specific activity can be injected here.
HttpModuleAcquireRequestStateThis event signals that ASP.NET runtime is ready to acquire session variables. Any processing you would like to do on session variables.
HttpModulePreRequestHandlerExecuteThis event is raised just prior to handling control to the HttpHandler. Before you want the control to be handed over to the handler any pre-processing you would like to do.
HttpHandlerProcessRequestHttphandler logic is executed. In this section, we will write logic which needs to be executed as per page extensions.
PageInitThis event happens in the ASP.NET page and can be used for:
  • Creating controls dynamically, in case you have controls to be created on runtime.
  • Any setting initialization.
  • Master pages and the settings.
In this section, we do not have access to viewstate, postedvalues and neither the controls are initialized.
PageLoadIn this section, the ASP.NET controls are fully loaded and you write UI manipulation logic or any other logic over here.
PageValidateIf you have valuators on your page, you would like to check the same here.
RenderIt’s now time to send the output to the browser. If you would like to make some changes to the final HTML which is going out to the browser, you can enter your HTML logic here.
PageUnloadPage object is unloaded from the memory.
HttpModulePostRequestHandlerExecuteAny logic you would like to inject after the handlers are executed.
HttpModuleReleaserequestStateIf you would like to save update some state variables like session variables.
HttpModuleUpdateRequestCacheBefore you end, if you want to update your cache.
HttpModuleEndRequestThis is the last stage before your output is sent to the client browser.

This is the right time to go dip on page life cycle

qEventsControls InitializedView state
Available
Form data
Available
What Logic can be written here?
1InitNoNoNoNote: You can access form data etc. by using ASP.NET request objects but not by Server controls.Creating controls dynamically, in case you have controls to be created on runtime. Any settinginitialization.Master pages and them settings. In this section, we do not have access to viewstate , posted values and neither the controls are initialized.
2Load view stateNot guaranteedYesNot guaranteedYou can access view state and any synch logic where you want viewstate to be pushed to behind code variables can be done here.
3PostBackdataNot guaranteedYesYesYou can access form data. Any logic where you want the form data to be pushed to behind code variables can be done here.
4LoadYesYesYesThis is the place where you will put any logic you want to operate on the controls. Like flourishing a combobox from the database, sorting data on a grid, etc. In this event, we get access to all controls, viewstate and their posted values.
5ValidateYesYesYesIf your page has validators or you want to execute validation for your page, this is the right place to the same.
6EventYesYesYesIf this is a post back by a button click or a dropdown change, then the relative events will be fired. Any kind of logic which is related to that event can be executed here.
7Pre-renderYesYesYesIf you want to make final changes to the UI objects like changing tree structure or property values, before these controls are saved in to view state.
8Save view stateYesYesYesOnce all changes to server controls are done, this event can be an opportunity to save control data in to view state.
9RenderYesYesYesIf you want to add some custom HTML to the output this is the place you can.
10UnloadYesYesYesAny kind of clean up you would like to do here.

Custom module creation and see how to invoke global asax methods:


HttpModules implement IHttpModule, you actually only get Init (and Dispose if you have any cleanup to do). 

Your custom module will get invoked as the requests at a point in pipeline to invoke your module. you are just attaching the event to HTTPApplication class to call for that method.
it's just a portable version of Global ASAX which can be used across all applicaiton.
Below sample shows, how you can call global asax method from your custom http module.
if you registere 
  1.  sample uses the BeginRequest event.
  2. Implement the Init and Dispose methods of the IHttpModule interface as follows:

    public void Init(HttpApplication app)
    {
       app.BeginRequest += new EventHandler(OnBeginRequest);
    }
    
    public void Dispose(){ }     
  3. Create a delegate for an event as follows:

    public delegate void MyEventHandler(Object s, EventArgs e);     
  4. Define a private local variable of the type MyEventHandler to hold a reference to the event:

    private MyEventHandler _eventHandler = null;     
  5. Create an event that hooks up the delegate to the method in the Global.asax file or class that inherits from theHttpApplication object:

    public event MyEventHandler MyEvent
    {
       add { _eventHandler += value; }
       remove { _eventHandler -= value; }
    }     
  6. Create the OnBeginRequest method, which hooks up to the BeginRequest event of HttpApplication:

    public void OnBeginRequest(Object s, EventArgs e)
    {
       HttpApplication app = s as HttpApplication;
       app.Context.Response.Write("Hello from OnBeginRequest in custom module.<br>");
       if(_eventHandler!=null)
          _eventHandler(this, null);
    }     
  7. Deploy module
  8. <configuration>
       <system.web>
          <httpModules>
             <add name="MyModule" type="MyModule.SyncModule, MyModule" />
          </httpModules>
       </system.web>
    </configuration>

Test the Module

  1. In the C:\Inetpub\Wwwroot\Module directory, create a new .aspx file named Test.aspx.
  2. Paste the following text into Test.aspx:

    <%@Page Language="C#"%>
    <% Response.Write("Hello from Test.aspx.<br>"); %>     
  3. In the C:\Inetpub\Wwwroot\Module directory, create a Global.asax file.
  4. Paste the following code into Global.asax:

    <%@ Import Namespace="MyModule" %>
    
    <script language="C#" runat=server >
    protected void MyModule_OnMyEvent(Object src, EventArgs e)
    { 
      Context.Response.Write("Hello from MyModule_OnMyEvent called in Global.asax.<br>");
    }
    </script>     
  5. Request the Test.aspx page. You should see the following lines of text:

    Hello from OnBeginRequest in custom module.
    Hello from MyModule_OnMyEvent called in Global.asax.
    Hello from Test.aspx.     


So how the sequence goes?

When asp.net executes, this first check in config file and if not found looks for machine.config file. if resources are conflicting, this enforces config setting.

Above example says.. custom module begin request got executed first and then global .asax file. which seems true as webconfig gets checked first and then machine config...

So if you try to have the same module name as that of machine config file, this will throw error "Same key is assigned twice"
custom module can have an event handler which can be invoked to call method defined in global asax.,  for this method name should be "httpmodulename_OnModuleEvent" as shown in color combination above.

Custom Module gets called first,  And So as the .net engine will go on executing modules, this will invoke the corresponding method in global.asax file.

if Begin_request is invoked in custom module after that it will invoke Global.asax Begin_request method. same way it will follow for other method.




No comments:

Post a Comment