2015-03-23 4 views
0

У меня есть asp.net MVC проект 5, и я пытаюсь бросить ошибку 404 вместо 500.Ошибка 500 вместо 404

Ошибки

Общественное действие метод «что-то 'не был найден на контроллере 'ProjetX.Controllers.HomeController'

и

Контроллер для пути «/ что-то» не найден или не реализует IController

Я понимаю, почему это ошибка 500, но я хотел бы бросить 404. Было бы лучше для SEO.

Я не могу понять, как

Вот мой код

Мой класс ExceptionHandler для 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()); 
     } 

маршрутам 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(); 
     } 

Мой 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

Вы не можете вернуть 404 в Ошибка500 в контроллере ошибок? –

+0

Как узнать, действительно ли это ошибка 500 или те две ошибки в контроллере ошибок? – Marc

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

Смотрите также
https://stackoverflow.com/a/4668252

+0

Это выглядит интересно. Я изучу его, когда я получу некоторое время. –

+0

Не могли бы вы написать свой комментарий о маршруте catch-all в качестве ответа, я дам вам точки plz – Marc

+0

Это не похоже на то, что весь маршрут играл большую часть роли в решении. –

 Смежные вопросы

  • Нет связанных вопросов^_^