I have an asp.net MVC 5 project and I'm trying to throw a 404 error instead of 500.
The errors are
A public action method 'something' was not found on controller 'ProjetX.Controllers.HomeController'
and
The controller for path '/something' was not found or does not implement IController
I understand why it's an error 500 but I would like to throw a 404. It would be better for SEO.
I can't figure out how to
Here's my code
My ExceptionHandler class for elmah
public class HandleCustomError : HandleErrorAttribute
{
public override void OnException(ExceptionContext filterContext)
{
//If the exeption is already handled we do nothing
if (filterContext.ExceptionHandled)
{
return;
}
else
{
//Log the exception with Elmah
Log(filterContext);
Type exceptionType = filterContext.Exception.GetType();
//If the exception is while an ajax call
if (exceptionType == typeof(ExceptionForAjax))
{
filterContext.HttpContext.Response.Clear();
filterContext.HttpContext.Response.ContentEncoding = Encoding.UTF8;
filterContext.HttpContext.Response.HeaderEncoding = Encoding.UTF8;
filterContext.HttpContext.Response.TrySkipIisCustomErrors = true;
filterContext.HttpContext.Response.StatusCode = 500;
filterContext.HttpContext.Response.StatusDescription = filterContext.Exception.Message;
}
else
{
base.OnException(filterContext);
}
}
//Make sure that we mark the exception as handled
filterContext.ExceptionHandled = true;
}
private void Log(ExceptionContext context)
{
// Retrieve the current HttpContext instance for this request.
HttpContext httpContext = context.HttpContext.ApplicationInstance.Context;
if (httpContext == null)
{
return;
}
// Wrap the exception in an HttpUnhandledException so that ELMAH can capture the original error page.
Exception exceptionToRaise = new HttpUnhandledException(message: null, innerException: context.Exception);
// Send the exception to ELMAH (for logging, mailing, filtering, etc.).
ErrorSignal signal = ErrorSignal.FromContext(httpContext);
signal.Raise(exceptionToRaise, httpContext);
}
}
How I add the custom errors
public static void RegisterGlobalFilters(GlobalFilterCollection filters)
{
filters.Add(new HandleCustomError());
}
The routes config
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute("Robots.txt",
"robots.txt",
new { controller = "robot", action = "index" });
routes.MapRoute(
name: "Localization",
url: "{lang}/{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional },
constraints: new { lang = @"^[a-zA-Z]{2}$" }
);
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
routes.MapRoute(
"NotFound",
"{*url}",
new { controller = "Error", action = "Error404" }
);
routes.MapMvcAttributeRoutes();
}
My webconfig
<system.web>
<authentication mode="None" />
<compilation debug="true" targetFramework="4.5" />
<!-- 2MB-->
<httpRuntime targetFramework="4.5" maxRequestLength="2097152" />
<httpModules>
<add name="ErrorLog" type="Elmah.ErrorLogModule, Elmah" />
<add name="ErrorMail" type="Elmah.ErrorMailModule, Elmah" />
<add name="ErrorFilter" type="Elmah.ErrorFilterModule, Elmah" />
</httpModules>
<!-- Set mode to RemoteOnly in production -->
<customErrors mode="On" redirectMode="ResponseRewrite" defaultRedirect="/Error/Error500">
<error statusCode="400" redirect="/Error/Error400" />
<error statusCode="404" redirect="/Error/Error404" />
<error statusCode="500" redirect="/Error/Error500" />
</customErrors>
</system.web>
<system.webServer>
<httpErrors errorMode="Custom" existingResponse="Replace">
<remove statusCode="400" subStatusCode="-1" />
<error statusCode="400" path="/Error/Error400" responseMode="ExecuteURL" />
<remove statusCode="404" subStatusCode="-1" />
<error statusCode="404" path="/Error/Error404" responseMode="ExecuteURL" />
<remove statusCode="500" subStatusCode="-1" />
<error statusCode="500" path="/Error/Error500" responseMode="ExecuteURL" />
</httpErrors>
<modules>
<remove name="FormsAuthenticationModule" />
<add name="ErrorLog" type="Elmah.ErrorLogModule, Elmah" preCondition="managedHandler" />
<add name="ErrorMail" type="Elmah.ErrorMailModule, Elmah" preCondition="managedHandler" />
<add name="ErrorFilter" type="Elmah.ErrorFilterModule, Elmah" preCondition="managedHandler" />
</modules>
<validation validateIntegratedModeConfiguration="false" />
<handlers>
<remove name="ExtensionlessUrlHandler-Integrated-4.0" />
<remove name="OPTIONSVerbHandler" />
<remove name="TRACEVerbHandler" />
<add name="ExtensionlessUrlHandler-Integrated-4.0" path="*." verb="*" type="System.Web.Handlers.TransferRequestHandler" preCondition="integratedMode,runtimeVersionv4.0" />
<add name="Robots-ISAPI-Integrated-4.0" path="/robots.txt" verb="GET" type="System.Web.Handlers.TransferRequestHandler" preCondition="integratedMode,runtimeVersionv4.0" />
</handlers>
<staticContent>
</staticContent>
</system.webServer>
I wanted to handle the error in the HandleCustomError class but the problem is that it goes straight to my Error500 action in the error controller.
What's weird is that the error is still logged in elmah.
It doesn't hit any breakpoint inside the HandleCustomError class, how can the error be logged?
Thank you