Monday, January 26, 2015

WCF Extensibility terminology and few examples - centralized error handling in WCF



WCF gives us a way to intercept message in communication channel. This provides us the interface to invoke methods when the message gets released from proxy and get received by dispatcher at service end.

Terminologies:

ChannelDispatchers – ChannelDispatchers (ChannelDispatcher) accept incoming messages.EachChannelDispatcher is associated with exactly one ChannelListener.ChannelListener receives the message as mentioned and the message is processed by channels.After the message is processed by the associated channels then ChannelDispatcher passes it on to a suitable EndpointDispatcher

EndPointDispatchers – EndPointDispatchers are responsible for taking a message out of the channel stack and passing them to the right service operation.

One of the key element of the EndpointDispatcher is the DispatchRuntime.DispatchRuntime provides facility to alter default service behaviour using custom classes to provide enhanced functionality related to Service Instancing,Error Handling,Security etc.

 DispatchRuntime contains the DispatchOperation which is responsible for routing the message to the right operation and providing customizations facilities applicable at the operation level.

Extension points available in DispatchRuntime and DispatchOperation along with the interfaces required to be implemented in order to develop these extension components.

DispatchRuntime

1. DispatchRuntime exposes the following two properties which provide facility to customize how ChannelDispatcher accepts or closes a channel.

1. ChannelInitializers – This is a collection of System.ServiceModel.DispatchRuntime.IChannelInitializerinterface objects.This interface is for raising notifications when a channel is created.
2. InputSessionShutdownHandlers – This is a collection ofSystem.ServiceModel..DispatchRuntime.IInputSessionShutdown interface objects.This interface is used to define actions for shutdown of an input session.

The following properties are exposed for customizing message processing:

MessageInspectors – This is a collection ofSystem.ServiceModel.DispatchRuntime.IDispatchMessageInspector objects.IDispatchMessageInspector defines contract to manipulate the messagesafter a message is received but before dispatched to the operationafter a operation is executed but before reply is sent

OperationSelectors – This is a collection ofSystem.ServiceModel.DispatchRuntime.IDispatchOperationSelector objects.IDispatchOperationSelector defines contract to select an operation name based on the message content.

Operations – This is a collection of System.ServiceModel.DispatchRuntime.DispatchOperation.We will discuss about the DispatchOperation in the next section.

ErrorHandlers – This is a collection of System.ServiceModel.DispatchRuntime.IErrorHandlerobjects.IErrorHandler defines methods to control the behaviour when an application exception is thrown.

The creation and lifetime of the service instances can be controlled by

InstanceContextInitializers – This is a collection ofSystem.ServiceModel.DispatchRuntime.IInstanceContextInitializer objects.IInstanceContextInitialzer defines the contract to manipulate the InstanceContext objects.

InstanceProvider – This is an object of type System.ServiceModel.DispatchRuntime.IInstanceProvider and this interface defines methods to customize creation and release of service instances.

DispatchOperation

Formatter – This property of type System.ServiceModel.DispatchRuntime.IDispatchMessageFormatter provides explicit control over message formatting.

CallContextInitializers – This is a collection of System.ServiceModel.Dispatcher.ICallContextInitializerobjects.This interface defines methods to add additional state information that is required during execution of the call.

ParameterInspectors – This is a collection of System.ServiceModel.DispatchRuntime.IParameterInspectorobjects and this interface defines methods to inspect/modify the parameters before and after method call.

So to extend the WCF functionality we need develop a component implementing the required interfaces and then assign it with the appropriate property of DispatchRuntime/DispatchOperation.


Now the obvious question is how do we attach the these components to the runtime in declarative or config driven manner

Example 1


Implementing IInstanceProvider

The class System.Runtime.Dispatcher.DispatchRuntime exposes the property InstanceProvider of type IInstanceProvider.DispatchRuntime uses this instance to acquire and release instances of service objects.IInstanceProvider defines the following methods:

GetInstance – Returns an service object instance
ReleaseInstance – Releases a service object instance

I have developed a class ServiceObjectPool which implements this interface and internally talks to the object pool as shown below:

public class ServiceObjectPool:IInstanceProvider  
{
    private ResourcePool pool = null;

