我有一个asp.net MVC 5项目,我试图抛出404错误而不是500错误。
错误是
公共行动方法'某事物'在控制器上找不到 ' ProjetX.Controllers.HomeController'
和
路径控制器' /某些'未找到或未执行 一个IController
我理解为什么它会出现错误500,但我想抛出404.这对SEO来说会更好。
我无法弄清楚如何
这是我的代码
我的elmah的ExceptionHandler类
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);
}
}
我如何添加自定义错误
public static void RegisterGlobalFilters(GlobalFilterCollection filters)
{
filters.Add(new HandleCustomError());
}
路线配置
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();
}
我的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>
我想处理HandleCustomError类中的错误,但问题是它直接进入错误控制器中的Error500操作。
奇怪的是,错误仍记录在elmah中。
它没有触及HandleCustomError类中的任何断点,如何记录错误?
谢谢
答案 0 :(得分:1)
这是最终的代码
我必须添加2个函数来生成一个带有我的控制器和动作名称的正则表达式
public class RouteConfig
{
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
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}$", controller = GetAllControllersAsRegex(), action = GetAllActionsAsRegex }
);
routes.MapRoute(
"Default",
"{controller}/{action}/{id}",
new { controller = "Home", action = "Index", id = UrlParameter.Optional },
new { controller = GetAllControllersAsRegex(), action = GetAllActionsAsRegex() }
);
routes.MapRoute(
"NotFound",
"{*url}",
new { controller = "Error", action = "Error404" }
);
routes.MapMvcAttributeRoutes();
}
private static string GetAllControllersAsRegex()
{
var controllers = typeof(MvcApplication).Assembly.GetTypes()
.Where(t => t.IsSubclassOf(typeof(Controller)));
var controllerNames = controllers
.Select(c => c.Name.Replace("Controller", ""));
return string.Format("({0})", string.Join("|", controllerNames));
}
private static string GetAllActionsAsRegex()
{
Assembly asm = Assembly.GetExecutingAssembly();
var actions = asm.GetTypes()
.Where(type => typeof(Controller).IsAssignableFrom(type)) //filter controllers
.SelectMany(type => type.GetMethods())
.Where(method => method.IsPublic && !method.IsDefined(typeof(NonActionAttribute)))
.Select(x=>x.Name);
return string.Format("({0})", string.Join("|", actions));
}
}