带布局的自定义错误页面

J-A*_*ano 5 .net html c# error-handling dynamic

我一直在努力让自定义错误页面工作,并继续寻找回到简单使用静态页面的方法.虽然静态页面有效,但它需要重新构建我们希望在此时避免的导航栏.我目前正在使用以下内容指定自定义错误页面.

Asp.net错误处理

<customErrors mode="On" redirectMode="ResponseRewrite">
  <error statusCode="404" redirect="~/404.aspx"/>
</customErrors>
Run Code Online (Sandbox Code Playgroud)

IIS错误处理

<httpErrors errorMode="Custom">
  <remove statusCode="404"/>
  <error statusCode="404" path="/404.html" responseMode="File"/>
</httpErrors>
Run Code Online (Sandbox Code Playgroud)

有没有一种方法可以实现动态自定义错误页面,可以处理IIS错误和Asp.net错误?

Ron*_*n C 5

我也在努力解决这个问题并且搜索了很长时间.据我所知,没有办法创建一个动态自定义错误页面,为未进入.net管道的请求的IIS错误提供服务.和你一样,我最终有两个404错误页面.一个动态.aspx用于文件未找到由于进入.net管道的请求而导致的错误,一个.html用于未找到从未进入.net管道的文件未找到的请求.贬低你的问题的人可能并没有意识到你提出了一个非常好的,也是一个难以解决的问题.我会提出你的问题,以帮助弥补.

  • 可悲的是,在发布和标记正确的方面,我仍然是stackoverflow的新手.他的回答是导致我最终解决方案的原因,尽管他的回答确实"有效",但对于我们的网站而言,这是一个太大的性能影响.我调整了他的解决方案以避免使用<handler>代码,而是在Global.asax.cs中设置Application_Error方法,该方法在IIS可以对它们执行任何操作之前捕获错误.结果是拥有动态错误页面,这些页面使用了我希望的布局,同时避免了性能损失.我应该编辑我的问题以显示最终结果吗? (2认同)

Nko*_*osi 1

我在 ASP.Net MVC 项目中通过处理程序将所有内容通过 .Net 进行管道传输,从而解决了同样的问题。

  <system.webServer>
    <handlers>
      <remove name="ExtensionlessUrlHandler-ISAPI-4.0_32bit" />
      <remove name="ExtensionlessUrlHandler-ISAPI-4.0_64bit" />
      <remove name="ExtensionlessUrlHandler-Integrated-4.0" />
      <remove name="OPTIONSVerbHandler" />
      <remove name="TRACEVerbHandler" />
      <add name="ExtensionlessUrlHandler-ISAPI-4.0_32bit" path="*.*" verb="GET,HEAD,POST,DEBUG,PUT,DELETE,PATCH,OPTIONS" modules="IsapiModule" scriptProcessor="%windir%\Microsoft.NET\Framework\v4.0.30319\aspnet_isapi.dll" preCondition="classicMode,runtimeVersionv4.0,bitness32" responseBufferLimit="0" />
      <add name="ExtensionlessUrlHandler-ISAPI-4.0_64bit" path="*.*" verb="GET,HEAD,POST,DEBUG,PUT,DELETE,PATCH,OPTIONS" modules="IsapiModule" scriptProcessor="%windir%\Microsoft.NET\Framework64\v4.0.30319\aspnet_isapi.dll" preCondition="classicMode,runtimeVersionv4.0,bitness64" responseBufferLimit="0" />
      <add name="ExtensionlessUrlHandler-Integrated-4.0" path="*.*" verb="GET,HEAD,POST,DEBUG,PUT,DELETE" type="System.Web.Handlers.TransferRequestHandler" preCondition="integratedMode,runtimeVersionv4.0" />
    </handlers>
  </system.webServer>
Run Code Online (Sandbox Code Playgroud)

首先ErrorController创建一个来处理请求错误和未找到的请求之类的。

[AllowAnonymous]
public class ErrorController : Controller {
    // GET: Error
    public ActionResult NotFound() {
        Response.StatusCode = (int)System.Net.HttpStatusCode.NotFound;
        Response.TrySkipIisCustomErrors = true;
        HttpContext.Response.StatusCode = (int)System.Net.HttpStatusCode.NotFound;
        HttpContext.Response.TrySkipIisCustomErrors = true;
        return View();
    }

    public ActionResult Error() {
        Response.StatusCode = (int)System.Net.HttpStatusCode.InternalServerError;
        Response.TrySkipIisCustomErrors = true;
        return View();
    }
}
Run Code Online (Sandbox Code Playgroud)

您会注意到我调用TrySkipIisCustomErrors是为了尽量避免 IIS 错误

ErrorController.NotFound然后创建一个基本控制器来处理映射到该操作的所有未知操作。

public abstract class FrontOfficeControllerBase : Controller {
    protected override void HandleUnknownAction(string actionName) {
        var data = ViewData;
        //Custom code to resolve the view.
        //ViewResult view = this.View<ErrorController>(c => c.NotFound());

        //Manually create view with view Data
        ViewResult view = new ViewResult();
        view.ViewData = new ViewDataDictionary();
        view.ViewData["controller"] = "Error";
        view.ViewData["action"] = "NotFound";

        if (data != null && data.Count > 0) {
            data.ToList().ForEach(view.ViewData.Add);
        }

        Response.StatusCode = (int)System.Net.HttpStatusCode.NotFound;
        Response.TrySkipIisCustomErrors = true;
        view.ExecuteResult(this.ControllerContext);
    }
}
Run Code Online (Sandbox Code Playgroud)

所有这些都Controllers将从这个基本控制器继承。

在所有其他路由之后配置了捕获所有路由。

routes.MapRoute(
    name: "404-NotFound",
    url: "NotFound",
    defaults: new { controller = "Error", action = "NotFound" }
);

routes.MapRoute(
    name: "500-Error",
    url: "Error",
    defaults: new { controller = "Error", action = "Error" }
);

routes.MapRoute(
    name: "CatchAll",
    url: "{*any}",
    defaults: new { controller = "Error", action = "NotFound" });
Run Code Online (Sandbox Code Playgroud)

这确保了如果路由与我的任何控制器都不匹配,它将安全地路由到操作ErrorController.NotFound

对于视图,我创建了相应的视图NotFound.shtmlError.cshtml在文件夹中分页 Views/Shared,它们受益于对根布局的访问,这就是我认为您正在寻找的。

最后,我能够删除 和customErrorsfrom httpErrorsweb.config因为不再需要它们,因为每个请求都由处理程序管理并相应地路由。

这种结构的最初想法来自这篇文章,我混合并匹配了可用的选项,直到找到一个适合我的需求的解决方案。

ASP.NET MVC 中的异常处理(6 种方法讲解)

希望这可以帮助。