    public ServiceObjectPool(Type resourceType, int maxPoolSize, int initialSize)
    {
        pool = new ResourcePool(resourceType, maxPoolSize, initialSize); //Create the pool
    }
    public ServiceObjectPool(Type resourceType, int maxPoolSize, int initialSize, int incrementSize)
    {
       pool = new ResourcePool(resourceType,maxPoolSize,initialSize,incrementSize); //Create the pool
    }
    public object GetInstance(System.ServiceModel.InstanceContext instanceContext, System.ServiceModel.Channels.Message message)
    {
        return pool.Acquire(); //Acquire from the Pool
    }

    public object GetInstance(System.ServiceModel.InstanceContext instanceContext)
    {
        return pool.Acquire(); //Acquire from the pool
    }

    public void ReleaseInstance(System.ServiceModel.InstanceContext instanceContext, object instance)
    {
        pool.Release(instance); //Release the object back to pool
    }

    }

Attaching the InstanceProvider to DispatchRuntime

To attach the custom Instance Provider to DispatchRuntime I have developed a custom behavior class ServicePoolBehavior as shown below:

public class ServicePoolBehavior : IServiceBehavior
    {
        public int MinPoolSize { get; set; }
        public int MaxPoolSize { get; set; }
        public int IncrementSize { get; set; }

        public void AddBindingParameters(ServiceDescription serviceDescription, System.ServiceModel.ServiceHostBase serviceHostBase, System.Collections.ObjectModel.Collection<ServiceEndpoint> endpoints, System.ServiceModel.Channels.BindingParameterCollection bindingParameters)
        {
            return;
        }
        public void ApplyDispatchBehavior(ServiceDescription serviceDescription, System.ServiceModel.ServiceHostBase serviceHostBase)
        {
        …….

        }

        public void Validate(ServiceDescription serviceDescription, System.ServiceModel.ServiceHostBase serviceHostBase)
        {

            return;

        }

    }

The main code goes into the ApplyDispatchBehavior method as shown below:

public void ApplyDispatchBehavior(ServiceDescription serviceDescription, System.ServiceModel.ServiceHostBase serviceHostBase)
{

     //Create the ServiceObjectPool instance
     ServiceObjectPool pool = new ServiceObjectPool(serviceDescription.ServiceType,MaxPoolSize ,MinPoolSize ,IncrementSize);
     ServiceThrottle throt = null;

     //Change the ServiceThrottle Setting in line with the Object Pool Settings

     foreach (ChannelDispatcher chDisp in serviceHostBase.ChannelDispatchers)
     {
         if(chDisp.ServiceThrottle!=null)
         {
             if (throt == null)
             {
                 throt = chDisp.ServiceThrottle;

             }
             else
             {
                 chDisp.ServiceThrottle = throt;
             }

             if (throt.MaxConcurrentInstances > MaxPoolSize)
             {
                 throt.MaxConcurrentInstances = MaxPoolSize;
             }
         }
         foreach (EndpointDispatcher endDisp in chDisp.Endpoints)
         {

             //Attach the Pool to Dispatch Runtime
             endDisp.DispatchRuntime.InstanceProvider = pool;
         }
     }
}

Attaching Behavior To Host

This can be done through code,attribute or configuration.Here I chose the configuration route.To attach the service behavior through configuration we need implement a subclass of System.ServiceModel.Configuration.BehaviorExtensionElement as shown below:

public class ServicePoolBehaviorExtensionElement:BehaviorExtensionElement
{
    [ConfigurationPropertyAttribute(“minPoolSize”,DefaultValue=2)]
    [IntegerValidator(MinValue=1)]
    public int MinPoolSize { get; set; }
    [ConfigurationPropertyAttribute(“maxPoolSize”,DefaultValue=10)]
    [IntegerValidator(MinValue = 1)]
    public int MaxPoolSize { get; set; }
    [ConfigurationPropertyAttribute(“incrementSize”,DefaultValue=2)]
    [IntegerValidator(MinValue = 1)]
    public int IncrementSize { get; set; }

    public override Type BehaviorType
    {
        get { return  typeof(ServicePoolBehavior); }
    }

    protected override object CreateBehavior()
    {
        ServicePoolBehavior behavior = new ServicePoolBehavior();
        behavior.MaxPoolSize = Convert.ToInt32( this.ElementInformation.Properties[“minPoolSize”].Value);
        behavior.MinPoolSize = Convert.ToInt32( this.ElementInformation.Properties[“maxPoolSize”].Value);
        behavior.IncrementSize = Convert.ToInt32( this.ElementInformation.Properties[“incrementSize”].Value) ;
        return behavior;
    }
}

