HttpModule Init method is called several times - why? - c#

I was creating a http module and while debugging I noticed something which at first (at least) seemed like weird behaviour.
When I set a breakpoint in the init method of the httpmodule I can see that the http module init method is being called several times even though I have only started up the website for debugging and made one single request (sometimes it is hit only 1 time, other times as many as 10 times).
I know that I should expect several instances of the HttpApplication to be running and for each the http modules will be created, but when I request a single page it should be handled by a single http application object and therefore only fire the events associated once, but still it fires the events several times for each request which makes no sense - other than it must have been added several times within that httpApplication - which means it is the same httpmodule init method which is being called every time and not a new http application being created each time it hits my break point (see my code example at the bottom etc.).
What could be going wrong here? Is it because I am debugging and set a breakpoint in the http module?
It have noticed that it seems that if I startup the website for debugging and quickly step over the breakpoint in the httpmodule it will only hit the init method once and the same goes for the eventhandler. If I instead let it hang at the breakpoint for a few seconds the init method is being called several times (seems like it depends on how long time I wait before stepping over the breakpoint). Maybe this could be some build in feature to make sure that the httpmodule is initialized and the http application can serve requests , but it also seems like something that could have catastrophic consequences.
This could seem logical, as it might be trying to finish the request and since I have set the break point it thinks something have gone wrong and try to call the init method again? Soo it can handle the request?
But is this what is happening and is everything fine (I am just guessing), or is it a real problem?
What I am specially concerned about is that if something makes it hang on the "production/live" server for a few seconds a lot of event handlers are added through the init and therefore each request to the page suddenly fires the eventhandler several times.
This behaviour could quickly bring any site down.
I have looked at the "original" .net code used for the httpmodules for formsauthentication and the rolemanagermodule, etc... But my code isn't any different that those modules uses.
My code looks like this.
public void Init(HttpApplication app)
{
if (CommunityAuthenticationIntegration.IsEnabled)
{
FormsAuthenticationModule formsAuthModule = (FormsAuthenticationModule) app.Modules["FormsAuthentication"];
formsAuthModule.Authenticate += new FormsAuthenticationEventHandler(this.OnAuthenticate);
}
}
Here is an example how it is done in the RoleManagerModule from the .NET framework:
public void Init(HttpApplication app)
{
if (Roles.Enabled)
{
app.PostAuthenticateRequest += new EventHandler(this.OnEnter);
app.EndRequest += new EventHandler(this.OnLeave);
}
}
Does anyone know what is going on?
(I just hope someone out there can tell me why this is happening and assure me that everything is perfectly fine) :)
UPDATE:
I have tried to narrow down the problem and so far I have found that the init method being called is always on a new object of my http module (contrary to what I thought before).
I seems that for the first request (when starting up the site) all of the HttpApplication objects being created and their modules are all trying to serve the first request and therefore all hit the eventhandler that is being added.
I can't really figure out why this is happening.
If I request another page all the HttpApplication's created (and their modules) will again try to serve the request causing it to hit the eventhandler multiple times.
But it also seems that if I then jump back to the first page (or another one) only one HttpApplication will start to take care of the request and everything is as expected - as long as I don't let it hang at a break point.
If I let it hang at a breakpoint it begins to create new HttpApplication's objects and starts adding HttpApplications (more than 1) to serve/handle the request (which is already in process of being served by the HttpApplication which is currently stopped at the breakpoint).
I guess or hope that it might be some intelligent "behind the scenes" way of helping to distribute and handle load and / or errors. But I have no clue.
I hope some out there can assure me that it is perfectly fine and how it is supposed to be?

It's normal for the Init() method to be called multiple times. When an application starts up, the ASP.NET Worker process will instantiate as many HttpApplication objects as it thinks it needs, then it'll pool them (e.g. reuse them for new requests, similar to database connection pooling).
Now for each HttpApplication object, it will also instantiate one copy of each IHttpModule that is registered and call the Init method that many times. So if 5 HttpApplication objects are created, 5 copies of your IHttpModule will be created, and your Init method called 5 times. Make sense?
Now why is it instantiating 5 HttpApplication objects say? Well maybe your ASPX page has links to other resources which your browser will try to download, css, javascript, WebResource.aspx, maybe an iframe somewhere. Or maybe the ASP.NET Worker Process 'is in the mood' for starting more than 1 HttpApplication object, that's really an internal detail/optimisation of the ASP.NET process running under IIS (or the VS built in webserver).
If you want code that's guaranteed to run just once (and don't want to use the Application_StartUp event in the Global.asax), you could try the following in your IHttpModule:
private static bool HasAppStarted = false;
private readonly static object _syncObject = new object();
public void Init(HttpApplication context)
{
if (!HasAppStarted)
{
lock (_syncObject)
{
if (!HasAppStarted)
{
// Run application StartUp code here
HasAppStarted = true;
}
}
}
}
I've done something similar and it seems to work, though I'd welcome critiques of my work in case I've missed something.

