错误 500 而不是 404

Error 500 instead of 404

我有一个 asp.net MVC 5 项目,我试图抛出 404 错误而不是 500。

错误是

A public action method 'something' was not found on controller 'ProjetX.Controllers.HomeController'

The controller for path '/something' was not found or does not implement IController

我明白为什么是错误 500,但我想抛出一个 404。这对 SEO 会更好。

我不知道怎么办

这是我的代码

我的 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);
        }

    }

我如何添加自定义错误

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();
        }

我的网络配置

<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 class 中处理错误,但问题是它会直接进入我在错误控制器中的 Error500 操作。

奇怪的是elmah中仍然记录错误。

在 HandleCustomError class 中没有遇到任何断点,如何记录错误?

谢谢

这是有效的最终代码

我必须添加 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)); 
    }
}

另请参阅