006_過濾器

来源:http://www.cnblogs.com/KeSaga/archive/2016/06/02/5552212.html
-Advertisement-
Play Games

過濾器 過濾器(Filter)把附加邏輯註入到MVC框的請求處理,實現了交叉關註。所謂交叉關註(Cross-Cutting Concerns),是指可以用於整個應用程式,而又不適合放置在某個局部位置的功能,否則會打破關註分離模式。典型的例子有:登錄、授權、緩存等等。 使用過濾器 如果希望動作方法只能 ...


 

過濾器

   過濾器(Filter)把附加邏輯註入到MVC框的請求處理,實現了交叉關註。所謂交叉關註(Cross-Cutting Concerns),是指可以用於整個應用程式,而又不適合放置在某個局部位置的功能,否則會打破關註分離模式。典型的例子有:登錄、授權、緩存等等。

使用過濾器

   如果希望動作方法只能被認證用戶所使用,可以在每個動作方法中檢查請求的授權狀態。如在動作方法中使用Request.IsAuthenticated方法明確地檢查授權:if(!Request.IsAuthenticated){如果未被授權,則…}。

   但是,如果在項目中這麼做,那會非常繁瑣,他需要在每一個需要有授權認證的動作方法中進行判斷。所以,採用過濾器才是最好的辦法,如清單1:

    // 說明:
    // 過濾器是 .NET 的註解屬性,可以把它們運用於動作方法或控制器類。
    // 當被用於控制器類時,其作用效果將覆蓋當前控制器中的每一個方法。
    [Authorize]
    public class AdminController : Controller
    {

        public ViewResult Index()
        {
            …
        }

        public ViewResult Edit(int productId)
        {
            …
        }

    }

.NET的註解屬性,一個新鮮的事物


 

   註解屬性(Attribute)是派生於System.Attribute的特殊的.NET類。它們可以被附加到其他代碼元素上,包括類、方法、屬性以及欄位等。目的是把附加信息嵌入到已編譯的代碼中,以便在運行時讀回這些信息。

   在C#中,註解屬性用方括弧進行附加,而且可以用已命名參數語法給它們的public屬性賦值(如:[MyAttribute(SomeProperty=value)])。在C#的編譯器命名約定中,如果這些註解屬性類的名稱以單詞Attribute結尾,則可以忽略這一部分(如,對於AuthorizeAttribute註解屬性,可以寫成[Authorize])。

過濾器的四種基本類型

         MVC框架支持四種不同類型的過濾器。分別是:認證過濾器、動作過濾器、結果過濾器、異常過濾器,如下表:

過濾器類型

介面

預設實現

描述

Authorization

(認證過濾器)

IAuthorizationFilter

AuthorizeAtrribute

最先運行,在任何其他過濾器或動作方法之前

Action

(動作過濾器)

IActionFilter

ActionFilterAtrribute

在動作方法之前及之後運行

Result

(結果過濾器)

IResultFilter

ActionFilterAtrribute

在動作結果被執行之前和之後運行

Exception

(異常過濾器)

IExceptionFilter

HandleErrorAtrribute

僅在另一個過濾器、動作方法、或動作結果拋出異常時運行

   在框架調用一個動作之前,會首先檢測該方法的定義,以查看它是否具有這些過濾器設置。如果有,那麼便會在請求管道的相應點上調用這些介面所定義的方法。當然,框架預設實現了這些介面。

註:ActionFilterAtrribute類即實現了IActionFilter,也實現了IResultFilter介面,但這是一個抽象類,要求我們必須提供一個實現。

將過濾器運用於控制器和動作方法

   過濾器可以應用於動作方法,也可以運用於整個控制器。清單1,將Authorize過濾器運用於AdminController類,其效果與將其運用於控制器中的每一個方法相同,如清單2:

    public class AdminController : Controller
    {
        [Authorize]
        public ViewResult Index()
        {
            …
        }
         [Authorize]
        public ViewResult Edit(int productId)
        {
            …
        }

    }

   可以運用多個過濾器,也可以混搭它們運用的層級——即,將它們運用於整個控制器或某個動作方法。如清單3演示了三個不同過濾器的使用方式:

  [Authorize(Roles="trader")]    // applies to all actions(運用於所有動作)
    public class ExampleController : Controller
    {
        [ShowMessage]    // applies to just this action(僅用於本動作)
        [OutputCache(Duration=60)]    // applies to just this action(僅用於本動作)
        public ViewResult Index()
        {
            …
        }

    }