Inspect the HttpContext.Current.Request to see, for what request the module's init is fired. Could be browser sending multiple request.
If you are connected to IIS, do check IIS logs to know whether any request is received for the time you are staying at the break point.

Here is a bit of explanation as to what you should use, when, and how they work.
When to use Application_Start vs Init in Global.asax?
Edit: More reading
The ASP Column: HTTP Modules
INFO: Application Instances, Application Events, and Application State in ASP.NET

Examle above locks the IHttpModule for all requests, and then, it frezes the whole application.
If your IHttpModule calls request several times is needed to call HttpApplication method CompleteRequest and dispose the HttpApplication instance of the IHttpModule in EndRequest event in order to remove instance of the HttpApplication like this:
public class TestModule :IHttpModule
{
#region IHttpModule Members
public void Dispose()
{
}
public void Init(HttpApplication context)
{
context.BeginRequest += new EventHandler(context_BeginRequest);
context.EndRequest += new EventHandler(context_EndRequest);
}
void context_EndRequest(object sender, EventArgs e)
{
HttpApplication app = sender as HttpApplication;
app.CompleteRequest();
app.Dispose();
}
void context_BeginRequest(object sender, EventArgs e)
{
//your code here
}
#endregion
}
If you need that IHttpModule requests every time without rerequest on postback use this code above.

Related

global.asax.cs authorize events for webapi need lock?

I am working on a web api and each request is authenticated with Authorize annotation on methods i.e. [Authorize (roles="trader")]
Based on the logs I can tell that multiple requests are entering the Application_PostAcquireRequestState event simultaneously.
As roles are loaded in Application_PostAcquireRequestState event, there can be race condition and some of the calls fail randomly.
I am not sure if I am on right track. The event is application level and Application.Lock() may fix the issue and like to know if it is the correct solution.
I have noticed a couple of calls to the web api failed, which were originated simultaneously.
I appreciate your help.
Global.ascs.cs
protected void Application_PostAcquireRequestState()
{
//Application.Lock();
//get user roles and verify access...
...
//Application.Unlock();
}
controller.cs
[Authorize(Roles = "Trader")]
public async Task<IHttpActionResult> GetOrder(long id)
{
//get order
}
You are wrong, this event, as well as a bunch of others (BeginRequest, AuthenticateRequest, AcquireRequestState etc.) is technically an application-level event (Application_...), however, actually it is a request-level event and multiple copies of the same handler are fired concurrently for different requests.
This means that the sender argument of the handler gives you exact execution context and is intended to be used like
protected void Application_PostAcquireRequestState( object sender, EventArgs e )
{
HttpApplication app = (HttpApplication)sender;
HttpContext ctx = app.Context; // current context
// with the current context in hand you can pretty much access anything
// including the Request, Response and last but not least, User
}
No need for locking or any other means of throttling.
I am only not sure why would you verify the access here, considering the MVC/WebAPI will do it in a moment in the pipeline, based on the Authorize and roles you put there.

Is HttpContext.RemapHandler supposed to change which handler processes request?

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.

MVC code to see whether or not a Controller is still in use

