直接行动代替 404 页面
Direct to action in lieu of 404 page
我正在制作一个单页应用程序,我设置它的方式是在 OnActionExecuting() 方法中使用基本控制器,我将非 ajax 请求重定向到主页索引操作.该路径仍将存在并用作指示 javascript 做什么。
这对于像 /login 这样的东西很好用,如果我没有使用我提到的技术阻止它,实际上有一个 /login 页面通常可以访问。
然而,当我更进一步并使用 /some/other/meaningful/but/bogus/url 时,它没有 route/controller 但对 javascript 有一定意义,我收到 404 错误。
很明显,我想做的是,在那种 404 情况下,我只想加载主页索引操作。或者,替换我的 ajax 阻塞,将所有路径重定向到 home index 操作(除非它们是用 ajax 调用的有效路由)将有相同的结果。
我搜索过类似的答案,不幸的是,相同的措辞经常用于描述有关自定义 404 页面的问题,因此很难搜索。
您确实想要自定义错误页面。不同之处在于您的自定义错误页面是 controller/action。自定义错误页面不必是像 notfound.html
这样的页面,它只是一个 url,因此您可以将 url 设置为控制器操作。
下面的代码会将未处理的状态代码重定向到“/home”,即家庭控制器。然后对于 404 它将转到 /controller/action ,它可能是 /home/notfound
.
<system.web>
<customErrors mode="RemoteOnly" defaultRedirect="/home">
<error statusCode="404" redirect="/controller/action"/>
</customErrors>
</system.web>
非重定向路由,在你的global.asax.cs
添加如下代码。这个例子可能有点重,但基本上实现了你想要的,因为自定义错误控制器被执行但 URL 没有改变。
protected void Application_Error(object sender, EventArgs e)
{
var httpContext = ((MvcApplication)sender).Context;
var currentController = " ";
var currentAction = " ";
var currentRouteData = RouteTable.Routes.GetRouteData(new HttpContextWrapper(httpContext));
if (currentRouteData != null)
{
if (currentRouteData.Values["controller"] != null && !String.IsNullOrEmpty(currentRouteData.Values["controller"].ToString()))
{
currentController = currentRouteData.Values["controller"].ToString();
}
if (currentRouteData.Values["action"] != null && !String.IsNullOrEmpty(currentRouteData.Values["action"].ToString()))
{
currentAction = currentRouteData.Values["action"].ToString();
}
}
var ex = Server.GetLastError();
var controllerFactory = ControllerBuilder.Current.GetControllerFactory();
var controller = (Controller)controllerFactory.CreateController(httpContext.Request.RequestContext, "Error");
var routeData = new RouteData();
var action = "Index";
if (ex is HttpException)
{
var httpEx = ex as HttpException;
switch (httpEx.GetHttpCode())
{
case 401:
action = "Unauthorized";
break;
case 403:
action = "Forbidden";
break;
case 404:
action = "NotFound";
break;
default:
break;
}
}
httpContext.ClearError();
httpContext.Response.Clear();
httpContext.Response.StatusCode = ex is HttpException ? ((HttpException)ex).GetHttpCode() : 500;
httpContext.Response.TrySkipIisCustomErrors = true;
routeData.Values["controller"] = "Error";
routeData.Values["action"] = action;
controller.ViewData.Model = new HandleErrorInfo(ex, currentController, currentAction);
((IController)controller).Execute(new RequestContext(new HttpContextWrapper(httpContext), routeData));
}
我正在制作一个单页应用程序,我设置它的方式是在 OnActionExecuting() 方法中使用基本控制器,我将非 ajax 请求重定向到主页索引操作.该路径仍将存在并用作指示 javascript 做什么。
这对于像 /login 这样的东西很好用,如果我没有使用我提到的技术阻止它,实际上有一个 /login 页面通常可以访问。
然而,当我更进一步并使用 /some/other/meaningful/but/bogus/url 时,它没有 route/controller 但对 javascript 有一定意义,我收到 404 错误。
很明显,我想做的是,在那种 404 情况下,我只想加载主页索引操作。或者,替换我的 ajax 阻塞,将所有路径重定向到 home index 操作(除非它们是用 ajax 调用的有效路由)将有相同的结果。
我搜索过类似的答案,不幸的是,相同的措辞经常用于描述有关自定义 404 页面的问题,因此很难搜索。
您确实想要自定义错误页面。不同之处在于您的自定义错误页面是 controller/action。自定义错误页面不必是像 notfound.html
这样的页面,它只是一个 url,因此您可以将 url 设置为控制器操作。
下面的代码会将未处理的状态代码重定向到“/home”,即家庭控制器。然后对于 404 它将转到 /controller/action ,它可能是 /home/notfound
.
<system.web>
<customErrors mode="RemoteOnly" defaultRedirect="/home">
<error statusCode="404" redirect="/controller/action"/>
</customErrors>
</system.web>
非重定向路由,在你的global.asax.cs
添加如下代码。这个例子可能有点重,但基本上实现了你想要的,因为自定义错误控制器被执行但 URL 没有改变。
protected void Application_Error(object sender, EventArgs e)
{
var httpContext = ((MvcApplication)sender).Context;
var currentController = " ";
var currentAction = " ";
var currentRouteData = RouteTable.Routes.GetRouteData(new HttpContextWrapper(httpContext));
if (currentRouteData != null)
{
if (currentRouteData.Values["controller"] != null && !String.IsNullOrEmpty(currentRouteData.Values["controller"].ToString()))
{
currentController = currentRouteData.Values["controller"].ToString();
}
if (currentRouteData.Values["action"] != null && !String.IsNullOrEmpty(currentRouteData.Values["action"].ToString()))
{
currentAction = currentRouteData.Values["action"].ToString();
}
}
var ex = Server.GetLastError();
var controllerFactory = ControllerBuilder.Current.GetControllerFactory();
var controller = (Controller)controllerFactory.CreateController(httpContext.Request.RequestContext, "Error");
var routeData = new RouteData();
var action = "Index";
if (ex is HttpException)
{
var httpEx = ex as HttpException;
switch (httpEx.GetHttpCode())
{
case 401:
action = "Unauthorized";
break;
case 403:
action = "Forbidden";
break;
case 404:
action = "NotFound";
break;
default:
break;
}
}
httpContext.ClearError();
httpContext.Response.Clear();
httpContext.Response.StatusCode = ex is HttpException ? ((HttpException)ex).GetHttpCode() : 500;
httpContext.Response.TrySkipIisCustomErrors = true;
routeData.Values["controller"] = "Error";
routeData.Values["action"] = action;
controller.ViewData.Model = new HandleErrorInfo(ex, currentController, currentAction);
((IController)controller).Execute(new RequestContext(new HttpContextWrapper(httpContext), routeData));
}