{"id":18855518,"url":"https://github.com/springhgui/404test","last_synced_at":"2026-02-05T00:36:04.798Z","repository":{"id":112564177,"uuid":"481278139","full_name":"SpringHgui/404test","owner":"SpringHgui","description":"404处理测试","archived":false,"fork":false,"pushed_at":"2022-05-10T13:10:58.000Z","size":914,"stargazers_count":2,"open_issues_count":0,"forks_count":2,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-07-03T01:34:51.296Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"HTML","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/SpringHgui.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2022-04-13T15:47:08.000Z","updated_at":"2024-07-30T16:14:40.000Z","dependencies_parsed_at":"2023-05-16T11:31:27.245Z","dependency_job_id":null,"html_url":"https://github.com/SpringHgui/404test","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/SpringHgui/404test","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/SpringHgui%2F404test","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/SpringHgui%2F404test/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/SpringHgui%2F404test/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/SpringHgui%2F404test/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/SpringHgui","download_url":"https://codeload.github.com/SpringHgui/404test/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/SpringHgui%2F404test/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":264519719,"owners_count":23621858,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-11-08T03:54:08.844Z","updated_at":"2026-02-05T00:35:59.772Z","avatar_url":"https://github.com/SpringHgui.png","language":"HTML","funding_links":[],"categories":[],"sub_categories":[],"readme":"# ASP.NETCore统一处理404错误都有哪些方式？\n\n### 当未找到网页并且应用程序返回 404 错误时，ASP.NET Core MVC 仅呈现通用浏览器错误页面，如下图所示\n![](https://img2022.cnblogs.com/blog/960145/202204/960145-20220413225114408-766034496.png)\n### 这不是很优雅，是吗？\n### 我们平时看到的404页面一般是这样的\n![](https://img2022.cnblogs.com/blog/960145/202204/960145-20220413225654936-1520371800.png)\n### 还有这样的\n![](https://img2022.cnblogs.com/blog/960145/202204/960145-20220413225801971-910901386.png)\n### 试了下京东，地址不存在的时候是会重定向到首页\n\n## 下面就来演示下ASP.NET Core中如何实现这种自定义的404页面处理。\n\n### 新建项目 ASP.NET Core MVC（WebApi处理方式也一样）\n![](https://img2022.cnblogs.com/blog/960145/202204/960145-20220413224820333-1949072682.png)\n####新建好的项目直接运行的效果\n![](https://img2022.cnblogs.com/blog/960145/202204/960145-20220413225008185-2049980054.png)\n####随便输入一个地址 `/test404`\n当未找到网页并且应用程序返回 404 错误时，ASP.NET Core MVC 仅呈现通用浏览器错误页面，如下图所示\n![](https://img2022.cnblogs.com/blog/960145/202204/960145-20220413225114408-766034496.png)\n\n## 方式一 [FallbackEndpointRouteBuilderExtensions.MapFallback](https://docs.microsoft.com/zh-cn/dotnet/api/microsoft.aspnetcore.builder.fallbackendpointroutebuilderextensions.mapfallback?f1url=%3FappId%3DDev16IDEF1%26l%3DZH-CN%26k%3Dk(Microsoft.AspNetCore.Builder.FallbackEndpointRouteBuilderExtensions.MapFallback);k(DevLang-csharp)%26rd%3Dtrue\u0026view=aspnetcore-6.0)\n这是个什么东西?\n![](https://img2022.cnblogs.com/blog/960145/202204/960145-20220413230325856-1549088503.png)\n意思大概是说这是注册一个优先级最低的通配路由，来匹配所有路由，那就来试试效果吧。\n\n```c#\n// Program.cs\n\napp.UseAuthorization();\n\napp.MapControllerRoute(\n    name: \"default\",\n    pattern: \"{controller=Home}/{action=Index}/{id?}\");\n\napp.MapFallback(async (ctx) =\u003e\n{\n    ctx.Response.Body.Write(Encoding.UTF8.GetBytes(\"404 from Fallback\"));\n});\n\napp.Run();\n```\n### 试试效果如下\n![](https://img2022.cnblogs.com/blog/960145/202204/960145-20220413231024288-1329857067.png)\n## 方式二 自定义通配路由\n在`HomeController`添加一个Action如下\n```\n// HomeController.cs\n\n[Route(\"{*url}\", Order = 9999)]\npublic IActionResult Page404()\n{\n    return View();\n}\n```\n添加对应的View页面如下\n```\n// Page404.cshtml\n@{\n    ViewData[\"Title\"] = \"404\";\n}\n\n\u003cdiv\u003e404 for {*url}\u003c/div\u003e\n```\n### 效果图\n![](https://img2022.cnblogs.com/blog/960145/202204/960145-20220413231638452-928218934.png)\n### 上面两种方式虽然能够正常处理404错误页，但是在程序内部抛出的404错误却无法进行拦截\n添加一个测试Action如下\n```\n[Route(\"/test404\")]\npublic IActionResult test404()\n{\n    // 一些业务处理，最终返回404 \n    // return NotFound();\n    return StatusCode(404);\n}\n```\n你看，这种404场景，上述方式没能进行拦截处理。\n![](https://img2022.cnblogs.com/blog/960145/202204/960145-20220413232050896-172080133.png)\n## 方式三 自定义[Middleware](https://docs.microsoft.com/zh-cn/dotnet/api/microsoft.aspnetcore.builder.useextensions.use?view=aspnetcore-6.0#microsoft-aspnetcore-builder-useextensions-use(microsoft-aspnetcore-builder-iapplicationbuilder-system-func((microsoft-aspnetcore-http-httpcontext-microsoft-aspnetcore-http-requestdelegate-system-threading-tasks-task))))拦截\n代码如下，关于Middleware如何使用这里不做介绍\n```\napp.Use((context, next) =\u003e\n{\n    var res = next(context);\n    if (context.Response.StatusCode == 404)\n    {\n        context.Response.StatusCode = 200;\n        context.Response.Body.Write(Encoding.UTF8.GetBytes(\"404 from Middleware\"));\n    }\n\n    return res;\n});\n```\n把方式一和方式二的代码注释掉，运行测试效果如下\n不存在的地址\n![](https://img2022.cnblogs.com/blog/960145/202204/960145-20220413232421419-431841184.png)\n存在的地址，但是业务上返回404\n![](https://img2022.cnblogs.com/blog/960145/202204/960145-20220413232457435-392679222.png)\n\n## 方式四 [UseStatusCodePagesWithReExecute](https://docs.microsoft.com/zh-cn/dotnet/api/microsoft.aspnetcore.builder.statuscodepagesextensions.usestatuscodepageswithreexecute?view=aspnetcore-6.0)\n注释上个方法的代码\n![](https://img2022.cnblogs.com/blog/960145/202204/960145-20220413233356918-1369385615.png)\n\n```\napp.UseStatusCodePagesWithReExecute(\"/error/{0}\");\n```\n\n```\n// HomeController.cs\n[Route(\"test401\")]\npublic IActionResult test401()\n{\n    return StatusCode(401);\n}\n```\n```\n  public class ErrorController : Controller\n  {\n      [Route(\"error/404\", Order = 9)]\n      public IActionResult Error404()\n      {\n          ViewBag.code = 404;\n          return View();\n      }\n\n      [Route(\"error/{code:int}\", Order = 1)]\n      public IActionResult Error(int code)\n      {\n          ViewBag.code = code;\n          switch (code)\n          {\n              case 404:\n                  ViewBag.msg = \"对不起，请求的资源不存在。\";\n                  break;\n              case 401:\n                  ViewBag.msg = \"对不起，您无权限访问此页面。\";\n                  break;\n              default:\n                  ViewBag.msg = \"服务异常，请稍后重试！\";\n                  break;\n          }\n\n          return View(\"Error404\");\n      }\n  }\n```\n```\n// Error404.cshtml\n@{\n}\n\n\u003cdiv\u003e@ViewBag.code : @ViewBag.msg\u003c/div\u003e\n```\n### 测试效果\n![](https://img2022.cnblogs.com/blog/960145/202204/960145-20220413233835787-1514125445.png)\n![](https://img2022.cnblogs.com/blog/960145/202204/960145-20220413233849338-661948617.png)\n完美！！！！\n## 方式五 `web.config` `\u003ccustomErrors\u003e` 节点中配置ASP.NET管道处理404错误\n这是以前framwork时代的iis配置方式，不推荐使用了，也不进行测试了。\n\n## 总结\n个人认为方式三、四推荐使用，四更加优雅，三是最灵活的，还有没有其他方式进行拦截统一处理404错误呢，欢迎补充。\n## 本文源码已上传github \n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fspringhgui%2F404test","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fspringhgui%2F404test","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fspringhgui%2F404test/lists"}