1. 程式人生 > >ASP.NET Core 處理 404 Not Found

ASP.NET Core 處理 404 Not Found

問題

在沒有修改任何配置的情況下,這是使用者使用 Chrome 訪問不存在的URL時會看到的內容:

640?wx_fmt=png&wxfrom=5&wx_lazy=1

幸運的是,處理錯誤狀態程式碼非常簡單,我們將在下面介紹三種技術。

解決方案

在以前的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》https://www.devtrends.co.uk/blog/handling-404-not-found-in-asp.net-core
翻譯:Sweet Tang
本文地址:http://www.cnblogs.com/tdfblog/p/handling-404-not-found-in-asp-net-core.html

原文地址: http://www.cnblogs.com/tdfblog/p/handling-404-not-found-in-asp-net-core.html

.NET社群新聞,深度好文,微信中搜索dotNET跨平臺或掃描二維碼關注

640?wx_fmt=jpeg