Recording events(request & response) in an MVC application - c#

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.

Related

Communication layer between client and server

I'd like to know if there is any technology to control communications between the client and the server in a web application (ASP.NET)
Example:
Number of requests
Check that no repeat a request
Check that an operation was performed
WorkFlow
The client sends the request "A"
The server receives the request "A", and responds
The server marks the request "A" as answered
The client resends the request "A"
The server answers that the request "A" was answered
You could intercept the request in the following method, in the Global.asax file:
protected void Application_BeginRequest(object sender, EventArgs e)
{
var request = ((System.Web.HttpApplication)(sender)).Context.Request;
//here you can evaluate and take decisions about the request
}
In any ASP.NET application you can use the HttpApplication events to track the needed changes. For example, you could track it using the BeginRequest and/or EndRequest events:
protected void Application_BeginRequest(object sender, EventArgs e)
{
if(MyGlobalFlags.TrackingRequests){
// do stuff
}
}
protected void Application_EndRequest(object sender, EventArgs e)
{
if(MyGlobalFlags.TrackingRequests){
// do stuff
}
}
By personal opinion, I would use a globlal flag that I could turn off easily if I wanted.
If you are talking about an ASP.NET MVC application, I would also recommend using ActionFilters in the actions you want to track. You could implement your own ActionFilter class and track those changes OnActionExecuted and/or OnResultExecuted. I would still use the global flag to turn off the tracking without changing code.
public class MyTrackingActionFilter: ActionFilterAttribute{
public override OnActionExecuted(ActionExecutedContext filterContext)
{
if(MyGlobalFlags.TrackingRequests){
// do stuff
}
}
public override OnResultExecuted(ActionExecutedContext filterContext)
{
if(MyGlobalFlags.TrackingRequests){
// do stuff
}
}
}
As a note, I wouldn't try to do heavy stuff in these events. If the track requires heavy database manipulation that can run in parallel, I recommend you to use a queue system while using the thread pool.

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.

ASP.net HttpHandler long running ProcessRequest doesn't end on App recycle

I'm trying to implement an HttpStreaming comet push server in ASP.net. I am implementing an IHttpAsyncHandler that holds onto an http request and periodically sends messages down to the connected client. The connection with the client can be held open for a very long time (lets say 30 minutes). The issue that I am having is that since I don't end the request for a very long time, the handler technical is still running. So when the app pool recycles or ends, my asp.net application doesn't end gracefully. Meaning, Application_End never gets called in Global.asax since it is waiting for all handlers to complete before it gets called. My handler hasn't completed yet since it is holding on to the request. Eventually, the application just gets killed by IIS.
Here a sample HttpHandler that runs infinitely until something tells it to stop.
public class StreamingSocketHandler3 : IHttpHandler
{
private static readonly AppDomainShutdown Instance = AppDomainShutdown.Instance;
public void ProcessRequest(HttpContext context)
{
long c = 1;
bool stop = false;
Instance.OnStop += delegate()
{
stop = true;
};
while (!stop)
{
LogThis.Log.LogThis("loop: " + c, LogThis.eloglevel.debug);
c++;
System.Threading.Thread.Sleep(1000);
}
}
public bool IsReusable
{
get
{
return true;
}
}
}
If a client connects to this handler and then I stop the app pool, the web app doesn't end until the app gets completely killed by IIS sometime later.
The obvious answer to this problem is to listen to some sort of application end event and then end the request. I can't hook into Global.asax Application_end as it doesn't get called until the handler ends. The following blog post (link) provides some other alternatives (see q5 at the end of the post). I have tried the AppDomain.DomainUnload event suggest with no luck. I have also tried the IRegisteredObject interface suggested. That doesn't work either. I have built the following class that implements IRegisteredObject for testing.
public sealed class AppDomainShutdown : IRegisteredObject
{
public event Action OnStop;
// Singleton reference
public static readonly AppDomainShutdown Instance = new AppDomainShutdown();
// Singleton private Constructor
private AppDomainShutdown()
{
// Register the object
HostingEnvironment.RegisterObject(this);
}
public void Stop(bool immediate)
{
// Whats it want us to do?
if (!immediate)
{
// Do some code to handle graceful
// if OK
LogThis.Log.LogThis("Not Immediate Stop called", LogThis.eloglevel.debug);
OnStop();
HostingEnvironment.UnregisterObject(this);
}
else
{
// Do some code to force down (THREAD.ABORT)
// Mandatory
LogThis.Log.LogThis("Immediate Stop called", LogThis.eloglevel.debug);
OnStop();
HostingEnvironment.UnregisterObject(this);
}
}
}
If I make a call to this class from Global.asax without the handler starting, I get the application stop notification as expected. However, placing the same call in the HttpHandler (see the handler code), the OnStop event never fires.
What's frustrating is that I have seen a couple of forums posts on the web were the posts had my exact issue and the poster supposedly was able to implement IRegisteredObject and end the HttpRequest so the app could shutdown.
Please note that the HttpHandler code I'm presenting is simply for testing that I can end the ProcessRequest method in response to the application ending.

