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

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.

Related

Recording events(request & response) in an MVC application

Ok, so I have quite a task here:
The background of this project is very complex and fully covered by NDA's so I'll just state what I am trying to do without the background.
So what I need is a way to record every request made to an MVC application and every response from it.
Furthermore, I also need a way to "reply" the requests exactly as they were sent.
I was hoping that I could create some solution that "loads" the MVC application, Self hosts or runs in IIS, get requests, records them and passed them verbatim to the MVC application which would then act exactly like any other MVC app.
I could then create a second solution that "loads" the MVC app but instead of opening it up to request it would read the events from the event store and "replays" them in the MVC app.
Now I have no clue where to even start. This kinda thing is way out of my comfort zone.
If there is another solution for how I can record and replay request (and responses) then please let me know.
Even if there is a way to intercept a request in MVC before it starts doing all of its authentication and routing malarkey then that would be a great starting point. I would also need to know where I can capture the response at the very last second before it is sent.
Many thanks for your time
Andy
A HttpModule would work just fine for your scenario:
using System;
using System.Web;
public class HelloWorldModule : IHttpModule
{
public HelloWorldModule()
{
}
public String ModuleName
{
get { return "HelloWorldModule"; }
}
// In the Init function, register for HttpApplication
// events by adding your handlers.
public void Init(HttpApplication application)
{
application.BeginRequest +=
(new EventHandler(this.Application_BeginRequest));
application.EndRequest +=
(new EventHandler(this.Application_EndRequest));
}
private void Application_BeginRequest(Object source,
EventArgs e)
{
// Create HttpApplication and HttpContext objects to access
// request and response properties.
HttpApplication application = (HttpApplication)source;
HttpContext context = application.Context;
/*...*/
}
private void Application_EndRequest(Object source, EventArgs e)
{
HttpApplication application = (HttpApplication)source;
HttpContext context = application.Context;
/*...*/
}
public void Dispose() { }
}
The code and more information available here.

ASP.NET session drop event

Is theire a way, to get noticed if an asp.net web forms session is droped (For example, the client cloeses the browser = timeout)?
We have one session for the temporary user shopping card:
HttpContext.Current.Session["UserShoppingCard"] = new UserShoppingCard();
Every thing works fine, besides the functions explanied above.
Thank you!
I would try to intercept the Session_End event in the global.asax file and put some logging in there, it might not happen right when the browser is closed but it will happen at some point anyway once the session is terminated and you can include your logic in there.
In fact the server never knows when a browser is closed or if instead a connection issue is making the client unable to connect.
As said before, complementing with code...
public class Global : System.Web.HttpApplication
{
protected void Session_End(object sender, EventArgs e)
{
//Do your things here when session ends...
}
}

How to remove a timer, after a session ends?

I'm implementing an auto-refresh feature on a asp.net website.
The user does the login on the website, and if he goes to a specific page, which has a table that needs to be refreshed, a timer is created that refreshes the table.
But when the user logs out or the session expires, the timer keeps running. Now multiply this for X users, and we will have X timers running on the server.
What's the best way to get rid of the timers when they're no longer needed?
So far my code is the following:
protected static System.Timers.Timer _timer;
protected void Page_Load(object sender, EventArgs e)
{
...
ServiceStatus serv = new ServiceStatus();
OutSubscricoesInfoV2 subscr = new OutSubscricoesInfoV2();
serv = StreamerUtils.GetSubscricoesStreamer(ref subscr);
if (serv != null && serv.success)
{
StreamerUtils.StreamerState strState = StreamerUtils.GetStreamerState(subscr);
if (strState != null && strState.IsActive)
{
startAutoRefresh();
}
}
}
private void startAutoRefresh()
{
if (Session["RefreshTimer"] == null)
{
_timer = new System.Timers.Timer(10000);
_timer.Elapsed += new ElapsedEventHandler(OnTimedEvent);
_timer.Enabled = true;
Session["RefreshTimer"] = _timer;
}
}
private static void OnTimedEvent(object source, ElapsedEventArgs e)
{
//TODO: call refresh function
}
In my page, i have the following button which the user can click to refresh the table:
<asp:ImageButton runat="server" ID="RefreshCot" OnClientClick="javascript:StocksListControl.TriggerPostBack(); return false;" CausesValidation="false" ImageUrl="/_layouts/images/refresh-title.png" />
I agree with the first comment to your question posted by Aristos, this is bad design.
For this situation I would suggest three options:
Use a asp.net Ajax control. An example can be found here: http://www.tutorialspoint.com/asp.net/asp.net_ajax_control.htm
AJAX poling - Have the timers in JavaScript which will sit on the clients. Once the timer has passed its elapsed time, the client will make an AJAX request to the server (preferably calling a web service) to fetch the updated data. I would recommend using a JavaScript library for this such as JQuery. The documentation on their ajax function is found here:
http://api.jquery.com/jQuery.ajax/
Consider using a library that provides real time functionality such as SignalR, here is a link to the libraries site:
http://signalr.net/
Now for the personal opinions; Of all 3 options, the 3rd will provide you with the most "elegant" solution.
The 1st option will require you to use asp.net AJAX controls, which produce ugly HTML and can be a pig to work with. Also, timers on the client will be created which remove the true "real-time" aspects.
The 2nd option will again put timers on the client, removing the true "real-time" aspects.
The 3rd option, will allow the server to be "aware" of connected clients, data shall be pushed to the clients, when available, via the use of "Hubs".
Whilst your'e at this learning curve crossroad, I would also recommend looking into some client side JavaScript design patterns to help structure your code on the clients. A great tool to use could be Knockout, found here:
http://knockoutjs.com/index.html
Here is a tutorial on how to use this with SignalR:
http://www.codeproject.com/Articles/322154/ASP-NET-MVC-SIngalR-and-Knockout-based-Real-time-U
The tutorial focuses on using ASP.NET MVC. I imagine this should be interchangeable with web forms, however, if the option is available to you I would recommend using MVC also.

HttpModule Init method is called several times - why?

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.

How to prevent HTTP GET for ASP.NET events? or How to check for Request.Type on all events?

With the help of fiddler, I did this "replay attack" with the following HTTP GET request
http://svr/Default.aspx?__EVENTTARGET=LinkButton1&__EVENTARGUMENT=&__VIEWSTATE=%2snipg%3D%3D&__EVENTVALIDATION=%2snip
To my surprise, it works as long as there is valid viewstate and event validation. The following stops GET on my click event, but...
protected void BtnUploadClick(object sender, EventArgs e)
{
if(Request.RequestType == "GET") throw new HttpException(405, "GET not allowed for this.");
}
I have events all over my code. Is there a way to globally add this behavior to events that are normally postback events?
You can yes. Attach to application's PreRequestHandlerExecute event. Do it either as a separate HttpModule or in Global.asax.
In event hadler you can either check:
_EVENTTARGET_ , _VIEWSTATE_ are not part of Request.QueryString property (on each request)
on GET you can check that Request.Form is empty. Because asp.net only posts a form on POST actions.
Accepted answer has solved very well the issue for me.
As it only contains some suggestions, I would like to post my own answer with an example of implementation, hoping it will be helpful for somebody (the method name is the one to use for Global.asax, for a httpmodule feel free to adapt) :
public void Application_PreRequestHandlerExecute(Object sender, EventArgs e)
{
// The code below is intended to block incoming HTTP GET requests which contains in query string parameters intended to be used in webform POST
if (Request.HttpMethod != "GET")
{
return; // Nothing to do
}
var hasPostParams = (Request.QueryString["__EVENTTARGET"] ??
Request.QueryString["__VIEWSTATE"] ??
Request.QueryString["__EVENTARGUMENT"] ??
Request.QueryString["__EVENTVALIDATION"]) != null;
if (hasPostParams)
{
// TODO : log error (I suggest to also log HttpContext.Current.Request.RawUrl) and throw new exception
}
}
Assuming you never want to process GETs for this particular application on certain page types you can disable GET for the various pages in your application using IIS. Under the Properties pane for the site or application click on Home Directory and then Configuration (assuming an application is configured) then click on the ASPX or other extension and you can limit the verbs in use for that extension.

Categories

Resources