Asp.Net MVC 3【Filters(過濾器)】


這里分享MVC里的Filters(過濾器),什么是MVC里的過濾器,他的作用是什么?

過濾器的請求處理管道中注入額外的邏輯。他們提供了一個簡單而優雅的方式來實現橫切關注點。這個術語是指所有對應用程序的功能,用於不適合整齊地進入任何一個地方,所以這將打破關注分離的模式。經典的橫切關注點的記錄,授權和緩存。

所謂的過濾器,因為這個詞被用於在其他Web應用程序相同的設施框架,包括Ruby on Rails。然而,MVC框架的過濾器是完全不同的ASP.NET平台的Request.Filterand的Response.Filter對象,執行轉換請求和響應流(一種先進的和經常進行的活動)。您可以使用Request.Filter和Response.Filterin MVC應用程序。

使用過濾器

當我們申請授權的行動SportsStore的AdminController控制器的方法。我們希望的操作方法只能用於用戶身份驗證自己的人,這為我們提供了一個可供選擇的方法。我們可以已檢查的授權狀況,在每一個要求,每一個動作方法,如下面:

View Code
    public class AdminController : Controller
    {
        private IProductRepository repository;
        public AdminController(IProductRepository repo)
        {
            this.repository = repo;
        }
        /// <summary>
        /// 展示商品列表頁面
        /// </summary>
        /// <returns>商品的列表</returns>
        public ViewResult Index()
        {
            return this.View(this.repository.Products);
        }
        /// <summary>
        /// 編輯方法
        /// </summary>
        /// <param name="productId">商品的ID</param>
        /// <returns>編輯后的商品</returns>
        public ViewResult Edit(int productId)
        {
            Product product = this.repository.Products.FirstOrDefault(h => h.ProductID == productId);
            return this.View(product);
        }
        public ActionResult Edit(Product product, HttpPostedFileBase image)
        {
            if (ModelState.IsValid)
            {
                if (image != null)
                {
                    product.ImageMimeType = image.ContentType;
                    product.ImageData = new byte[image.ContentLength];
                    image.InputStream.Read(product.ImageData, 0, image.ContentLength);
                }
                this.repository.SaveProduct(product);
                //設置臨時字典
                TempData["message"] = string.Format("{0} Has Been Saved", product.Name);
                return this.View(product);
                    //.RedirectToAction("Index");
            }
            else
            {
                //如果數據有問題
                return this.View(product);
            }
        }
}

可以看到代碼里有大量的重復的東東,在這種方法中,這就是為什么我們決定使用一個過濾器代替,所以上面的代碼可以修改為下面:

View Code
 [Authorize]
    public class AdminController : Controller
    {
        private IProductRepository repository;
        public AdminController(IProductRepository repo)
        {
            this.repository = repo;
        }
        /// <summary>
        /// 展示商品列表頁面
        /// </summary>
        /// <returns>商品的列表</returns>
        public ViewResult Index()
        {
            return this.View(this.repository.Products);
        }
        /// <summary>
        /// 編輯方法
        /// </summary>
        /// <param name="productId">商品的ID</param>
        /// <returns>編輯后的商品</returns>
        public ViewResult Edit(int productId)
        {
            Product product = this.repository.Products.FirstOrDefault(h => h.ProductID == productId);
            return this.View(product);
        }
        [HttpPost]
        public ActionResult Edit(Product product, HttpPostedFileBase image)
        {
            if (ModelState.IsValid)
            {
                if (image != null)
                {
                    product.ImageMimeType = image.ContentType;
                    product.ImageData = new byte[image.ContentLength];
                    image.InputStream.Read(product.ImageData, 0, image.ContentLength);
                }
                this.repository.SaveProduct(product);
                //設置臨時字典
                TempData["message"] = string.Format("{0} Has Been Saved", product.Name);
                return this.View(product);
                    //.RedirectToAction("Index");
            }
            else
            {
                //如果數據有問題
                return this.View(product);
            }
        }
        /// <summary>
        /// 創建商品
        /// </summary>
        /// <returns>新的商品</returns>
        public ViewResult Create()
        {
            return this.View("Edit", new Product());
        }
}

過濾器是.NET屬性添加額外的步驟,請求處理管道。我們使用了授權過濾清單上面代碼中。

介紹四種基本類型的過濾器