The following lines needs to be added in the configuration file of the host:

    <extensions>
        <behaviorExtensions>
            <add name=”poolBehavior” type=”SB.ServiceModel.Pool.ServicePoolBehaviorExtensionElement, SB.ServiceModel.Pool, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null” />
        </behaviorExtensions>
    </extensions>
    <behaviors>
        <serviceBehaviors>
            <behavior name=”testBehavior”>
                <serviceDebug includeExceptionDetailInFaults=”true” />
                <serviceMetadata httpGetEnabled=”true” httpGetUrl=”http://localhost:9001/Meta” />
                <poolBehavior minPoolSize=”5″ maxPoolSize=”10″ incrementSize=”2″/>
            </behavior>
        </serviceBehaviors>
    </behaviors>
     <services>
          <service behaviorConfiguration=”testBehavior” name=”SampleService.Test”>
               <endpoint address=”http://localhost:9001/Test” binding=”wsHttpBinding”
                    name=”testhttp” contract=”SampleService.ITest” />
          </service>
     </services>
</system.serviceModel>



Example 2: to create centralized error handler


·          Create a custom Service Behaviour Attribute to let WCF know that we want to use the GlobalErrorHandler class whenever an unhandled exception occurs. 


using System;
using System.Collections.ObjectModel;
using System.ServiceModel;
using System.ServiceModel.Channels;
using System.ServiceModel.Description;
using System.ServiceModel.Dispatcher;

namespace CalculatorService
{
   
public class GlobalErrorHandlerBehaviourAttribute : Attribute, IServiceBehavior
    {
       
private readonly Type errorHandlerType;

       
public GlobalErrorHandlerBehaviourAttribute(Type errorHandlerType)
        {
           
this.errorHandlerType = errorHandlerType;
        }

       
public void Validate(ServiceDescription serviceDescription,
                             
ServiceHostBase serviceHostBase)
        {
        }

       
public void AddBindingParameters(ServiceDescription serviceDescription,
                                         
ServiceHostBase serviceHostBase,
                                         
Collection<ServiceEndpoint> endpoints,
                                         
BindingParameterCollection bindingParameters)
        {
        }

       
public void ApplyDispatchBehavior(ServiceDescription serviceDescription,
                                         
ServiceHostBase serviceHostBase)
        {
           
IErrorHandler handler = (IErrorHandler)Activator.CreateInstance(this.errorHandlerType);

           
foreach (ChannelDispatcherBase channelDispatcherBase in serviceHostBase.ChannelDispatchers)
            {
               
ChannelDispatcher channelDispatcher = channelDispatcherBase as ChannelDispatcher;
               
if (channelDispatcher != null)
                    channelDispatcher.ErrorHandlers.Add(handler);
            }
        }
    }
}

[GlobalErrorHandlerBehaviour(typeof(GlobalErrorHandler))]
public class CalculatorService : ICalculatorService
{
//try
    //{
       
return Numerator / Denominator;
   
//}
    //catch (DivideByZeroException ex)
    //{
    //    DivideByZeroFault divideByZeroFault = new DivideByZeroFault();
    //    divideByZeroFault.Error = ex.Message;
    //    divideByZeroFault.Details = "Denominator cannot be ZERO";