In my MVC application, I have a controller which creates an instance of a Model object. Within the Model, I have a timer which executes a function every 700ms. When I run the controller within my website, I continue to see the timer running even after I close the browser window. (The timer starts/stops a serial port connection, and I have a light that indicates when there is communication).
The communication actually never stops until I restart IIS entirely.
Is there some way in which I can check whether the controller is still in use, and thereby stop the timer if the controller is no longer active?
Here is the model code:
public CheckPulses(int interval) {
CheckPulsesTimer(interval);
}
public void CheckPulsesTimer(int interval) {
Timer timer = new Timer();
timer.Enabled = true;
timer.AutoReset = true;
timer.Interval = interval;
timer.Elapsed += new ElapsedEventHandler(GetPulses);
}
And here is the Controller code:
public ActionResult Index() {
CheckPulses Pulses = new CheckPulses(700);
return View();
}
I thought perhaps I should just add something to the GetPulses event, which happens every time the timer interval expires, and check there whether the controller is still in use. If it isn't, stop the timer. However, I'm not sure how to write that check. Can anyone point me in the right direction?
I think the core issue here is in your understanding of what a controller being "in use" is.
It seems as if you are imagining the following:
The user types in your URL and the browser connects to the server.
The server routes the request to an MVC Controller, which keeps a connection to the browser, and responds to each subsequent request using this connection.
The user closes their browser, or navigates away - and the Controller closes down the connection, and disposes.
This is not, however, what actually happens. Web traffic is generally a series of isolated, individual request/response pairings. There is no ongoing connection between the browser and the server.
The more correct sequence is something like the following:
The user types in your URL, and the browser connects to your server on port 80 (or 443 for https), passing in a valid HTTP request, containing a URL, HTTP verb, and other info.
Your server uses the HTTP request's information to route the request to a specific piece of executable code (in this case, your Controller's specific Action method).
In order to execute, the server creates an Instance of your Controller, then fires it's Action method, using the HTTP request's information as parameters.
Your Controller code executes, and an HTTP response message is sent back to the browser.
The Controller is .Dispose()'d by the ControllerFactory.
The issue you're experiencing is not caused by your Controller being "active" - because that's not something Controllers do. You are, instead, creating a Timer within your Model - and the Model, therefore, continues to live on in memory, unable to be killed by GarbageCollection. See this answer for more details.
In essence, think of it like this:
Your Controller is acting as a factory. When you call its Index method, it's equivalent to telling the factory "produce 1 Model". Once the Model rolls out of the factory, the factory is free to shut down, turn off the lights, and send all the workers home (the Controller is .Dispose()'d).
The Model, however, lives on in memory. In most cases, the Model should probably die off due to GarbageCollection once it goes out of scope - but because you have an active Timer inside of it, something is preventing that process from executing - and so the Model continues to live in your server's memory, happily firing its code again and again on each timer expiration.
Note that this has nothing to do with whether or not the user is still on your web-site, or whether their browser is still open, etc. It has to do with the nature of variable scoping and GarbageCollection on your server. You have now started a process which will continue until told to stop.
A potential solution:
In order to fix this, you might consider the following:
Create your Timer inside of a Singleton object. Something like:
public static class ConnectionManager {
private static bool initialized = false;
private static DateTime lastStartedAt = DateTime.Now;
private static Timer timer = null;
private static void Initialize() {
if (timer == null) {
timer = new Timer() {
AutoReset = true,
};
timer.Elapsed += new ElapsedEventHandler(GetPulses);
}
}
public static void Start(int interval) {
lastStartedAt = DateTime.Now;
Initialize(); // Create a timer if necessary.
timer.Enabled = true;
timer.Interval = interval;
}
public static void Stop() {
timer.Enabled = false;
}
}
Change your Controller to something like this:
public ActionResult Index() {
ConnectionManager.Start(700);
return View();
}
When you handle the expiration of the Timer event, check to see how long ago the lastStartedAt event occurred. If it is more than X minutes, do not process, and fire ConnectionManager.Stop().
This will give you the ability to keep your serial activity polling on a rolling expiration. In other words - each time a user requests your Index page, you will refresh the timer, and ensure that you are listening. After X minutes, though, if no users have made a request - you can simply shut down the timer and the associated port.
You are likely not stopping or disposing the Timer. This will cause it to not be garbage collected and stay active for the duration the application stays running.
You should stop and dispose of the Timer within the Controller's Dispose method.
You have several options:
Override Dispose method on the controller and dispose your model with calling Pulses.Dispose()
Override OnActionExecuted method on the controller and do disposing
Create custom action filter and implement OnActionExecuted method and assign it to controller or action.(You can place reference to your model into TempData and then in your ActionFilter check if filterContext.Controller.TempData["MyReferenceToModel"] != null, then use it to dispose timer)
Implement IDisposable interface in your Model and use it inside using statement
Hope this helps,
Dima
You can stop the Timer with JQuery+ MVC.
Jquery can respond to the unload event of the page like so:
$(window).unload(function() {
alert('Handler for .unload() called.');
});
You can make ajax calls to your controllers. We also need to create a property to access the timer. I'll assume you called your Timer Property MyTimer
Timer MyTimer { get; set; }
So you need to create a controller that returns void and calls the Stop() method of your Timer.
[HttpPost]
public void KillTimer()
{
MyTimer.Stop();
}
Now if you add an Ajax call to your unload event we created earlier, then we should be able to kill the timer whenever the page closes.
$.ajax(
{
type: "POST",
url: "/Home/Index",
,
success: function(result)
{
alert("Timer Closed");
},
error : function(req, status, error)
{
alert("Sorry! We could not receive your feedback at this time.");
}
});
The success and error functions are not necessary. I included them only for demonstration.
I also guessed the name of your controller to be Home. You will need to update the URL if it is something different. You could do this with pure javascript. JQuery helps to save you from writing lots of tedious browser compatibility code. (I hear opera is a pain with the unload part)
To address the issue of potential browser crashes and unexpected events you can wire up your controller to check if the timer has exceeded a max time limit.
Good Luck !
Sources :
JQuery Unload()
Invoking ASP.NET MVC Actions from JavaScript using jQuery
JQuery Ajax()