註:如果為控制器定義了一個自定義基類,那麼運用於基類上的任何過濾器都會影響其派生類。

創建示例項目

   為了後面內容的介紹,我們這裡利用空模板創建一個名為Filters的項目。在項目中添加一個Home控制器,並將其Index動作方法修改成如下這樣:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;

namespace Filters.Controllers
{
    public class HomeController : Controller
    {

        /// <summary>
        /// 一個返回字元串值的動作方法,這樣可以使 MVC 繞過 Razor 視圖引擎,直接將字元串值發送給瀏覽器
        /// (這隻是為了簡化,在實際的項目中還是應該使用視圖——這裡只關註控制器)
        /// </summary>
        /// <returns></returns>
        public string Index()
        {
            return "This is the Index action on the Home Controller";
        }

    }
}

         上面的動作方法的返回值修改為字元串型,這樣可以是MVC框架繞過Razor視圖引擎,直接將字元串發送給瀏覽器,這樣做只是為了簡化,因為現在我們只關註控制器。

         該示例的運行結果如圖所示:

                       

使用授權過濾器

   授權過濾器是首先運行的過濾器,而且也在動作方法被調用之前。過濾器通過執行設定的授權策略以確保動作方法只被一人在用戶所調用。授權過濾器需要實現IAuthorizationFilter介面。如:

namespace System.Web.Mvc
{
    public interface IAuthorizationFilter
    {
        void OnAuthorization(AuthorizationContext filterContext);
    }
}

         當然也可以通過創建實現IAuthorizationFilter介面的類,實現一個自定義的授權過濾器,使用自己的安全邏輯。但是,不建議這樣做,主要原因如下:


警告:編寫安全性代碼的安全性


   一般情況下,自行編寫的安全代碼總會存在一些缺陷,或未經測試的角落,從而留下了一些安全漏洞。

   所以,只要可能,可以使用經過廣泛測試並得到驗證的安全代碼。而且框架也提供了特性完備的授權過濾器,並能夠擴展實現自定義授權策略。

 

   一個更安全的辦法是創建一個AuthorizeAttribute類的子類,讓它照管所有棘手的事情,而且編寫自定義的授權代碼是很容易的。這裡為了演示這種方式的實現,在示例項目中添加了一個Infrastructure文件夾,在這個文件夾中我創建了一個新的類文件:CustomAuthAttribute.cs,其內容如下:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;

namespace Filters.Infrastructure
{
    public class CustomAuthAttribute : AuthorizeAttribute
    {
        private bool _localAllowed;

        public CustomAuthAttribute(bool allowedParam)
        {
            this._localAllowed = allowedParam;
        }

        protected override bool AuthorizeCore(HttpContextBase httpContext)
        {
            if (httpContext.Request.IsLocal)
            {
                return this._localAllowed;
            }
            else
            {
                return true;
            }
        }

    }
}

 

   這是一個簡單的授權過濾器,它實現了阻止本地請求的訪問(所謂本地請求就是一種瀏覽器與應用程式伺服器在同一設備上運行而形成的請求,如開發用機)。

         在這個示例中繼承了AuthorizeAttribute類,並重寫了AuthorizeCore方法。這樣即實現了自定義授權的目的,也保證了能夠獲益AuthorizeAttribute的其他內建特性。在構造函數中,使用了一個布爾值,用以指示是否允許本地請求。

         這裡重寫的這個AuthorizeCore方法,是MVC框架用以檢查過濾器,是否隊請求進行授權訪問的方式。其接收的參數是HttpContexBase對象,通過該參數可以獲得待處理請求的信息。通過利用AuthorizeAttribute基類的內建特性,只需要關註授權邏輯,併在想要對請求進行授權時,從AuthorizeCore方法中返回true,而再不想授權時返回false。


