Reputation: 11597
For testing purposes, I have this method:
public ActionResult Index()
{
System.Diagnostics.Debug.Write("Index");
return new HttpNotFoundResult();
}
The method is being called ('Index' is outputted). Somehow, it is causing a HttpException
to be thrown. In my Global.asax file I have an Application_Error
implementation:
void Application_Error(object sender, EventArgs e)
{
Exception exc = Server.GetLastError();
if (exc is System.Web.HttpException)
{
string msg = "UrlReferrer: "
+ Context.Request.UrlReferrer + " UserAgent: " + Context.Request.UserAgent
+ " UserHostAddress: " + Context.Request.UserHostAddress + " UserHostName: "
+ Context.Request.UserHostName;
ErrorHandler.Error(exc.Message, msg);
}
else {
...
}
}
This method is being called after the system has processed the request for Index
. I think that the HttpNotFoundResult
causes the exception to be thrown - or perhaps the exception is thrown for any ActionResult
with a status code of 404.
This is quite annoying, as it is side-stepping the OnException
handler on my controller. For my website, Application_Error
is supposed to be a last-ditch fallback - most normal errors are intended to be handled in other places (by the controllers, or action filters). I only want Application_Error
to log completely unexpected exceptions, or 404s for things like image or .js files.
Is there a way to stop asp.net from throwing exceptions for programatically generated 404s? Alternatively, is there a way to determine in Application_Error
if the HttpException
was caused by a programatically generated 404?
Upvotes: 2
Views: 1183
Reputation: 32758
You can create a custom exception filter that handles 404 exceptions raised by all the actions. You could use HttpContext.Items
collection to track whether it is a programatically raised 404 or not.
Custom exception filter
public class NotFoundExceptionFilter : IExceptionFilter
{
public void OnException(ExceptionContext filterContext)
{
// ignore if the exception is already handled or not a 404
if (filterContext.ExceptionHandled || new HttpException(null, filterContext.Exception).GetHttpCode() != 404)
return;
filterContext.HttpContext.Items.Add("Programmatic404", true);
filterContext.ExceptionHandled = true;
}
}
You need to apply NotFoundExceptionFilter
as a global filter.
Application_Error event
public static void Application_Error(object sender, EventArgs e)
{
var httpContext = ((MvcApplication)sender).Context;
// ignore if it is a programatically raised 404
if(httpContext.Items["Programmatic404"] != null && bool.Parse(httpContext.Items["Programmatic404"].ToString()))
return;
// else, Log the exception
}
Upvotes: 2