Completed Event not triggering for web service on some systems

This is rather weird issue that I am facing with by WCF/Silverlight application. I am using a WCF to get data from a database for my Silverlight application and the completed event is not triggering for method in WCF on some systems. I have checked the called method executes properly has returns the values. I have checked via Fiddler and it clearly shows that response has the returned values as well. However the completed event is not getting triggered. Moreover in few of the systems, everything is fine and I am able to process the returned value in the completed method.
Any thoughts or suggestions would be greatly appreciated. I have tried searching around the web but without any luck :(
Following is the code.. Calling the method..
void RFCDeploy_Loaded(object sender, RoutedEventArgs e)
{
btnSelectFile.IsEnabled = true;
btnUploadFile.IsEnabled = false;
btnSelectFile.Click += new RoutedEventHandler(btnSelectFile_Click);
btnUploadFile.Click += new RoutedEventHandler(btnUploadFile_Click);
RFCChangeDataGrid.KeyDown += new KeyEventHandler(RFCChangeDataGrid_KeyDown);
btnAddRFCManually.Click += new RoutedEventHandler(btnAddRFCManually_Click);
ServiceReference1.DataService1Client ws = new BEVDashBoard.ServiceReference1.DataService1Client();
ws.GetRFCChangeCompleted += new EventHandler<BEVDashBoard.ServiceReference1.GetRFCChangeCompletedEventArgs>(ws_GetRFCChangeCompleted);
ws.GetRFCChangeAsync();
this.BusyIndicator1.IsBusy = true;
}
Completed Event....
void ws_GetRFCChangeCompleted(object sender, BEVDashBoard.ServiceReference1.GetRFCChangeCompletedEventArgs e)
{
PagedCollectionView view = new PagedCollectionView(e.Result);
view.GroupDescriptions.Add(new PropertyGroupDescription("RFC"));
RFCChangeDataGrid.ItemsSource = view;
foreach (CollectionViewGroup group in view.Groups)
{
RFCChangeDataGrid.CollapseRowGroup(group, true);
}
this.BusyIndicator1.IsBusy = false;
}
Please note that this WCF has lots of other method as well and all of them are working fine.... I have problem with only this method...
Thanks...
As others have noted, a look at some of your code would help. But some things to check:
(1) Turn off "Enable Just My Code" under Debug/Options/Debugging/General, and set some breakpoints in the Reference.cs file, to see whether any of the low-level callback methods there are getting hit.
(2) Confirm that you're setting the completed event handlers, and on the right instance of the proxy client. If you're setting the event handlers on one instance, and making the call on another, that could result in the behavior you're describing.
(3) Poke around with MS Service Trace Viewer, as described here, and see if there are any obvious errors (usually helpfully highlighted in red).
Likely there are other things you could check, but this will keep you busy for a day or so :-).
(Edits made after code posted)
(4) You might want to try defining your ws variable at the class level rather than the function. In theory, having an event-handler defined on it means that it won't get garbage collected, but it's still a little odd, in that once you're out of the function, you don't have a handle to it anymore, and hence can't do important things like, say, closing it.
(5) If you haven't already, try rebuilding your proxy class through the Add Service Reference dialog box in Visual Studio. I've seen the occasional odd problem pop up when the web service has changed subtly and the client wasn't updated to reflect the changes: some methods will get called successfully, others won't.
(6) If you're likely to have multiple instances of a proxy client open at the same time, consider merging them into one instance (and use the optional "object userState" parameter of the method call to pass the callback, so you don't run into the nasty possibility of multiple event handlers getting assigned). I've run into nasty problems in the past when multiple instances were stepping on each other, and my current best practice is to structure my code in such a way that there's only ever one client instance open at a time. I know that's not necessarily what MS says, but it's been my experience.
This issue is because of special characters in one of the fields returned from DB which browser was not able to render. After considerable debug n search over the web, was able to find this out. Used Regular expressions to remove these special characters in WCF, the new returned values from the method was successfully rendered in various browsers on different system. :)
Make sure you have checked 'Generate asynchronous operations' in your service reference. Right-click on the service reference and check the box. This solved it for me.

Earliest access to the .net lifecycle

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.

Categories

Resources