保持授權註解屬性簡單


 

   以上對AuthorizeCore方法傳遞了一個HttpContextBase對象,該對象所提供的是對請求信息進行訪問的方法,而不是訪問運用該註解屬性的控制器和方法的信息。開發人員直接實現IAuthorizationFilter介面的主要原因,是為了獲得對傳遞給OnAuthorization方法的AuthorizationContext的訪問,通過它可以得到更廣範的信息,包括路由細節,以及當前控制器和動作方法的信息。

   一般是不建議自行實現IAuthorizationFilter介面的,主要是因為不僅編寫自己的安全代碼是不危險的。雖然授權是一種交叉關註,但會在授權註解屬性中建立一些邏輯,這些邏輯會與控制器緊密地耦合在一起,這會破壞關註分離,並導致測試和維護的問題。要儘可能保持授權註解屬性簡單,並關註基於請求的授權——讓授權的上下文來自於運用該註解屬性的地方。

運用自定義授權過濾器

   可以像預設的過濾器那樣使用自定義的授權過濾器,如下演示的這樣(加粗部分):

using Filters.Infrastructure;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;

namespace Filters.Controllers
{
    public class HomeController : Controller
    {

        /// <summary>
        /// 一個返回字元串值的動作方法,這樣可以使 MVC 繞過 Razor 視圖引擎,直接將字元串值發送給瀏覽器
        /// (這隻是為了簡化,在實際的項目中還是應該使用視圖——這裡只關註控制器)
        /// </summary>
        /// <returns></returns>
        [CustomAuth(false)]
        public string Index()
        {
            return "This is the Index action on the Home Controller";
        }

    }
}

 

   示例中將過濾器構造函數的參數設置為false,表示本地請求將被拒絕訪問Index動作方法。如果運行程式,併在本機瀏覽器進行訪問,則將看到授權被拒絕的結果,如圖:

 

本地請求被自定義授權過濾器拒絕訪問

使用內建的授權過濾器

   內建的授權過濾器:AuthorizeAttribute擁有自己的實現,它將通過AuthorizeCore方法實現常規的授權任務。

   當直接使用AuthorizeAttribute時,可以用這個類的兩個公共屬性來指定授權策略,下表給出了這兩個屬性的簡單介紹:

名稱

類型

描述

Users

string

一個逗號分割的用戶名稱列表,允許這些用戶訪問該動作方法

Roles

string

一個逗號分割的角色列表。為了訪問該動作方法,用戶必須至少是這就角色之一。

   下麵是這兩個屬性的使用示例(加粗):

using Filters.Infrastructure;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;

namespace Filters.Controllers
{
    public class HomeController : Controller
    {

        /// <summary>
        /// 一個返回字元串值的動作方法,這樣可以使 MVC 繞過 Razor 視圖引擎,直接將字元串值發送給瀏覽器
        /// (這隻是為了簡化,在實際的項目中還是應該使用視圖——這裡只關註控制器)
        /// </summary>
        /// <returns></returns>
        //[CustomAuth(false)]
        [Authorize(Users = "adam,steve,jacqui", Roles = "admin")]
        public string Index()
        {
            return "This is the Index action on the Home Controller";
        }

    }
}

 

   上述示例中同時指定了用戶和角色,這表示除非兩個條件都滿足,否則將不授予許可權。這裡還有一個隱含條件,即該請求已被認證。如果未指定任何用戶或角色,那麼任何已被認證的用戶都可以使用這個動作方法。

提示:AuthorizeAttribute處理授權,但不負責認證。但我們可以使用任何ASP.NET內建的認證系統或開發自己的認證系統(建議最好使用內建認證系統)。只要認證系統使用標準的ASP.NET的API,那麼,AuthorizeAttribute就能限制對控制器和動作的訪問。

   對於大多數情況,AuthorizeAttribute提供的授權策略已經足夠了。但如果希望實現一些特殊功能,可以通過這個類進行派生。雖然這樣比直接實現IAuthorizationFilter介面的風險要小很多,但在開發的過程中還要非常謹慎的考慮策略的影響,並對它進行充分的測試。

使用異常過濾器

   只有在調用一個動作方法時,如果拋出未處理的異常,異常過濾器才會運行。這種異常的來源主要有以下幾種:

  • 另一個過濾器(授權、動作或結構過濾器);
  • 動作方法本身;
  • 當動作結果被執行時。

