我正在尝试以这种方式处理MVC5站点中的HTTP错误:
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>
错误控制器.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);
}
路由配置.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,因为RouteData
中没有"statusCode"键,因为它使用的是默认路由而不是错误路由,并且statusCode
在路由中传递名称为"id"(默认路由键)。
我知道我可以使用默认路由并从 ID 中捕获状态代码,但是当我对来自其他控制器的错误进行RedirectToRoute
时,我有该自定义路由,所以我想在这里使用它。有什么方法可以告诉<httpErrors>
我想使用与默认路由不同的路由?
有没有办法告诉我想使用与默认路由不同的路由?
是的。有两种方法。
最明智的方法是将特定路由放在常规路由之前,这样路由表中就不会有无法访问的执行路径。这可确保传入的 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
时指定路由名称。请注意,您没有为您的路由命名(它是 null),因此除非您按照我上面所说的方式命名它,否则您无法执行此操作。
return RedirectToRoute(
routeName: "Error",
routeValues: new { culture = base.culture, controller = "Error", action = "Details", statusCode = 404 });
这会将您重定向到正确的 URL,但可能仍然不起作用,因为当访问 URL 时,它仍然会命中您的"默认"路由,因为它与此 URL 匹配并且首先注册。