【问题标题】:Custom routes with custom 404 page in MVC在 MVC 中使用自定义 404 页面的自定义路由
【发布时间】:2016-01-13 05:56:32
【问题描述】:

我设置了自定义路线:

var tradeCategoriesRoute = routes.MapRoute(
     name: "TradeCategoriesIndex",
     url: "TradeCategories/{*categories}",
     defaults:
          new
          {
                controller = "TradeCategories",
                action = "Index"
          },
          namespaces: new[] {"Website.Controllers"}
);
tradeCategoriesRoute.DataTokens["UseNamespaceFallback"] = false;
tradeCategoriesRoute.RouteHandler = new CategoriesRouteHandler();

我还在 Global.asax 中设置了自定义 404 页面:

private void Application_Error(object sender, EventArgs e)
{
    var exception = Server.GetLastError();
    var httpException = exception as HttpException;
    DisplayErrorPage(httpException);
}

private void DisplayErrorPage(HttpException httpException)
{
    Response.Clear();
    var routeData = new RouteData();

    if (httpException != null && httpException.GetHttpCode() == 404)
    {
        routeData.Values.Add("controller", "Error");
        routeData.Values.Add("action", "Missing");
    }
    else if (httpException != null && httpException.GetHttpCode() == 500)
    {
        routeData.Values.Add("controller", "Error");
        routeData.Values.Add("action", "Index");
        routeData.Values.Add("status", httpException.GetHttpCode());
    }
    else
    {
        routeData.Values.Add("controller", "Error");
        routeData.Values.Add("action", "Index");
        routeData.Values.Add("status", 500);
    }
    routeData.Values.Add("error", httpException);
    Server.ClearError();
    Response.TrySkipIisCustomErrors = true;
    IController errorController = ObjectFactory.GetInstance<ErrorController>();
    errorController.Execute(new RequestContext(new HttpContextWrapper(Context), routeData));
    Response.End();
}

看来我真正的问题是我制作的自定义路由处理程序:

public IHttpHandler GetHttpHandler(RequestContext requestContext)
{
    IRouteHandler handler = new MvcRouteHandler();
    var values = requestContext.RouteData.Values;
    if (values["categories"] != null)
        values["categoryNames"] = values["categories"].ToString().Split('/').Where(x => !string.IsNullOrWhiteSpace(x)).ToArray();
    else
        values["categoryNames"] = new string[0];
    return handler.GetHttpHandler(requestContext);
}

它可以正常工作并正确显示“/doesnotexist”之类的路线的 404 页面,但不适用于“/TradeCategories/doesnotexist”之类的路线。相反,我得到一个内置的 404 页面,其中显示消息“您要查找的资源已被删除、名称已更改或暂时不可用。”。

如何让我的自定义 404 页面与这些自定义路由一起使用?

【问题讨论】:

    标签: asp.net-mvc asp.net-mvc-4


    【解决方案1】:

    您可能想要研究的是 TradeCategories 控制器的 Index 操作的实现。自定义路由和自定义处理程序看起来基本上可以匹配任何路由(TradeCategories/*),所以我猜测您的操作或视图中的某些内容正在返回 404 而不会引发可以在 global.asax 中捕获的异常?

    【讨论】:

      【解决方案2】:

      您需要覆盖 GLobal.asax 中的 Application_Error 方法

      来自link

      void Application_Error(object sender, EventArgs e)
      {
        // Code that runs when an unhandled error occurs
      
        // Get the exception object.
        Exception exc = Server.GetLastError();
      
        // Handle HTTP errors
        if (exc.GetType() == typeof(HttpException))
        {
          // The Complete Error Handling Example generates
          // some errors using URLs with "NoCatch" in them;
          // ignore these here to simulate what would happen
          // if a global.asax handler were not implemented.
            if (exc.Message.Contains("NoCatch") || exc.Message.Contains("maxUrlLength"))
            return;
      
          //Redirect HTTP errors to HttpError page
          Server.Transfer("HttpErrorPage.aspx");
        }
      
        // For other kinds of errors give the user some information
        // but stay on the default page
        Response.Write("<h2>Global Page Error</h2>\n");
        Response.Write(
            "<p>" + exc.Message + "</p>\n");
        Response.Write("Return to the <a href='Default.aspx'>" +
            "Default Page</a>\n");
      
        // Log the exception and notify system operators
        ExceptionUtility.LogException(exc, "DefaultPage");
        ExceptionUtility.NotifySystemOps(exc);
      
        // Clear the error from the server
        Server.ClearError();
      }
      

      这应该可行。但是,我宁愿重定向到不同的页面,而不是写信给Response

      类似this:

      IController controller = new ErrorPageController();
          controller.Execute(new RequestContext(new HttpContextWrapper(Context), routeData));
          Response.End();
      

      【讨论】:

      • 我的问题应该更明确。我有一个使用 Application_Error 设置的自定义 404 页面。问题是它不适用于以我的自定义路由定义的 /TradeCategories 开头的网址。它仅适用于不以 /TradeCategories 开头的任何路线。
      • @jdehlin 在函数 Application_Error( ) 中添加断点,当您尝试访问 /TradeCategories/NonExistingUrl 时应该会看到 404 错误
      • 这就是问题所在。它没有命中 Application_Error。我得到这个screencast.com/t/2snbcwL8t。我认为无论出于何种原因它都匹配该自定义路线,它都不会通过管道。
      猜你喜欢
      • 2010-10-07
      • 1970-01-01
      • 2019-09-03
      • 1970-01-01
      • 1970-01-01
      • 2018-10-18
      • 2023-03-24
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多