創建異常過濾器

   異常過濾器必須實現IExceptionFilter介面,該介面的命名空間為:System.Web.Mvc,其中OnException方法是在發送異常時被調用的。該方法的參數是一個繼承自ControllerContext的ExceptionContext類型的對象,它提供了很多有用的屬性可以用來獲取關於請求的信息,如下表:

名稱

類型

描述

Controller

ControllerBase

返回請求的控制器對象

HttpContext

HttpContextBase

提供對請求細節的訪問,以及對響應的訪問

IsChildAction

bool

若是子動作,便返回true

RequestContext

RequestContext

提供對HttpContext和路由數據的訪問,通過其他屬性,兩者都是可用的

RouteData

RouteData

返回請求的路由數據

   上表中的屬性都是繼承自ControllerContext的,除此之外,它還定義了一些附加屬性,見下表:

名稱

類型

描述

ActionDescriptior

ActionDescriptior

提供動作方法的細節

Result

ActionResult

用於動作方法的結果:通過將該屬性設置為一個非空值過濾器可以取消這個請求

Exception

Exception

未處理異常

ExceptionHandled

bool

如果另一個過濾器已經把這個異常標記為“已處理”,則返回true

   被拋出的異常可以通過Exception屬性進行操作。將ExceptionHandled屬性設置為“true”,異常過濾器可以報告它已經處理了該異常。但即便如此,應用於一個動作的所有異常過濾器還是會被調用,所以,一個比較好的處理方式是檢測另一個過濾器是否已經處理了這個問題,以免恢復另一個過濾器已經解決了的問題。

註:如果一個動作方法的所有異常過濾器均為將ExceptionHandled屬性設置為“true”,MVC框架將使用預設的ASP.NET異常處理器。這將會顯示恐怖的“黃色屏幕”。

   Result屬性由異常過濾器使用,已告訴MVC框架要做什麼。異常過濾器的兩個主要用途是對異常進行日誌,並將適當的消息顯示給用戶。下麵我們通過 類來演示該如何使用:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;

namespace Filters.Infrastructure
{
    public class RangeExceptionAttribute : FilterAttribute, IExceptionFilter
    {

        public void OnException(ExceptionContext filterContext)
        {

            if (!filterContext.ExceptionHandled &&
                filterContext.Exception is ArgumentOutOfRangeException)
            {
                filterContext.Result = new RedirectResult("~/Content/RangerErrorPage.html");
                filterContext.ExceptionHandled = true;
            }
        }
    }
}

 

   這裡對ArgumentOutOfRangeException實例進行了處理,採取的辦法是將用戶瀏覽器重定向到Content文件夾中名為RangerErrorPage.html文件。

   需要註意該類繼承了FilterAttribute類,此外還實現了IExceptionFilter介面。為了讓一個.NET註解屬性類被視為一個MVC過濾器,該類必須實現IMvcFilter介面。我們可以直接實現該介面,但最簡單的方式是通過FilterAttribute來派生自己的類,它已經實現了所以需要的介面,並提供一些有用的基本特性,如處理過濾器執行的預設處理順序。

運用異常過濾器

   在使用異常過濾器之前還需要前面提到的Content文件夾和RangerErrorPage.html文件(靜態的HTML文件)。在本示例中將使用該文件顯示一些簡單的消息。代碼如下:

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <title>Rang Error</title>
</head>
<body>
    <h2>Sorry</h2>
    <span>One of the arguments was out of the expected range.</span>
</body>
</html>

 

   下麵,需要對Home控制器添加一個動作方法,它將拋出我們感興趣的異常。添加的內容如下:

public string RangeTest(int id)
        {
            if (id > 100)
            {
                return string.Format("The id value is:{0}", id);
            }
            else
            {
                throw new ArgumentOutOfRangeException("id", id, "");
            }
        }
