【问题标题】:Direct to action in lieu of 404 page直接采取行动代替 404 页面
【发布时间】:2015-08-27 06:22:03
【问题描述】:

我正在制作一个单页应用程序,我设置它的方式是使用 OnActionExecuting() 方法中的基本控制器将非 ajax 请求重定向到主索引操作。路径仍然存在并用作指示 javascript 做什么的指示符。

这适用于像 /login 这样的东西,其中实际上有一个 /login 页面,如果我没有使用我提到的技术阻止它,通常可以访问它。

但是,当我更进一步并使用 /some/other/meaningful/but/bogus/url 没有路由/控制器但对 javascript 有一定意义时,我收到 404 错误。

很明显,我想做的是在 404 情况下,我只想加载 home 索引操作。或者,替换我的 ajax 阻塞,将所有路径重定向到 home 索引操作(除非它们是用 ajax 调用的有效路由)将产生相同的结果。

我搜索过类似的答案,不幸的是,相同的措辞经常用于描述有关自定义 404 页面的问题,因此很难搜索。

【问题讨论】:

    标签: c# asp.net-mvc entity-framework single-page-application


    【解决方案1】:

    确实想要一个自定义错误页面。不同之处在于您的自定义错误页面是控制器/操作。自定义错误页面不必是像 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));
    }
    

    【讨论】:

    • 我试了你的解决方法,发现地址栏的网址变了。这是您所期望的行为吗?如果是这样,我认为您误读了我的问题:P 在客户端应该没有重定向的迹象,这对于维护所描述的 JavaScript 功能至关重要。
    • @braks 更新了一些 global.asax.cs 代码,可以实现您的目标。
    • 这更像!我喜欢这种方法,因为它非常可定制。一件事虽然我不得不将Setup.GetControllerFactory(); 更改为ControllerBuilder.Current.GetControllerFactory();
    • @braks 我会更新问题,代码很旧,可能是 mvc 4:P
    猜你喜欢
    • 1970-01-01
    • 2014-11-12
    • 1970-01-01
    • 2011-12-29
    • 2017-02-06
    • 1970-01-01
    • 2016-08-02
    • 1970-01-01
    • 2010-11-13
    相关资源
    最近更新 更多