MVC框架支持四種不同類型的過濾器。每一個允許您介紹邏輯在請求處理管道的不同點,具體如下表所示:

過濾類型(Filter Type) 接口(Interface) 默認實現(Default Implementation) 描述(Description)
Authorization IAuthorizationFilter AuthorizeAttribute 首先運行,在其他過濾器的操作方法
Action IActionFilter ActionFilterAttribute 運行之前和之后的動作方法
Result IResultFilter ActionFilterAttribute 運行前后執行的操作結果
Exception IExceptionFilter HandleErrorAttribute 如果只運行另一個過濾器, 操作方法,或行動結果拋出一個異常

的MVC框架調用一個動作之前,它會檢查該方法的定義,看它是否有實現表中列出的接口的屬性。如果是這樣,那么在適當的點在請求管道,通過這些接口中定義的方法被調用。該框架包括默認屬性類實現過濾器的接口。

應用過濾器在控制器和操作方法

過濾器可以應用到個人的行動方法或整個控制器。在上面代碼中,我們采用授權濾波器的AdminController類,它具有相同的效果,將它應用到每個動作在控制器中的方法,修改如下:

 public class AdminController : Controller
    {
        private IProductRepository repository;
        public AdminController(IProductRepository repo)
        {
            this.repository = repo;
        }
        /// <summary>
        /// 展示商品列表頁面
        /// </summary>
        /// <returns>商品的列表</returns>
       [Authorize]
        public ViewResult Index()
        {
            return this.View(this.repository.Products);
        }
        /// <summary>
        /// 編輯方法
        /// </summary>
        /// <param name="productId">商品的ID</param>
        /// <returns>編輯后的商品</returns>
        [Authorize]
        public ViewResult Edit(int productId)
        {
            Product product = this.repository.Products.FirstOrDefault(h => h.ProductID == productId);
            return this.View(product);
        }
        [Authorize]
        [HttpPost]
        public ActionResult Edit(Product product, HttpPostedFileBase image)
        {
            if (ModelState.IsValid)
            {
                if (image != null)
                {
                    product.ImageMimeType = image.ContentType;
                    product.ImageData = new byte[image.ContentLength];
                    image.InputStream.Read(product.ImageData, 0, image.ContentLength);
                }
                this.repository.SaveProduct(product);
                //設置臨時字典
                TempData["message"] = string.Format("{0} Has Been Saved", product.Name);
                return this.View(product);
                    //.RedirectToAction("Index");
            }
            else
            {
                //如果數據有問題
                return this.View(product);
            }
        }
}

您可以將多個過濾器,混合和匹配它們的應用。也就是說,他們是否被施加到控制器或一個個別的操作方法。上面三個方法使用的都是一個,只有編輯使用了多個過濾器。

使用授權過濾器

授權過濾器的過濾器首先運行之前,其他類型的過濾器和前動作方法被調用。正如它的名字所暗示的,這些過濾器執行您的授權政策,確保只有經批准的用戶可以調用該操作的方法。授權過濾器實現IAuthorizationFilter接口,如下面代碼所示:

View Code
namespace MvcFilters.Interface
{
    public interface IAuthorizationFilter
    {
        //對使用 AuthorizeAttribute 特性時所需的信息進行封裝
        void OnAuthorization(AuthorizationContext filterContext);
    }
}

假如 MVC框架已收到請求從瀏覽器。路由系統已處理請求的URL和提取nameof是有針對性的控制器和動作。控制器類的新實例被創建,但在此之前的操作方法被調用,MVC框架檢查,看看是否有任何授權過濾器的操作方法。如果有,則然后IAuthorizationFilter接口,OnAuthorization的定義,唯一的方法被調用。如果認證過濾器,批准該請求,然后進行下一階段的處理管道。如果沒有,那么請求將被拒絕。

創建一個授權認證過濾器

了解如何驗證過濾器工作的最好的方法是創建一個簡單的例子,。它只是檢查,訪客先前在(Request.IsAuthenticated的是true)時記錄,在一個固定的允許用戶列表中出現的用戶名。具體代碼如下:

View Code
using System.Web.Mvc;