…

 

   啟動程式,並導航至/Home/RangeTest/50(如我的完整URL是:http://localhost:4081/Home/RangeTest/50),便可以看到預設的異常處理結果。(Visual Studio為MVC項目創建的預設路由中,具有一個名為id的片段變數,針對這一URL,它的值將被設為50,這回得到下圖的響應結果)。

 

   可以將異常過濾器運用於控制器或個別動作,如:

 [RangeException]
        public string RangeTest(int id)
        {
            if (id > 100)
            {
                return string.Format("The id value is:{0}", id);
            }
            else
            {
                throw new ArgumentOutOfRangeException("id", id, "");
            }
        }
…

   在此導航至/Home/RangeTest/50,將得到如下結果:

 

使用視圖來響應異常

   通過顯示靜態內容的頁面來處理異常是簡單且安全的,但這對用戶來說沒有什麼用處。——最多也就能得到一個泛泛的警告,最後選擇退出程式。最好的辦法是使用視圖來顯示問題的細節,併為其提供一些上下文信息和選項,以幫助用戶對異常採取處理。

         對於該示例,這裡做出了一些調整,將RangeExceptionAttribute類修改成如下這樣(加粗部分和註釋部分為修改內容):

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;

namespace Filters.Infrastructure
{
    public class RangeExceptionAttribute : FilterAttribute, IExceptionFilter
    {

        public void OnException(ExceptionContext filterContext)
        {

            if (!filterContext.ExceptionHandled &&
                filterContext.Exception is ArgumentOutOfRangeException)
            {
                int val = (int)(((ArgumentOutOfRangeException)filterContext.Exception).ActualValue);
                filterContext.Result = new ViewResult
                {
                    ViewName = "RangeError",
                    ViewData = new ViewDataDictionary<int>(val)
                };
                // 下麵註釋掉的方式顯示了一個靜態頁面內容
                //filterContext.Result = new RedirectResult("~/Content/RangerErrorPage.html");
                filterContext.ExceptionHandled = true;
            }
        }
    }
}

 

         這裡創建了一個ViewResult對象,並設置了ViewName和ViewData屬性的值,以指定視圖名稱和要傳遞給視圖的模型對象。這樣寫顯得代碼有些凌亂是直接使用ViewResult對象,而不是在Controller類定義的動作方法中使用View方法的原因。這裡我們沒必要關註這些,只要明白如何實現這一效果即可。後面我們會通過內建的異常過濾器更好的實現同樣效果。

         這裡我們指定了一個名為RangeError的視圖,並傳了一個int型的參數值,以這個引起異常的參數值作為視圖模型對象。後面,繼續在項目中添加一個Views/Shared文件夾,並創建RangeError.cshtml文件:

@model int

<!DOCTYPE html>

<html>
<head>
    <meta name="viewport" content="width=device-width" />
    <title>Range Error</title>
</head>
<body>
    <h2>The value @Model was out of the expected range.</h2>
    <div>
        @Html.ActionLink("Change value and try again", "Index")
    </div>
</body>
</html>

   由於示例功能有限,未向用戶指示出解決這一問題的任何有用信息,但這裡使用ActionLink輔助器方法創建了一個指向另一個動作方法的連接,目的是演示可以使用一整套視圖特性。再次啟動程式,並導航至/Home/RangeTest/50,將看到如下效果:

 

   避免異常錯誤陷阱

         使用視圖來顯示錯誤消息的好處是可以使用佈局是錯誤消息與應用程式的其餘部分一致,並生成動態的內容,幫助用戶瞭解發生了什麼錯誤,以及提示他們可以如何處理問題。

         但是這麼做也存在一些缺陷:這就要求我們在開發的過程當中必須徹底的測試視圖,以確保不會產生其他異常。作為簡單示例,這裡對RangeError.cshtml視圖添加了一個Razor代碼塊,很明顯它將拋出一個異常,如:

@model int

@{
    // 用來演示在異常視圖信息中拋出異常的情況
    var count = 0;
    var number = Model / count;
}

<!DOCTYPE html>

<html>
<head>
    <meta name="viewport" content="width=device-width" />
    <title>Range Error</title>
</head>
<body>
    <h2>The value @Model was out of the expected range.</h2>
    <div>
        @Html.ActionLink("Change value and try again", "Index")
    </div>
</body>
</html>

   當該視圖被渲染時,將會生成一個DivideByZeroException(被零除異常)。如果啟動程式,並導航至/Home/RangeTest/50,將會看到拋出的異常,該異常是在視圖渲染期間拋出的,且不由控制器拋出。如下圖:

 

   這個演示雖不是真是場景,但它說明瞭當視圖有問題時發送的情況——用戶看到了一個困惑的錯誤提示,甚至與他們在程式中遇到的問題毫不相關。所以,在使用一個依賴於視圖的異常過濾器時,必須小心謹慎地對視圖進行充分的測試。

使用內建的異常過濾器

   在實際的項目中一般不需要向前面將的那樣去創建自己的過濾器,MVC框架包含了HandleErrorAttribute異常過濾器,它是內建IExceptionFilter介面的實現。該異常過濾器有一些常用的屬性,可以用來指定一個異常以及視圖和佈局名稱,詳見下表:

名稱

類型

描述

ExceptionType

Type

由過濾器處理的異常類型。它也處理通過給定值繼承而來的異常類型,但會忽略所有其他類型。其預設值是System.Exception,其含義為,預設地處理所有標準異常

View

string

該過濾器渲染的視圖模板名。如果未指定一個值,則採用預設的Error值,因此,預設情況下會渲染/Views/<currentCotrollerName>/Error.cshtml或/Views/Shared/Error.cshtml

Master

string

在渲染這過濾器的視圖時所使用的佈局名稱。如果未指定一個值,該視圖使用其預設佈局頁面

   當遇到由ExceptionType指定類型的未處理異常時,此過濾器將渲染由View屬性指定的視圖(使用預設佈局,或有Master屬性指定的佈局)。

   1.使用內建異常過濾器要做的準備

   只有在Web.config文件中啟用了自定義錯誤時,HandleErrorAttribute過濾器才會生效,這可以在<system.web>節點中添加一個customErrors屬性即可,如:

<system.web>

    <httpRuntime targetFramework="4.5" />

    <compilation debug="true" targetFramework="4.5" />

    <pages>
      <namespaces>
        <add namespace="System.Web.Helpers" />
        <add namespace="System.Web.Mvc" />
        <add namespace="System.Web.Mvc.Ajax" />
        <add namespace="System.Web.Mvc.Html" />
        <add namespace="System.Web.Routing" />
        <add namespace="System.Web.WebPages" />
      </namespaces>
    </pages>
    <customErrors mode="On" defaultRedirect="/Content/RangeErrorPage.html"/>
  </system.web>

   model屬性的預設值是RemoteOnly,意為在開發期間,HandleErrorAttribute將不會攔截異常,但將應用程式部署到產品伺服器,並從另一臺電腦發出請求時才會生效。為了看到用戶最終將看到的情況,要確保已經將這個自定義錯誤模式設置為“On”。defaultRedirect屬性指定了一個內容頁面,在其他情況下都無法顯示異常消息時,便會使用該頁面。

   2.運營內建的異常過濾器

   下麵我們看看該如何使用這一內建的異常過濾器:

[HandleError(ExceptionType = typeof(ArgumentOutOfRangeException), View = "RangeError")]
        public string RangeTest(int id)
        {
            if (id > 100)
            {
                return string.Format("The id value is:{0}", id);
            }
            else
            {
                throw new ArgumentOutOfRangeException("id", id, "");
            }
        }
…

   該示例重建了前面自定義過濾器一樣的情況,即通過將視圖顯示給用戶的方式來處理ArgumentOutOfRangeException異常。

         在渲染視圖時,HandleErrorAttribute過濾器會傳遞一個HandleErrorInfo視圖模型對象,這是一個封裝了異常細節的封裝程式,它提供了可在視圖中使用的附加信息,下表給出了HandleErrorInfo類定義的屬性:

名稱

類型

描述

ActionName

string

返回生成異常的動作方法名稱

ControllerName

string

返回生成異常的控制器名稱

Exception

Exception

返回此異常

   下麵將演示如何使用這個模型對象來更新RangeError.cshtml視圖:

<!--使用 HandleErrorInfo 模型對象-->
@model HandleErrorInfo
<!--model int-->

@{
    //// 用來演示在異常視圖信息中拋出異常的情況
    //var count = 0;
    //var number = Model / count;

    // 使用 HandleErrorInfo 模型對象
    ViewBag.Title = "Sorry,there was a problem!";
}

<!DOCTYPE html>

<html>
<head>
    <meta name="viewport" content="width=device-width" />
    <title>Range Error</title>
</head>
<body>
    @*<h2>The value @Model was out of the expected range.</h2>
        <div>
            @Html.ActionLink("Change value and try again", "Index")
        </div>*@

    <!--使用 HandleErrorInfo 模型對象-->
    <h2>Sorry</h2>
    <span>
        The value @(((ArgumentOutOfRangeException)Model.Exception).ActualValue)
        was out of the expected range.
    </span>
    <div>
        @Html.ActionLink("Change value and try again", "Index")
    </div>
    <!--放在 div 中且將 display 設為 none 可將堆棧的跟蹤情況隱藏-->
    <div style="display:none">
        <!--必須包含該屬性的值,否則將不能顯示異常視圖-->
        @Model.Exception.StackTrace
    </div>

</body>
</html>

         該視圖中必須將Model.Exception屬性值轉為ArgumentOutOfRangeException類型,以便能夠讀取ActualValue屬性,因為HandleErrorInfo類是一個用來將任何異常傳遞給視圖的一個通用的模型對象。

註意:在使用HandleError過濾器時有一個奇怪的行為,即視圖中必須包含Model. Exception. StackTrace屬性的值,否則視圖便不會顯示給用戶。但因為不想顯示堆棧的跟蹤情況,所以將該值的輸出放在一個div元素中,並將其CSS的display屬性設置為none,使之對用戶是不可見的。

   其效果和使用前述自定義異常過濾器一樣,如圖:

 

使用動作過濾器

   動作過濾器是可以被用於任何目的的多用途過濾器。創建這種過濾器需要實現介面IActionFilter,在MSDN中給出的描述是這樣的:

   命名空間:System.Web.Mvc

   語法:public interface IActionFilter

   公開成員(方法):

名稱

說明

語法

OnActionExecuted

在執行操作方法後調用。

void OnActionExecuted(

          ActionExe

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

-Advertisement-
Play Games
更多相關文章
  • Ftp(文件傳輸協議) 概念 FTP是File Transfer Protocol(文件傳輸協議)的英文簡稱,而中文簡稱為“文傳協議”。用於Internet上的控制文件的雙向傳輸。同時,它也是一個應用程式(Application)。基於不同的操作系統有不痛的FTP應用程式,而所有這些應用程式都遵守同 ...
  • Win8 app判斷網路連接狀態 推薦:http://www.cnblogs.com/roucheng/p/3535198.html ...
  • 代理伺服器(Proxy Server)是個人網路和Internet服務商之間的中間代理機構,它負責轉發合法的網路信息,對轉發進行控制和登記。代理伺服器作為連接Internet(廣域網)與Intranet(區域網)的橋梁,在實際應用中發揮著極其重要的作用。 環境:Win7(64位)+VMware11( ...
  • 1:W 查看系統整體負載,無法查看具體負載,比如記憶體,磁碟 23:25:20 up 13 min, 2 users, load average: 0.00, 0.01, 0.01 USER TTY FROM LOGIN@ IDLE JCPU PCPU WHAT flex tty1 - 23:13 1 ...
  • 屏幕捕捉快捷鍵動作............................保存到............-快捷鍵 全屏捕捉........................桌面(.PDF文件)......Command + Shift + 3 (win+shift+3)屏幕部分畫面.......... ...
  • ApiView是.net api的介面文檔查看網站,用於解決分散式開發過程中的Api介面管理和溝通問題。 自動生成api文檔; 方便調試及第三方開發人員對接,可以應用在asp.net mvc,wcf,webservice 中使用; 代碼及原理都很簡單,方便修改和完善。 ...
  • 各級省份代碼: 各級市代碼: ...
  • 上次分享了控制器向視圖傳遞數據的4種方式,今天再來給大家講講MVC視圖中的數據如何提交到控制器。 我們可以通過以下幾種方式提交數據到控制器: 1、通過Request.Form讀取表單數據 在 控制器動作方法(Action)中,POST方法提交的表單可以使用Request.Form讀取其中的數據: < ...
一周排行
    -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.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...