ASP.NET MVC 5 - Как я могу изменить маршрут в httpErrors?

Я пытаюсь обработать ошибки HTTP на сайте MVC5 следующим образом:

web.config:

<system.webServer>
    <httpErrors errorMode="Custom" existingResponse="Replace">
      <clear/>
      <error statusCode="403" path="/language/Error/Details/403" responseMode="ExecuteURL"/>
      <error statusCode="404" path="/language/Error/Details/404" responseMode="ExecuteURL"/>
      <error statusCode="500" path="/language/Error/Details/500" responseMode="ExecuteURL"/>
    </httpErrors>
</system.webServer>

ErrorController.cs:

// GET: Error/Details
public ActionResult Details()
{
    /* Setting the language for the errors since it is not possible to handle multi-language errors in the web.config file where the errors are redirected */
    if (!CultureHelper.cultures.Contains(base.culture))
    {
        RouteData.Values["culture"] = CultureHelper.GetCurrentNeutralCulture();
    }

    /* Redirecting uncontrolled errors to 404 error */
    if (RouteData.Values["statusCode"] == null)
    {
        return RedirectToRoute(new { culture = base.culture, controller = "Error", action = "Details", statusCode = 404 });
    }

    /* Preparing the model */
    ErrorViewModel error = ErrorFactory.Create(Convert.ToInt32(RouteData.Values["statusCode"]));


    /* Preparing the view */
    base.SetLanguageFromRoute();

    return View(error);
}

RouteConfig.cs:

public static void RegisterRoutes(RouteCollection routes)
{
    routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

    routes.MapRoute(
        name: "Default",
        url: "{culture}/{controller}/{action}/{id}",
        defaults: new { culture = CultureHelper.GetCurrentNeutralCulture(), controller = "User", action = "Home", id = UrlParameter.Optional }
    );

    routes.MapRoute(
        name: null,
        url: "{culture}/Error/Details/{statusCode}",
        defaults: new { culture = CultureHelper.GetCurrentNeutralCulture() }
    );
}

Моя проблема в том, что когда вызывается действие Details GET, как только оно достигает этой строки:

if (RouteData.Values["statusCode"] == null)

Он всегда возвращает true, потому что нет ключа "statusCode" в RouteData так как он использует маршрут по умолчанию вместо маршрута ошибки, и statusCode передается по маршруту с именем "id" (ключ маршрута по умолчанию).

Я знаю, что могу просто использовать маршрут по умолчанию и поймать код состояния из идентификатора, но у меня есть этот собственный маршрут, когда я делаю RedirectToRoute к ошибке от других контроллеров, поэтому я хотел бы использовать это здесь. Есть ли способ сказать <httpErrors> что я хочу использовать маршрут, отличный от маршрута по умолчанию?

1 ответ

Можно ли сказать, что я хочу использовать маршрут, отличный от маршрута по умолчанию?

Да. Есть 2 способа.

Наиболее разумным способом является размещение определенных маршрутов перед общими маршрутами, чтобы в таблице маршрутов не было недоступных путей выполнения. Это гарантирует, что ваши входящие URL будут направлены на правильный контроллер.

Это означает, что вам нужно указать более конкретный пользовательский маршрут перед маршрутом по умолчанию, чтобы он был проверен первым.

public static void RegisterRoutes(RouteCollection routes)
    {
        routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

        routes.MapRoute(
            name: "Error",
            url: "{culture}/Error/Details/{statusCode}",
            defaults: new { culture = CultureHelper.GetCurrentNeutralCulture() }
        );

        routes.MapRoute(
            name: "Default",
            url: "{culture}/{controller}/{action}/{id}",
            defaults: new { culture = CultureHelper.GetCurrentNeutralCulture(), controller = "User", action = "Home", id = UrlParameter.Optional }
        );
    }

Другой способ - указать название маршрута при звонке. RedirectToRouteResult, Обратите внимание, что вы не дали своему маршруту имя (оно пустое), поэтому у вас нет возможности сделать это, если вы не назовете его, как указано выше.

return RedirectToRoute(
    routeName: "Error", 
    routeValues: new { culture = base.culture, controller = "Error", action = "Details", statusCode = 404 });

Это перенаправит вас на правильный URL-адрес, но, вероятно, все еще не будет работать, потому что при обращении к URL-адресу он все равно попадет на ваш маршрут по умолчанию, так как он соответствует этому URL-адресу и регистрируется первым.

Другие вопросы по тегам