欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  移动技术

详解ASP.NET Core 处理 404 Not Found

程序员文章站 2023-12-16 12:04:28
问题 在没有修改任何配置的情况下,这是用户使用 chrome 访问不存在的url时会看到的内容: 幸运的是,处理错误状态代码非常简单,我们将在下面介绍三种技术。...

问题

在没有修改任何配置的情况下,这是用户使用 chrome 访问不存在的url时会看到的内容:

详解ASP.NET Core 处理 404 Not Found

幸运的是,处理错误状态代码非常简单,我们将在下面介绍三种技术。

解决方案

在以前的asp.net mvc版本中,主要在 web.config 中处理404错误的。

您可能记得在 <customerrors> 节点中配置asp.net管道处理404错误,以及在低版本的iis中通过 <httperrors> 节点处理 404错误。好像有点混乱。

在.net core中,情况就不同了,没有必要使用xml配置(尽管如果您是通过iis代理,您仍然可以在web.config中使用 httperrors,并且您真的想这样吗:-))。

在处理 not-found 错误时,我们需要处理两种不同的情况。

url与任何路由不匹配的情况。在这种情况下,如果我们无法确定用户正在访问什么,我们需要返回一个通用的未找到的页面。有两种常见的处理方法,但首先我们将讨论第二种情况。url与路由匹配的情况,但是一个或多个参数无效,我们可以用自定义视图来解决这个问题。

自定义视图

这种情况的一个例子是具有无效或过期id的产品页面。在这里,我们知道用户正在查看产品,而不是返回通用错误,我们可以更友好的页面,返回自定义未找到产品的的页面。这仍然需要返回404状态代码,但是使用不通用的页面,同时也可以向用户显示类似或受欢迎的产品。

处理这些情况是非常琐碎,我们需要做的是在返回我们的自定义视图之前设置状态代码:

  public async task<iactionresult> getproduct(int id)
  {
    var viewmodel = await _db.get<product,getproductviewmodel>(id);
  
    if (viewmodel == null)
    {
      response.statuscode = 404;
      return view("productnotfound");
    }
  
    return view(viewmodel);
  }

当然,您可能更喜欢将其包装成自定义actionresult:

  public class notfoundviewresult : viewresult
  {
    public notfoundviewresult(string viewname)      
    {
      viewname = viewname;
      statuscode = (int)httpstatuscode.notfound;
    }
  }

这简化了我们的action:

  public async task<iactionresult> getproduct(int id)
  {
    var viewmodel = await _db.get<product,getproductviewmodel>(id);
  
    if (viewmodel == null)
    {
      return new notfoundviewresult("productnotfound");
    }
  
    return view(viewmodel);
  }

这个简单的技术涵盖了特定的404页,现在来看看通用的404错误,我们无法弄清楚用户想要查看的内容。

通配路由

在先前版本的mvc,创建一个通配符路由来处理,在.net core中,也可以使用相同的方式。这个方式是,您有一个通配符路由,它会接收任何其它路由尚未处理的url。使用特性路由,方式如下:

  [route("{*url}", order = 999)]
  public iactionresult catchall()
  {
    response.statuscode = 404;
    return view();
  }

重要的是指定顺序,以确保其它路由优先。

一个通配符路由的方式非常不错,但它不是.net core中的首选。虽然全部路由将处理404,但下一个方式将处理任何非成功状态代码,以便您可以执行以下action(可能在生产中的action过滤器中):
 

  public async task<iactionresult> getproduct(int id)
  {
    ...
  
    if (requiresthrottling())
    {
      return new statuscoderesult(429)
    }
  
    if (!haspermission(id))
    {
      return forbid();
    }
  
    ...
  }

statuscodepageswithreexecute方法 中件间

usestatuscodepageswithreexecute使用了一个非常聪明的中间件(statuscodepagesmiddleware),在未输出响应前,它能处理非成功状态代码。这意味着如果您使用上面详细描述的自定义视图技术,则404状态代码将不会被中间件处理(这正是我们想要的)。

当从内部中间件组件返回错误代码(如404)时,usestatuscodepageswithreexecute允许您执行另一个控制器action来处理状态代码。

您可以在startup.cs中使用一行代码将其添加到管道中:

  app.usestatuscodepageswithreexecute("/error/{0}");
  ...
  app.usemvc();

中间件定义的顺序很重要,您需要确保在可能返回错误代码的任何中间件(如mvc中间件)之前注册statuscodewithreexecute

您可以指定一个固定路径来执行或使用状态代码值的占位符,如上所述。

您还可以指向静态页面(假设您已经具有staticfilemiddleware中间件)和控制器action。

在这个例子中,我们有一个单独的action处理404。任何其它非成功状态代码,使用 error action。

  [route("error/404")]
  public iactionresult error404()
  {
    return view();
  }
  
  [route("error/{code:int}")]
  public iactionresult error(int code)
  {
    // handle different codes or just return the default error view
    return view();
  }

显然,您可以根据您的需要量身定制。例如,如果您正在使用上一节所示的请求限制,那么您可以返回一个解释为什么请求失败的429页面。

总结

处理404页面的具体问题最好用自定义视图来处理,并设置状态代码(直接或通过自定义操作结果)。

通过使用statuscodepagesmiddleware中间件,可以非常容易地处理通用404错误(或实际上是任何非成功状态代码)。一般来说,这两种技术是在asp.net core中处理非成功http状态代码的首选方法。

原文:《handling 404 not found in asp.net core

翻译:sweet tang

上一篇:

下一篇: