I looked for an answer to this for quite sometime now but didn't find any.
I will refer to Application start as a stage.
Most of the documentations out there talk about the Global.asax file and the Application_Start method which is invoked only once when the first request reaches the Application, even if this behaviour is similar to subscribing to an event it's technicaly not an event.
While lifecycle events such as BeginRequest, AuthenticateRequest and so on are accessible through the application instance as events, the Application.Start is not.
I can subscribe to BeginRequest event in an HttpModule.Init() method or Global.asax Init() method but not to the Application.Start stage like so:
Module
public class MyModule : IHttpModule
{
public void Init(HttpApplication httpApplication)
{
httpApplication.BeginRequest += new EventHandler(ApplicationBeginRequest);
}
}
Global
public class Global : HttpApplication
{
public override void Init()
{
BeginRequest += new EventHandler(ApplicationBeginRequest);
}
}
My question:
Since there is no HttpApplication.Start event accessible from the Application instance, is Global.asax and the "Application_Start" method the only hope to subscribe to the Application start stage ?
After jumping to the .NET source code i found that the HttpApplicationFactory class looks for a method named Application_OnStart or Application_Start in the Global.asax file and then invokes it using reflection => ReflectOnMethodInfoIfItLooksLikeEventHandler().
I don't have the answer why HttpApplication.Start is not event but it's clearly intended to be handled in an event like fashion using Application_OnStart or Application_Start methods.
Related
I'm facing the following problem. I have a SignalR hub like this:
public class NewsLetterHub : Hub
{
private readonly IServicesContainer _servicesContainer;
private readonly ILifetimeScope _hubLifetimeScope;
public NewsLetterHub(ILifetimeScope lifetimeScope, IServicesContainer servicesContainer)
{
_servicesContainer = servicesContainer;
_hubLifetimeScope = lifetimeScope.BeginLifetimeScope();
_servicesContainer.NewsLetterService.ImportProgress += _sentNewsLetter_Progress;
}
I register this hub in Autofac this way:
builder.RegisterHubs(Assembly.GetExecutingAssembly());
Debugging the code I see that hub constructor is called once per request but the ImportProgress event contains the previous registered handler. This brings _sentNewsLetter_Progress method to be executed multiple times.
I tryied to register the hub this way:
builder.RegisterHubs(Assembly.GetExecutingAssembly()).InstancePerLifetimeScope();
Doing this it seems to work but I don't know if this is the right solution (it becomes singleton).
I also tryied to unregister the event:
_servicesContainer.NewsLetterService.ImportProgress -= _sentNewsLetter_Progress;
_servicesContainer.NewsLetterService.ImportProgress += _sentNewsLetter_Progress;
But it seems to do nothing.
How to prevent this behavior?
You need to change where you're de-registering the event handler to do it in a destructor or Dispose() method. If you try to do in the constructor it will try to de-register the _sentNewsLetter_Progress handler from the instance being constructed. Since that instance isn't registered yet it will do nothing. However, if you de-register in the destructor/Dispose then it will work.
I'm creating a HTTP module by implementing IHttpModule and I'd like to handle the Authenticate event, raised by the Forms Authentication module.
The documentation only states how to handle this event from within Global.asax, how can I handle this event from within my HTTP module?
You can handle the AuthenticateRequest event of the HttpApplication that is passed to the Init method of your IHttpModule implementation:
// IHttpModule.Init
public void Init(HttpApplication context)
{
// subscribe to the AuthenticateRequest event
context.AuthenticateRequest += this.onApplicationAuthenticateRequest;
}
private void onApplicationAuthenticateRequest(object sender, EventArgs e)
{
// your code goes here
}
This article has an example of the basic authentication in Web API which uses custom HttpModule, might be helpful.
If I add my HttpModule using the following method it fires for the page request only and not for any static image requests.
[assembly: PreApplicationStartMethod(typeof(MyHttpModule), "Start")]
public class MyHttpModule :
{
public static void Start()
{
DynamicModuleUtility.RegisterModule(typeof(MyHttpModule));
}
}
If I register it normally within the modules section within system.webServerin the web.config the HttpModule works correctly and handles all requests.
The event handler registered in the HttpModule is the PostAuthorizeRequestevent handler
Any ideas?
Q 1. To my understanding FormsAuthenticationModule is subscribed to AuthenticateRequest event, and thus only after this event is fired, is FormsAuthenticationModule called. But the following quotes got me a bit confused:
The AuthenticateRequest event signals that the configured authentication mechanism has authenticated the current request.
Doesn’t the above quote suggest that when AuthenticateRequest event is raised, request (aka user) is already authenticated?
Subscribing to the AuthenticateRequest event ensures that the request will be authenticated before processing the attached module or event handler.
As far as I understand this quote, if we subscribe to AuthenticatedRequest, then our event handler will be called prior to FormsAuthenticationModule? Thus Application_AuthenticateRequest() will be called before FormsAuthenticationModule is called?
Q 2. Book I’m learning from suggests that within Application_AuthenticateRequest() we are able to verify whether user is a member of specific role, and if not, we can add the user automatically:
protected void Application_AuthenticateRequest(Object sender, EventArgs e)
{
if (User.Identity.IsAuthenticated && Roles.Enabled)
{
//here we can subscribe user to a role via Roles.AddUserToRole()
}
}
Judging from the above code, Application_AuthenticateRequest() is called after FormsAuthenticationModule has been invoked, but somewhere else same book implies that Application_AuthenticateRequest() is called prior to FormsAuthenticationModule:
Application_AuthenticateRequest is called just before authentication is performed.
This is a jumping-off point for creating your own authentication logic.
What am I missing?
Thanx
It seems that the FormsAuthenticationModule gets handled first. This module is normally earlier than any custom module in the ASP.NET pipeline, so when AuthenticateRequest is fired, FormsAuthenticationModule will get called first, do its job and then your module's event handler will be called.
If you really want to dig deep into this, I suggest trying to debug the ASP.NET code yourself. Here is a post how to set up your VS:
http://weblogs.asp.net/scottgu/archive/2008/01/16/net-framework-library-source-code-now-available.aspx
EDIT: I was able to confirm this behavior by setting up a web project with custom module and event handlers in Global.asax. Take a look at the source code of HttpApplication.InitInternal, the order of initialization is as follows:
initialization of integrated modules: FormsAuthenticationModule hooks up to HttpApplication.AuthenticateRequest event
initialization of custom modules: custom module hooks up to HttpApplication.AuthenticateRequest event
initialization of Global class (global.asax): here we hook up to the AuthenticateRequest event
HttpApplication.InitInternal searches for methods on Global class following the specific name pattern (e.g. Application_AuthenticateRequest), matches them to event and hooks up
After the initialization, when the AuthenticateRequest fires, the event handlers are called in the order they where initialized, so:
FormsAuthenticationModule.AuthenticateRequest event handler
CustomModule.AuthenticateRequest event handler
Global.AuthenticateRequest event handler
Global.Application_AuthenticateRequest method
Unless I missed something, there is no mechanism for stopping the event handlers to fire, so no matter what the result of FormsAuthenticationModule.AuthenticateRequest, the next handlers will still be called. I hope that helps.
If you want access to the User object, I'd suggest you use
protected void Application_Start()
{
PostAuthenticateRequest += Application_PostAuthenticateRequest;
}
protected void Application_PostAuthenticateRequest(object sender, EventArgs e)
{
if(User.Identity.IsAuthenticated)
{
//Do stuff here
}
}
After looking at the .net on IIS7 application lifecycle:
http://msdn.microsoft.com/en-us/library/ms178473.aspx
For maximum performance, I want to find a way to get my code started as soon as the HttpContext object is created but before HttpApplication is. (it's easy to run code after the HttpApplication class is loaded but before any of it's event are triggered by using the contructor of an HTTP Module like this:
public class AuthModule : IHttpModule
{
public AuthModule()
{
HttpContext.Current.Response.Write("hello world");
HttpContext.Current.Response.End();
}
#region IHttpModule Members
public void Dispose()
{ }
public void Init(HttpApplication context)
{ }
#endregion
}
I know that i won't get access to the User object, but i won't need it.
You cannot ever be sure your code starts before the HttpApplication instance is created, since these instances may be reused.
Also, running code at this stage is beyond the scope of the pipeline. It should make you ask yourself whether it's really a sensible thing to do.
And what's this about performance? You really think the time to create an instance of HttpApplication is going to register in your performance?
Take a step back and reconsider.
Look at the life-cycle events on MSDN. You can consider using one of those events if you want something earlier than the normal page events.