How would an HttpModule for Custom Authentication interact with Windows Authentication?

I am trying to create a custom HttpModule which controls which users can view a site.
I am trying to leverage Windows Authentication to do this.
On an individual page, I would probably do something like this:
if (HttpContext.Current.User.Identity.Name.Contains("jsmith"))
{
Response.Write("You do not have the correct permissions to view this site.");
Response.End();
}
But because I want to make this more configurable at the application level, I would like to use an HttpModule.
Here is the start that I have made on the code:
using System;
using System.Web;
public class CustomAuthHttpModule : IHttpModule
{
public void Dispose() { }
public void Init(HttpApplication context)
{
context.BeginRequest += new EventHandler(OnBeginRequest);
context.EndRequest += new EventHandler(OnEndRequest);
}
void OnBeginRequest(object sender, EventArgs e) { }
void OnEndRequest(object sender, EventArgs e)
{
HttpApplication appObject = (HttpApplication)sender;
HttpContext contextObject = appObject.Context;
if (contextObject.User.Identity.Name.Contains("jsmith"))
{
contextObject.Response.Clear();
contextObject.Response.End();
}
}
}
I would be fine with using the code I have, if I could put it in the OnBeginRequest() function. But the User property is not created in the HttpContext object until OnEndRequest() runs.
Running the code earlier would prevent the application from doing the extra work of producing this output, since some users are just going to be blocked from access in the end.
Can someone suggest a solution to this - is this happening because my module is running before the Windows Auth module, or what?
... or, maybe there is an easier way to do what I am trying to do with IIS or file system permissions?
You want the AuthenticateRequest event.
AuthenticateRequest event
Have you tried to implement the method in the global.aspx? OnSessionStart?
Besides I would use hasRole or some other group-Property instead of contains and username.
Why write an http module for this. If this is asp.net web forms then why not simply use built in stuff like LoginView http://msdn.microsoft.com/en-us/library/system.web.ui.webcontrols.loginview.aspx

Custom C# HttpModule Infinite Redirect Loop

I am writing a custom c# HttpModule that will handle requests from all file types. As a simple proof of concept I have setup the module by adding a reference to the httpModules section of the web config and added application extensions for the demo IIS website with a reference to the aspnet_isapi.dll so that it currently only intercepts request for ".htm" files
But even if there is no significant code in the "OnBeginRequest" event (code below) it causes an infinite redirect loop. I am using IIS 5 on XP Anyone got any ideas?
So far I have only seen HttpModule examples for use with ASPX files but surely you can configure the for any file type?
#region IHttpModule Members
public void Dispose() { }
public void Init(HttpApplication context)
{
context.BeginRequest += new EventHandler(OnBeginRequest);
}
///
///
///
///
public void OnBeginRequest(Object s, EventArgs e)
{
HttpApplication context = s as HttpApplication;
Uri currentURL = context.Request.Url;
string pageName = currentURL.Segments.Last().ToLower();
}
#endregion
OK. The problem was actually in the HttpModule itself.
It appears that you have to use the HttpApplication context in order for it to render on the client.
For Example after you have performed all your custom logic you need to write to the context:
context.Response.Write("/n/r");
//or
context.Response.Redirect("test.htm");
Everything then renders as you would expect

Categories

Resources