namespace MvcFilters.ContClass
{
    public class CustomAuthAttribute : AuthorizeAttribute
    {
        private string[] allowedUsers;
        //構造函數
        public CustomAuthAttribute(params string[] users) 
        {
            this.allowedUsers = users;
        }
        protected override bool AuthorizeCore(HttpContextBase httpContext)
        {
            return httpContext.Request.IsAuthenticated &&
                   this.allowedUsers.Contains(httpContext.User.Identity.Name,
                   StringComparer.InvariantCultureIgnoreCase);
        }

    }
}

這個簡單的方法創建一個授權過濾器是子類化AuthorizeAttribute類和重寫AuthorizeCore方法。這確保了我們到內置的功能中構建在AuthorizeAttribute。

我們的過濾器的構造函數接受一個數組的名字。這些被授權的用戶。我們的過濾器包含一個稱為PerformAuthenticationCheck的方法,以確保該請求是及認證該用戶是授權的集之一。

這個類實現的OnAuthorization方法的。參數傳遞給這個方法是AuthorizationContext類的一個實例,這是來自ControllerContext。 ControllerContext為我們提供了一些有用的對象的訪問權限,至少不是這是一個HttpContextBase,通過它,我們可以訪問請求的詳細信息的屬性。由不同的使用的所有的上下文對象從這個類派生的各種動作過濾器,所以你可以使用這些屬性保持一致。如下表:

Name(名字) Type(類型) Description(描述)
Controller ControllerBase 返回控制器對象來處理該請求
HttpContext HttpContextBase 提供接入的要求,並獲得響應
IsChildAction bool 返回true,如果這是一個子集的行動
RequestContext RequestContext 提供了訪問的HttpContextand的路由數據,這兩者都可以通過其他屬性
RouteData RouteData 返回此請求的路由數據

使用上下文對象,我們可以得到所有的信息,我們需要做出決定的的要求。 AuthorizationContext的定義了兩個附加屬性,這些屬性如表下所示。

Name(名字) Type(類型) Description(描述)
ActionDescriptor ActionDescriptor 提供詳細的操作方法
Result ActionResult 結果操作方法上的;一個過濾器可以取消請求通過將這個屬性設置為一個非空值

第一,ActionDescriptor,這些屬性返回一個實例System.Web.Mvc.ActionDescriptor,你可以用它來獲取信息的行動,過濾器已被應用。結果,第二個屬性,讓你的過濾器的工作是關鍵。但是,如果上下文對象的Result屬性設置為一個ActionResult對象,MVC框架將以此作為整個請求的結果。管道中的其余步驟是不執行,並且你已經提供的結果被執行,以產生輸出為用戶。

使用內置的授權過濾器

MVC框架包含了一個非常有用的內置授權過濾器AuthorizeAttribute。我們可以指定我們的授權政策,使用這個類的兩個公共屬性,如下表:

Name(名字) Type(類型) Description(描述)
Users String 用逗號分隔的用戶名列表,被允許訪問動作方法。
Roles String 用逗號分隔的角色名稱。訪問操作方法,用戶必須至少在其中的一個角色。

使用內置的授權過濾器,代碼如下:

View Code
    public class HomeController : Controller
    {
        //
        // GET: /Home/

        [Authorize(Users="admin,Steve,bob",Roles="admin")]
        public ActionResult Index()
        {
            return this.View();
        }

    }

我們已經指定在列表中的用戶和角色。這意味着,授權將不除非兩個條件都滿足用戶的名字是admin,Steve,或bob以及用戶的管理的作用。有一個隱含的條件,這是請求進行身份驗證。如果我們不指定任何用戶或角色,那么任何身份驗證的用戶可以使用的操作方法。

對於大多數應用,AuthorizeAttribute提供的授權策略,是足夠的。如果您要實現一些特別的東西,你可以從這個類派生。這是少得多的風險比實施IAuthorizationFilter接口直接,但你仍然應該非常小心思考通過策略和測試它徹底的影響。

AuthorizeAttribute類提供了兩個不同的定制,具體如下描述:

  • AuthorizeCore方法,這就是所謂的AuthorizeAttribute實施OnAuthorization和執行授權檢查
  • HandleUnauthorizedRequest方法,這就是所謂的授權檢查失敗時

實現自定義授權策略

