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
}
}
Related
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.
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.
I have this code
List<DaSubscription> lstSubscription=new List<DaSubscription>();
for(int i=0;i<20;i++)//20 is just to simulate the behavior
{
DaSubscription Generic=new DaSubscription();
Generic.DataChanged += new DataChangedEventHandler(Generic_DataChanged);
lstSubscription.add(Generic);
}
//EVENT Handler which is raised from a 3rd party library [COM]
void Generic_DataChanged(DaSubscription aDaSubscription, DaItem[] items, ValueQT[] values, int[] results)
{
UpdateDataChangedDTO(items, values);
}
As the same event handler [m_daSubscription_Generic_DataChanged] is assigned to the multiple instance of same class [m_daSubscription]. Question i have is if at the same time multiple instances invokes this handler how will be handled here. will there will be any instance it shall overwrite the data. or the event handler will be separate for each instance.
The event handlers execute seperately. It sounds like your worried about the parameters being overwritten by another call to the handler. That won't happen (I don't think it is even possible). Since it doesn't look like you are accessing any shared objects in the event handler, you should be perfectly safe.
The MSDN documentation says:
HttpContext.RemapHandler Method - Enables you to specify a handler for the request.
I am trying to move the processing of the request from one handler to another depending on a condition in the first handler. The HttpContext.RemapHandler method seems to initialise an instance of the second handler but not call the HttpHandler.ProcessRequest method; the response is empty.
Does the HttpContext.RemapHandler method do what I think it should - transfer processing to a new HttpHandler and calling the HttpHandler.ProcessRequest method? Or should I be using another approach such as another method or an HttpModule?
EDIT:
Turns out I should be using a HTTPHandlerFactory. I have the solution working nicely now.
So what exactly is HttpContext.RemapHandler for?
You can use HttpContext.RemapHandler as you specified, however if another HttpHandler calls RemapHandler (e.g. ASP.NET MVC which registers MvcHandler in PostResolveRequestCache) your IHttpModule will never fire. This is maybe why IHttpHandler.Process was never called.
If this is your issue, you can simply define a route to ignore in MvcApplication.RegisterRoutes like this:
routes.IgnoreRoute("your_path/{*pathInfo}");
Also, remember that with Visual Studio Web Development Server and IIS6, RemapHandler will not work.
Here is an example of how to select the right way to remap the handler based on whether or not Integrated Pipeline is activated AND still be able to access the session:
public void Init(HttpApplication application)
{
if (HttpRuntime.UsingIntegratedPipeline)
// For IIS 7 and IIS 8
application.PostAuthorizeRequest += Application_PostAuthorizeRequest;
else
// For IIS 6
application.PostMapRequestHandler += Application_PostMapRequestHandler;
}
private void Application_PostAuthorizeRequest(object sender, EventArgs e)
{
((HttpApplication)sender).Context.RemapHandler(_myHandler);
}
private void Application_PostMapRequestHandler(object sender, EventArgs e)
{
((HttpApplication)sender).Context.Handler = _myHandler;
}
The difference between using a HttpHandlerFactory and HttpModule in this case is that the latter allows you to decide when to use which IHttpHandler regardless of ASP.NET IHttpHandler mappings. More on MSDN: HTTP Handlers and HTTP Modules Overview.
I have a custom error handler class like this:
namespace AccountCenterUserControls
{
public class EWHErrorModule : IHttpModule
{
public void Init(HttpApplication app)
{
app.Error += new System.EventHandler(OnError);
}
public void OnError(object obj, EventArgs args)
{
Page myPage = (System.Web.UI.Page)HttpContext.Current.Handler;
ctx.Server.ClearError();
}
public void Dispose() { }
}
}
I've instantiated this error handler in my web.config like this:
<httpModules>
<!-- EWH Custom Error Handler -->
<add type="AccountCenterUserControls.EWHErrorModule" name="EWHErrorModule"/>
</httpModules>
It traps errors ok. My question is, how can I let my trapped error pages benefit from my masterpage? I can get to the individual masterpages from my page, but I'm not quite sure how I set the contentplaceholder when I am in this deep.
In ASP.NET the app error event can be raised at any point during the page life-cycle you may be executing your error handler at a time it is entirely illegal to modify the Page. If it is allowable you can attain a reference to the element you wish to modify or replace using FindControl. Again, if the timing is legal you can modify the controls collection of the control or add or remove controls from the control's control collection to achive the eventual desired rendering.
I hope my assumptions are correct about your situation If they are I did wonder why you do not simply implement Application_Error in Global.asax/.cs? This would be automatically wired to the ASP.NET application's OnError event. Inside that handler you would have references available to Request, Response, and Session.
Also, you should be aware that HttpContext.Current.Handler can and will return null at certain stages of the life-cycle. For example an error has occurred before the request is handed off to the handler like during authenticate request.