ASP.NET Core 處理 404 Not Found

来源:http://www.cnblogs.com/tdfblog/archive/2017/10/16/handling-404-not-found-in-asp-net-core.html
-Advertisement-
Play Games

您可能會驚訝地發現,預設的ASP.NET Core MVC模板不正確地處理404錯誤,在找不到頁面時,會導致標準的瀏覽器錯誤屏幕。這個博各討論在ASP.NET Core處理404 Not Found 錯誤的各種方法。 ...


問題

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

Chrome Default 404 Screen

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

解決方案

在以前的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
歡迎轉載,請在明顯位置給出出處及鏈接。


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...