    //    throw new FaultException<DivideByZeroFault>(divideByZeroFault);
    //}}


using System;
using System.ServiceModel;
using System.ServiceModel.Channels;
using System.ServiceModel.Dispatcher;
namespace CalculatorService
{
   
public class GlobalErrorHandler : IErrorHandler
    {
       
public bool HandleError(Exception error)
        {
           
// log the actual exception for the IT Team to investigate
            // return true to indicate that the exception is handled
           
return true;
        }

       
public void ProvideFault(Exception error,
                                 System.ServiceModel.Channels.
MessageVersion version,
                                 ref System.ServiceModel.Channels.
Message fault)
        {
           
if (error is FaultException)
               
return;

            // Return a general service error message to the client
           
FaultException faultException = new FaultException("A general service error occured");
           
MessageFault messageFault = faultException.CreateMessageFault();
            fault =
Message.CreateMessage(version, messageFault, null
);
        }
    }
}



Sunday, January 25, 2015

WCF with Fluent NHibernate and StructureMap - Unit of work - Session/Session factory transaction


-- Content yet to be re-structured....

This tells about the IOC registration to be invoked once in WCF . in Web application it's easy because this has session in it when browser is opend, but WCF with Basic binding doesn't have that features.

so to make IOC registration/ on each service method this was to be called. and again WCF service was to invoke different connection based on country code supplied in service method, so IOC has to be reset with new connection string each time service method was called.

Like Webapplication, I could have done this..like creating new registry for different conenction (DB) for different countries. and in Applicaiton_Start event invoke IOC and all registry . then using  repositry and single unit of work parttern- I could have used the DAO layer to do the transaction.

Problem is : once the service method was invoked and it did the operation, session was getting closed. This is because we knew, Service has no session and it can't work like (Per session Instance mode) like web application.

so each call acts as new session and once service method is invoked, everything is lost. session is closed.

So I had to use the repository class's constructure to use Isessionfactory object opening a new session everytime it's called and begin new transaction. sets this in repository .session object and use this in calling method to commit or rollback it.

and to Make IOC registration call only once/ I had to make it singleton by using static object so that it does not get called every time  when service method was called.

Another problem was: everytime IOC was called the sessionfactory was called everytime and session was getting opened that many time with begin transaction. which i had to commented out and use it in repsiotry class to open session every time .  (

x.For<ISessionFactory>().Singleton()
                            .Use(() => new NHibernateHelper().BuildSessionfactory());

                        //x.For<ISession>().HybridHttpOrThreadLocalScoped()
                        //    .Use(ctx =>
                        //    {
                        //        var session = ctx.GetInstance<ISessionFactory>().OpenSession();
                        //        session.FlushMode = FlushMode.Commit;
                        //        session.BeginTransaction();
                        //        return session;
                        //    });

Commented section was getting called very time. I could have used the same pattern but when Isession was used this remains in open state and transaction is active. and once it's done with SQL transaction it was getting closed, so had to call IOC registratoin every time to create new Isession instance.

Little more details with


Next time when service method is called, again this will create session factory for a single country DB connection. this will check if Sessionfactory already create, this will just return the earlier created sessionfactory else will create a new one ( Singleton way)

then in repository class (Constructor), it will create new session of existing/new session factory and will do the Get/Update method.

when session.begintransaction gets called, Transaciton -gets active. and on commit it becomes false.

This is how in WCF call/ Bootstrapper.RegisterIOC can be called only once as we would have done in WebApplication by calling in "Applicaiotn_Start" event. and Webservice won't consume memory/ or will have headache of reseting sessionfactory and session all lthe time, service method gets called.


Example:


 public class Repository : IRepository, IDisposable
    {
        public ISession _session { get; set; }
       // public Repository(ISession session) { _session = session;}
        private ISessionFactory SessionFactory;
        public Repository()
        {
            SessionFactory = ObjectFactory.GetInstance<ISessionFactory>();
            _session = SessionFactory.OpenSession(); // Sets this in Repostiory session so that can be rollbacked or commited from service/client layer.
            _session.BeginTransaction();

        }
}

Boostraper:
public static class Bootstrapper
    {
        private static object _instance;
        private static object syncRoot = new Object();



        public static object Instance
        {
            get
            {
                if (_instance == null)
                {
                    lock (syncRoot)
                    {
                        // if (_instance == null)
                        // instance = new Singleton();
                    }
                }

                return _instance;
            }
        }

        public static void RegisterIoC()
        {
            if (_instance == null)
            {
                _instance = "US";  -- for US only once created.
                ObjectFactory.Initialize(x =>
                    {
                        //This needs to be configured to make user of multiple string. and RegisterIOC will only be called once when this is initilalised.
so below method won't get called every time as we used to do in service method.
                        x.For<ISessionFactory>().Singleton()
                            .Use(() => new NHibernateHelper().BuildSessionfactory());

                        //x.For<ISession>().HybridHttpOrThreadLocalScoped()
                        //    .Use(ctx =>
                        //    {
                        //        var session = ctx.GetInstance<ISessionFactory>().OpenSession();
                        //        session.FlushMode = FlushMode.Commit;
                        //        session.BeginTransaction();
                        //        return session;
                        //    });
                        x.For<IMS001>().Use<MS001>();
                        //x.For<IMS002>().Use<MS002>();
                        x.For<IMS004>().Use<MS004>();
                        x.For<IMS020>().Use<MS020>();
                        x.For<IMS021>().Use<MS021>();
                        x.For<IMS022>().Use<MS022>();
                        x.For<IMS024>().Use<MS024>();
                        x.For<IMS025>().Use<MS025>();
                        x.For<IMS026>().Use<MS026>();
                        x.For<IMSHelper>().Use<MSHelper>();

                        x.For<IRepository>().Use<Repository>();
                        x.Scan(y =>
                        {
                            y.TheCallingAssembly();
                            y.LookForRegistries();
                        });

                    });

            }
        }


        //public static void Initialize()
        //{
        //    throw new NotImplementedException();
        //}
    }

    public class SqlServerRegistry : Registry
    {
        public SqlServerRegistry()
        {

            //For<ISession>().HybridHttpOrThreadLocalScoped()
            //   .Use(ctx =>
            //   {
            //       var session = ctx.GetInstance<ISessionFactory>().OpenSession();
            //       session.FlushMode = FlushMode.Commit;
            //       session.BeginTransaction();
            //       return session;
            //   });

        }

    }

Example of Service method:
Calling method:
   private void CommitTransaction()
        {
            ISession session = ((Hierarchy_Services.Infrastructure.BusinessLogic.Repository)_repository)._session;
            if (session != null)
            {
             
                try
                {
                    if (session.IsOpen)
                    {
                        if (session.Transaction.IsActive)
                   
                           session.Transaction.Commit();
                       // session.BeginTransaction();
                     
                    }
                }
                catch (Exception ex)
                {
                    logger.Error(GetErrorMessage(ex));
                    RollbackTransaction();
                }
            }
        }
        private void RollbackTransaction()
        {
            ISession session = ((Hierarchy_Services.Infrastructure.BusinessLogic.Repository)_repository)._session; //this is where you capture the repository session.
         
            if (session.IsOpen )
            {
                if (session.Transaction != null && session.Transaction.IsActive)
                {
                    session.Transaction.Rollback();
                }
            }
        }
        private void CloseSession()
        {
            ISession session = ((Hierarchy_Services.Infrastructure.BusinessLogic.Repository)_repository)._session;
            if (session !=null && session.IsOpen )
            {
                  session.Dispose();
            }
        }

Public string ReturnMethod (string inputparameter)
{
InvokeFactory(request.countryCode.ToUpper()); -- this is where we used to know when which DB connection is going to used (country based)
}


 private void InvokeFactory(string countryCode, int divNo)
        {
            setCountryConfig(countryCode, divNo);
            Bootstrapper.RegisterIoC();
            _repository = ObjectFactory.GetInstance<IRepository>();
          //   session = ObjectFactory.GetInstance<ISession>();
            SessionFactory = ObjectFactory.GetInstance<ISessionFactory>();
            helper = new PositionHierarchyHelper(_repository, SessionFactory);
        }

Mainly you are passing the Isessionfactory object to repository class and there you are creating a new session and begin transaction. do operation and on calling method (page/service) you are getting the session (Isession) of repository partern and commit it or rollingh it back.

To make Single ton IOC registratoin and sessionfactory

public class NHibernateHelper
    {
        private static ISessionFactory _sessionFactory;

        private static ISessionFactory SessionFactory
        {
            get
            {
                if (_sessionFactory == null)

                    InitializeSessionFactory();
                return _sessionFactory;
            }
        }

        private static void InitializeSessionFactory()
        {
            _sessionFactory = Fluently.Configure()
                .Database(MsSqlConfiguration.MsSql2008
                  .ConnectionString(
                  @"Server=(local);initial catalog=xxxxx;
  user=xxxxx;password=xxxxx;") // Modify your ConnectionString
                              .ShowSql()
                )
                .Mappings(m =>
                          m.FluentMappings
                              .AddFromAssemblyOf<Program>())
                .ExposeConfiguration(cfg => new SchemaExport(cfg)
                                                .Create(true, true))
                .BuildSessionFactory();
        }

        public static ISession OpenSession()
        {
            return SessionFactory.OpenSession();
        }
    }

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.