MVC 過濾器


  在mvc中,過濾器是無此不在,可能沒有顯示的去調用,所以很多人還不是很理解,本節就通過幾個例子來說明一下mvc中過濾器的使用。

一、過濾器概況

  為什么說過濾器在mvc中無此不在呢?默認添加一個的控制器,會發現其繼承的是Controller類,在Controller上面按F12轉到定義:

public abstract class Controller : ControllerBase, IActionFilter, IAuthorizationFilter, IDisposable, IExceptionFilter, IResultFilter

 其中上面的幾個接口,帶有Filter后綴名的,也就是我們本節要說明的過濾器了,共四個:ActionFilter(方法過濾器),ResultFilter(結果過濾器,感覺不是很好聽,就這樣叫吧),AuthorizationFilter(授權過濾器),ExceptionFilter(異常處理過濾器)。現在應該知道無處不在的原因了吧,難道說你不是用Controller。好了廢話不多扯了,開始進入我們的正題。

二、過濾器說明

2.1 IActionFilter有兩個方法:

        // 摘要:
        //     Called after the action method executes.
        //
        // 參數:
        //   filterContext:
        //     The filter context.
        void OnActionExecuted(ActionExecutedContext filterContext);
        //
        // 摘要:
        //     Called before an action method executes.
        //
        // 參數:
        //   filterContext:
        //     The filter context.
        void OnActionExecuting(ActionExecutingContext filterContext);
View Code

一個是在調用前使用,一個是在調用后使用的。
2.2同樣IResultFilter也有兩個方法:

        // 摘要:
        //     Called after an action result executes.
        //
        // 參數:
        //   filterContext:
        //     The filter context.
        void OnResultExecuted(ResultExecutedContext filterContext);
        //
        // 摘要:
        //     Called before an action result executes.
        //
        // 參數:
        //   filterContext:
        //     The filter context.
        void OnResultExecuting(ResultExecutingContext filterContext);
View Code

2.3 IAuthorizationFilter:

void OnAuthorization(AuthorizationContext filterContext);

這個是在所有過濾器調用之前調用的方法。
2.4 IExceptionFilter

void OnException(ExceptionContext filterContext);

這個是在異常發生時調用。

感覺講的還是不夠清楚,使用書中的一個表格來說明:(雖然是e文,感覺不是很難看懂)

好了,簡單的也說明了一些上面的方法,可能還是不清楚怎么去使用這些過濾器。接下來我將會先比較一下他們的相同點,然后去舉幾個例子來說明其用途。

三、過濾器的使用

3.1共同點

現在我們回頭來看上面幾個接口的方法,主要是看其形參——一個共同的特點是其包括一個基類為ControllerContext的形參。這個參數有很多有用的屬性,如HttpContextBase,ControllerBase,RouteData等這些屬性都直接關系着我們http請求以及請求的去向。

3.2實例

接下來就來看幾個實例,感受一下過濾器的厲害:如果例子中有不足的地方,或者有更好的使用,請大牛指點。

例子1.讓含有admin的controller必須要登陸,否則轉到登陸界面。

    public class AdminActionFilter:Controller
    {
        
        protected override void OnActionExecuting(ActionExecutingContext filterContext)
        {
            //當controller里面含有admin並且session為空時,轉到登陸頁
            if (filterContext.RouteData.Values["controller"].ToString().ToLower().Contains("admin")
                && filterContext.HttpContext.Session.Count==0)
            {
                filterContext.Result = RedirectToAction("LogOn", "Account");//Account/LogOn
                return;
            }
        }
    }

然后讓admin文件夾里面的controller去實現繼承我們定義的AdminActionFilter.

例子2.統計異常(該實例基於HandleErrorAttribute)

public class CustomExceptionFilter : HandleErrorAttribute
    {
        public override void OnException(ExceptionContext filterContext)
        {
            //如果異常未處理
            if (!filterContext.ExceptionHandled)
            {
                Exception innerException = filterContext.Exception;
                //如果錯誤碼為500
                if ((new HttpException(null, innerException).GetHttpCode() == 500) && this.ExceptionType.IsInstanceOfType(innerException))
                {
                    //獲取出現異常的controller名和action名,用於記錄
                    string controllerName = (string)filterContext.RouteData.Values["controller"];
                    string actionName = (string)filterContext.RouteData.Values["action"];
                    //定義一個HandErrorInfo,用於Error頁使用
                    HandleErrorInfo model = new HandleErrorInfo(filterContext.Exception, controllerName, actionName);
                   //ViewResult是ActionResult,經常出現在controller中action方法return后面,但是出現形式是View()
                    ViewResult result = new ViewResult
                    {
                        ViewName = this.View,
                        MasterName = this.Master,
                        //定義ViewData,使用的是泛型
                        ViewData = new ViewDataDictionary<HandleErrorInfo>(model),
                        TempData = filterContext.Controller.TempData
                    };
                    filterContext.Result = result;
                    filterContext.ExceptionHandled = true;
                    filterContext.HttpContext.Response.Clear();
                    filterContext.HttpContext.Response.StatusCode = 500;
                    filterContext.HttpContext.Response.TrySkipIisCustomErrors = true;
                }
            }
            base.OnException(filterContext);
        }
    }

然后前台的error.cshtml應該更改為

@model System.Web.Mvc.HandleErrorInfo

@{
    ViewBag.Title = "錯誤";
}
    <p> 
        錯誤類型: <b>@Model.Exception.GetType().Name</b> 
        控制器和方法名稱 <b>@Model.ControllerName</b>'s <b>@Model.ActionName</b>  
    </p> 
    <p> 
        異常信息 <b><@Model.Exception.Message></b> 
    </p> 
@***********************************************************
這部分可以用來測試用
*************************************************************   
 <p>堆棧信息:</p> 
    <pre>@Model.Exception.StackTrace</pre>
        <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>*@
View Code
之后web.config里面 由於我們的view中的error頁面可能會出現異常,所以為了防止這樣的問題發生, <system.web/>節點里面可以配置一下,<customErrors mode="On" defaultRedirect="ErrorPage.htm">
使用global文件注冊過濾器。
如果沒有使用global注冊的話,只能一個個去實現,所以我們最好使用哦global去實現注冊。
  public static void RegisterGlobalFilters(GlobalFilterCollection filters)       
 {            //filters.Add(new HandleErrorAttribute());       
      filters.Add(new CustomExceptionFilter());   
 }
下面我把異常處理的源碼上傳上去,僅供參考。
源碼

 

 
        

 

 

 


免責聲明!

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



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