為了演示如何使用自定義身份驗證策略,我們將創建一個自定義AuthorizeAttribute子類。這一政策將授予訪問權限的任何人訪問該網站從瀏覽器上直接運行服務器的桌面(Request.IsLocal是真實的),以及遠程訪問者的用戶名和角色匹配的normalAuthorizeAttribute規則。這可能是有益的,允許服務器管理員繞過網站的登錄過程。我們可以告訴如果是這樣的情況下通過讀取的IsLocalproperty,HttpRequestBase類。下面代碼演示了我們的自定義過濾器:

View Code
using System.Web;
using System.Web.Mvc;

namespace MvcFilters.ContClass
{
    public class OrAuthorizationAttribute : AuthorizeAttribute
    {
        protected override bool AuthorizeCore(HttpContextBase httpContext)
        {
            return httpContext.Request.IsLocal || base.AuthorizeCore(httpContext);
        }
    }
}

我們可以在之前的Action(方法)上使用我們字自定義的授權,代碼如下:

View Code
using System.Web;
using System.Web.Mvc;
using MvcFilters.ContClass;

namespace MvcFilters.Controllers
{
    public class HomeController : Controller
    {
        //
        // GET: /Home/

        [OrAuthorization(Users = "admin,Steve,bob", Roles = "admin")]
        public ActionResult Index()
        {
            return this.View();
        }

    }
}

現在當地中沒有指定名稱的列表,並沒有被授予了管理員角色的用戶將能夠使用的操作方法.

實現一個自定義授權失敗的政策

處理授權失敗嘗試的默認策略是將用戶重定向到登錄頁面。我們不要總想做到這一點。例如,如果我們正在使用AJAX,發送重定向可能會導致登錄出現在用戶正在觀看的任何頁的中間頁。幸運的是,我們可以重寫HandleUnauthorizedRequest的AuthorizeAttribute類的方法來創建自定義策略。

 我們自定義一個授權失敗的策略,代碼如下:

View Code
using System.Web;
using System.Web.Mvc;

namespace MvcFilters.ContClass
{
    public class AjaxAuthorizeAttribute : AuthorizeAttribute
    {
        protected override void HandleUnauthorizedRequest(AuthorizationContext context)
        {
            if (context.HttpContext.Request.IsAjaxRequest())
            {
                UrlHelper urlHelper = new UrlHelper(context.RequestContext);
                context.Result = new JsonResult
                {
                    Data = new
                    {
                        Error = "NotAuthorized",
                        LogOnUrl = urlHelper.Action("LogOn", "Account")
                    },
                    JsonRequestBehavior = JsonRequestBehavior.AllowGet
                };
            }
            else 
            {
                base.HandleUnauthorizedRequest(context);
            }
        }
    }
}

 使用異常過濾器

如果一個未處理的異常被拋出時調用一個動作異常過濾器只運行方法。唯一的例外,可以從以下位置查找:

  • 另一種過濾器(授權,行動或結果的過濾器)
  • 動作方法本身
  • 當動作執行結果

創建一個異常過濾器

異常過濾器必須實現IExceptionFilter接口,具體代碼如下:

View Code
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Web.Mvc;

namespace MvcFilters.Interface
{
    public interface IExceptionFilter
    {
        void OnException(ExceptionContext filterContext);
    }
}

OnException方法被調用時出現未處理的異常。這個參數方法是一種ExceptionContext對象。這個類別是類似於授權濾波器參數,來自ControllerContext類(所以,你可以得到有關請求的信息)並定義了一些額外的過濾器特定的屬性,具體如下表:

Name Type Description
ActionDescriptor ActionDescriptor 提供詳細的操作方法
Result ActionResult 結果的操作方法,過濾器可以取消
要求將此屬性設置為一個非空值
Exception Exception 未處理的異常
ExceptionHandled bool 另一個過濾器,則返回true,如果有明顯的異常
處理

被拋出的異常,可通過Exception屬性。一個異常過濾器報告說,它已處理異常ExceptionHandled屬性設置為true。所有的異常篩選器應用到一個動作被調用,即使這個屬性被設置為true,所以它是個好習慣檢查是否有另一個過濾器已經處理了這個問題,以避免嘗試恢復從另一個過濾器的問題已經解決。

所使用的異常過濾器的Resultproperty告訴MVC框架做什么。這兩個異常過濾器的主要用途是記錄異常,並顯示一個合適的信息給用戶。下面代碼演示,將用戶重定向到一個特定的錯誤頁面時,特定種類出現未處理的異常。

