Is there a way for me to catch all incoming requests to my ASP.NET MVC 4 app and run some code before continuing the request onward to the specified control
I think that what you search for is this:
Application_BeginRequest()
http://www.dotnetcurry.com/showarticle.aspx?ID=126
You put it in Global.asax.cs
.
protected void Application_BeginRequest(object sender, EventArgs e)
{
HttpContext.Current.Request.....;
}
I use this for debugging purposes but I am not sure how good solution it is for your case.
The most correct way would be to create a class that inherits ActionFilterAttribute and override OnActionExecuting
method. This can then be registered in the GlobalFilters
in Global.asax.cs
Of course, this will only intercept requests that actually have a route.
I'm not sure about MVC4 but I think it is fairly similar to MVC5. If you have created a new web project -> look in Global.asax
and you should see the following line FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
in the method Application_Start()
.
RegisterGlobalFilters
is a method in the file FilterConfig.cs
located in the folder App_Start
.
As @YngveB-Nilsen said ActionFilterAttribute
is the way to go in my opinion. Add a new class that derives from System.Web.Mvc.ActionFilterAttribute
. This is important because System.Web.Http.Filters.ActionFilterAttribute
will fail with the following exception for example.
The given filter instance must implement one or more of the following filter interfaces: System.Web.Mvc.IAuthorizationFilter, System.Web.Mvc.IActionFilter, System.Web.Mvc.IResultFilter, System.Web.Mvc.IExceptionFilter, System.Web.Mvc.Filters.IAuthenticationFilter.
Example that writes the request to the debug window:
public class DebugActionFilter : System.Web.Mvc.ActionFilterAttribute
{
public override void OnActionExecuting(ActionExecutingContext actionContext)
{
Debug.WriteLine(actionContext.RequestContext.HttpContext.Request);
}
}
In FilterConfig
-> RegisterGlobalFilters
-> add the following line: filters.Add(new DebugActionFilter());
.
You can now catch all incoming requests and modify them.
You can use a HttpModule to accomplish this. Here is a sample I use to calculate the process time for all requests:
using System;
using System.Diagnostics;
using System.Web;
namespace Sample.HttpModules
{
public class PerformanceMonitorModule : IHttpModule
{
public void Init(HttpApplication httpApp)
{
httpApp.BeginRequest += OnBeginRequest;
httpApp.EndRequest += OnEndRequest;
httpApp.PreSendRequestHeaders += OnHeaderSent;
}
public void OnHeaderSent(object sender, EventArgs e)
{
var httpApp = (HttpApplication)sender;
httpApp.Context.Items["HeadersSent"] = true;
}
// Record the time of the begin request event.
public void OnBeginRequest(Object sender, EventArgs e)
{
var httpApp = (HttpApplication)sender;
if (httpApp.Request.Path.StartsWith("/media/")) return;
var timer = new Stopwatch();
httpApp.Context.Items["Timer"] = timer;
httpApp.Context.Items["HeadersSent"] = false;
timer.Start();
}
public void OnEndRequest(Object sender, EventArgs e)
{
var httpApp = (HttpApplication)sender;
if (httpApp.Request.Path.StartsWith("/media/")) return;
var timer = (Stopwatch)httpApp.Context.Items["Timer"];
if (timer != null)
{
timer.Stop();
if (!(bool)httpApp.Context.Items["HeadersSent"])
{
httpApp.Context.Response.AppendHeader("ProcessTime",
((double)timer.ElapsedTicks / Stopwatch.Frequency) * 1000 +
" ms.");
}
}
httpApp.Context.Items.Remove("Timer");
httpApp.Context.Items.Remove("HeadersSent");
}
public void Dispose() { /* Not needed */ }
}
}
And this is how you register the module in Web.Config:
<system.webServer>
<modules runAllManagedModulesForAllRequests="true">
<add name="PerformanceMonitorModule" type="Sample.HttpModules.PerformanceMonitorModule" />
</modules>
<//system.webServer>