View Code
using System.Web;
using System.Web.Mvc;

namespace MvcFilters.ContClass
{
    public class MyExceptionAttribute : FilterAttribute, IExceptionFilter
    {
        public void OnException(ExceptionContext filterContext)
        {
            if (!filterContext.ExceptionHandled && filterContext.Exception is NullReferenceException)
            {
                filterContext.Result = new RedirectResult("/SpecialErrorPage.html");
                filterContext.ExceptionHandled = true;
            }
        }
    }
}

該過濾器NullReferenceException的情況下,如果沒有其他異常過濾器處理該異常。我們將用戶重定向到一個特殊的錯誤頁面,這對我們使用一個文字網址。如下代碼,我們可以應用此過濾器

... 
[MyException] 
public ActionResult Index() { 
... 

如果該指數的操作方法拋出一個異常,並且該異常的一個實例的NullReferenceException,並沒有其他的異常過濾器處理異常,那么我們的過濾器重定向用戶的URL到/SpecialErrorPage.html頁面的。

使用內置的異常過濾器

HandleErrorAttribute是內置的實施的IExceptionFilter接口和使得它更輕松地創建異常過濾器。有了它,你可以指定一個異常的視圖的名稱,布局中使用下表中描述的屬性。

Name Type Description
ExceptionType Type 此過濾器處理的異常類型。它也將處理異常類型,繼承從指定的值,但
忽略所有其他的。默認值是System.Exception的,這意味着,默認情況下
,它會處理所有標准例外。
View String 這個過濾器呈現的視圖模板的名稱。如果您
不指定一個值,它的默認值是錯誤,所以
默認情況下,它呈現
/Views/<currentControllerName>/Error.cshtmlor
/Views/Shared/Error.cshtml.
Master string 名稱的布局呈現時使用此過濾器的看法。如果你不指定一個值,該視圖將使用其默認布局
頁。

當遇到未處理的異常的類型指定ExceptionType,這個過濾器將設置HTTP結果代碼500(意思是SERVERERROR)和指定的視圖渲染視圖屬性(使用默認的布局或指定的主)。下面代碼顯示了如何使用HandleErrorAttribute過濾器。

... 
[HandleError(ExceptionType=typeof(NullReferenceException), View="SpecialError")] 
public ActionResult Index() { 
... 

當渲染一個視圖,HandleErrorAttribute過濾器通過HandleErrorInfo的的視圖模型對象,這意味着您可以包括詳細的異常消息中顯示的用戶。具體代碼如下:

View Code
@Model HandelErrorInfo
@{
    ViewBag.Title = "Sorry,there was a problem!";
}
<p> 
There was a <b>@Model.Exception.GetType().Name</b> 
while rendering <b>@Model.ControllerName</b>'s 
<b>@Model.ActionName</b> action. 
</p> 
<p> 
The exception message is: <b><@Model.Exception.Message></b> 
</p> 
<p>Stack trace:</p> 
<pre>@Model.Exception.StackTrace</pre> 

用方法/行動和結果過濾器

動作和結果過濾器是通用的過濾器,可用於任何目的。這兩種遵循常見的模式。內置的類創建這些類型的過濾器,IActionFilter,同時實現了接口。下面代碼顯示了這個接口。

View Code
using System.Text;
using System.Web.Mvc;

namespace MvcFilters.Interface
{
    public interface IActionFilter
    {
        void OnActionExecuting(ActionExecutingContext filterContext);
        void OnActionExcuted(ActionExecutedContext filterContext);
    }
}

這個接口定義了兩個方法。MVC框架調用OnActionExecuting方法之前的操作方法被調用。它調用OnActionExecuted方法后的操作方法被調用。

實現OnActionExecuting方法

OnActionExecuting方法被調用之前調用的操作方法。您可以使用此檢查的要求,選擇取消請求,修改請求,或啟動某些機會活動將跨越調用的動作。該方法的參數是一個
ActionExecutingContext ControllerContext類的子類,並定義了兩個相同的對象,你已經看到在其他上下文對象的性能,如下表所示。

Name Type Descrption
ActionDescriptor ActionDescriptor 提供詳細的操作方法
Result ActionResult 結果的操作方法,過濾器可以取消
要求將此屬性設置為一個非空值

您可以選擇性地取消的請求的參數設置Result屬性作用的結果.具體代碼如下:

View Code
using System.Web;
using System.Web.Mvc;

namespace MvcFilters.ContClass
{
    public class MyActionFilterAttribute : FilterAttribute, IActionFilter
    {
        public void OnActionExecuting(ActionExecutingContext filterContext) 
        {
            if (!filterContext.HttpContext.Request.IsSecureConnection)
            {
                filterContext.Result = new HttpNotFoundResult();
            }
        }
        public void OnActionExecuted(ActionExecutedContext filterContext) 
        {
             //......
        }
    }
}

上面代碼里,我們使用OnActionExecuting方法來檢查請求是否已取得使用SSL。如果沒有,我們返回一個404 - Not Found響應給用戶。

實現OnActionExecuted方法

您還可以使用過濾器來執行一些任務,涵蓋了執行的操作方法。下面寫一個具體的方法代碼:

View Code
using System.Web;
using System.Web.Mvc;

namespace MvcFilters.ContClass
{
    public class ProfileAttribute : FilterAttribute, IActionFilter
    {
        private StopWatch timer;

        public void OnActionExecuting(ActionExecutingContext filterContext)
        {
            timer = Stopwatch.StartNew();
        }
        public void OnActionExecuted(ActionExecutedContext filterContext)
        {
            timer.Stop();
            if (filterContext.Exception == null)
            {
                filterContext.HttpContext.Response.Write(
                string.Format("Action method elapsed time: {0}",
                timer.Elapsed.TotalSeconds));
            }
        } 
    }
}

我們使用OnActionExecuting方法啟動一個定時器(使用Stopwatchtimer System.Diagnostics命名空間中)。在OnActionExecuted方法被調用時,已完成的操作方法。在清單中,我們使用這個方法來停止計時器,寫一個消息的響應,報告所用的時間。

被傳遞到OnActionExecuted方法的參數,該參數是一個ActionExecutedContext對象。這個類定義了一些額外的屬性,如下表所示。 Exception屬性返回任何異常拋出的操作方法,並ExceptionHandled屬性指示是否另一個過濾器處理。

Name Type Description
ActionDescriptor ActionDescriptor 提供詳細的操作方法
Canceled bool 如果另一個過濾器的動作已取消,則返回true
Exception Exception 返回另一個過濾器的操作方法拋出的異常
ExceptionHandled bool 返回true,如果異常被處理
Result ActionResult 結果的操作方法,過濾器可以取消
要求將此屬性設置為一個非空值

被取消的屬性將返回true,如果另一個過濾器已取消的請求(通過設置一個值Result屬性),因為過濾器的OnActionExecuting方法被調用的時間。我們的OnActionExecuted方法仍然是所謂的,但只有這樣,我們可以清理和釋放任何資源,我們所使用的。

實現結果過濾器

動作過濾器和結果過濾器有很多共同點。結果過濾器是采取行動的結果是什么樣的動作過濾器的操作方法。結果過濾器實現IResultFilter接口,具體代碼如下:

View Code
using System.Text;
using System.Web.Mvc;

namespace MvcFilters.Interface
{
    public interface IResultFilter
    {
        void OnResultExecuting(ResultExecutingContext filterContext);
        void OnResultExecuted(ResultExecutedContext filterContext);
    }
}

這讓我們分開
從執行的一個操作方法的意圖。當我們應用過濾器的操作方法,的OnResultExecuting方法被調用一次的動作方法返回一個行動的結果,但在此之前執行的操作的結果。 OnResultExecuted方法被調用執行動作后的結果。這些方法中的參數,以是ResultExecutingContext和ResultExecutedContext對象,分別,他們是非常相似,他們的動作過濾器同行。他們定義了相同的
性能。具體代碼如下:

View Code
using System.Web;
using System.Web.Mvc;

namespace MvcFilters.ContClass
{
    public class ProfileResultAttribute : FilterAttribute, IResultFilter
    {
        private Stopwatch timer;
        public void OnResultExecuting(ResultExecutingContext filterContext)
        {
            timer = Stopwatch.StartNew();
        }
        public void OnResultExecuted(ResultExecutedContext filterContext)
        {
            timer.Stop();
            filterContext.HttpContext.Response.Write(
            string.Format("Result execution - elapsed time: {0}",
            timer.Elapsed.TotalSeconds));
        } 
    }
}

這個過濾器的時間采取措施執行結果。讓我們把過濾器用在來動作方法,具體如下:

View Code
... 
[ProfileResult] 
public ActionResult Index() { 
return View(); 
} 
... 

使用內置的行動和結果過濾器類

MVC框架包括一個內置的類,它可以用來創建兩個行動和結果過濾器。但與內置的授權和異常過濾器,它不提供任何有用的特性。這個類,叫做ActionFilterAttribute,具體代碼如下:

View Code
using System.Web;
using System.Web.Mvc;

namespace MvcFilters.ContClass
{
    public class ActionFilterAttribute : FilterAttribute, IActionFilter, IResultFilter
    {
        public virtual void OnActionExecuting(ActionExecutingContext filterContext) 
        {
        }
        public virtual void OnActionExecuted(ActionExecutedContext filterContext) 
        {
        }
        public virtual void OnResultExecuting(ResultExecutingContext filterContext) 
        {
        }
        public virtual void OnResultExecuted(ResultExecutedContext filterContext) 
        {
        }
    }
}

唯一的好處是,你使用這類不需要實現方法,下面代碼顯示了一個過濾器,ActionFilterAttribute-derived 結合我們的測試的動作方法和行動的結果。

View Code
using System.Web;
using System.Web.Mvc;

namespace MvcFilters.ContClass
{
    public class ProfileAllAttribute : ActionFilterAttribute
    {
        private Stopwatch timer;
        public override void OnActionExecuting(ActionExecutingContext filterContext)
        {
            timer = Stopwatch.StartNew();
        }
        public override void OnActionExecuted(ActionExecutedContext filterContext)
        {
            timer.Stop();
            filterContext.HttpContext.Response.Write(
            string.Format("Action method elapsed time: {0}",
            timer.Elapsed.TotalSeconds));
        }
        public override void OnResultExecuting(ResultExecutingContext filterContext)
        {
            timer = Stopwatch.StartNew();
        }
        public override void OnResultExecuted(ResultExecutedContext filterContext)
        {
            timer.Stop();
            filterContext.HttpContext.Response.Write(
            string.Format("Action result elapsed time: {0}",
            timer.Elapsed.TotalSeconds));
        } 
    }
}

ActionFilterAttribute的類實現了IActionFilter和IResultFilter接口,這意味着MVC框架將把派生類這兩種類型的過濾器,即使不是所有的被覆蓋的方法。如果我們應用的過濾器在上面代碼對我們的行動方法。

過濾沒有屬性

 使用過濾器的正常的方式創建和使用屬性,因為我們已經證明,在以前的部分。然而,還存在另一種使用屬性。 Controller類實現IAuthorizationFilter,IActionFilter,IResultFilter,IExceptionFilter接口。它也提供空的虛擬實現的onXXX方法,你已經看到了,如OnAuthorization和OnException。如下代碼:

View Code
using System.Web;
using System.Web.Mvc;

namespace MvcFilters.Controllers
{
    public class SampleController : Controller
    {
        private Stopwatch timer; 
        public ActionResult Index()
        {
            return View();
        }
        protected override void OnActionExecuting(ActionExecutingContext filterContext)
        {
            timer = Stopwatch.StartNew();
        }
        protected override void OnActionExecuted(ActionExecutedContext filterContext)
        {
            timer.Stop();
            filterContext.HttpContext.Response.Write(
            string.Format("Action method elapsed time: {0}",
            timer.Elapsed.TotalSeconds));
        }
        protected override void OnResultExecuting(ResultExecutingContext filterContext)
        {
            timer = Stopwatch.StartNew();
        }
        protected override void OnResultExecuted(ResultExecutedContext filterContext)
        {
            timer.Stop();
            filterContext.HttpContext.Response.Write(
            string.Format("Action result elapsed time: {0}",
            timer.Elapsed.TotalSeconds));
        }
    }
}

這種技術是非常有用的,當你在項目創建一個基類中的多個控制器。濾波是把整個應用程序所需的代碼到底還是查出了整點在一個可重復使用的位置。

OK,關於過濾器先就介紹這么些東西吧!后續我們有什么就繼續分享,文章肯定有描述錯誤的地方,還請各位前輩及朋友多多指點批評,大家共同進步!


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM