ASP.Net MVC過濾器
在ASP.NET MVC中,控制器定義的操作方法通常與可能的用戶交互具有一對一的關係,但有時候您希望在調用操作方法之前或者在操作方法運行之後執行邏輯。
爲了支持這個功能,ASP.NET MVC提供了過濾器。 過濾器是一個自定義類,它提供了一種聲明式和程序式的方法,可將操作前和操作後行爲添加到控制器操作方法中。
動作過濾器
動作過濾器是一個屬性,可以將其應用於控制器動作或整個控制器,以修改執行動作的方式。 ASP.NET MVC框架包含幾個操作過濾器 -
- OutputCache - 將控制器操作的輸出緩存指定的時間量。
- HandleError - 處理執行控制器操作時引發的錯誤。
- Authorize - 使能夠限制對特定用戶或角色的訪問。
過濾器的類型
ASP.NET MVC框架支持四種不同類型的過濾器 -
- 授權過濾器 - 實現
IAuthorizationFilter
屬性。 - 動作過濾器 - 實現
IActionFilter
屬性。 - 結果過濾器 - 實現
IResultFilter
屬性。 - 異常過濾器 - 實現
IExceptionFilter
屬性。
過濾器按上面列出的順序執行。例如,授權過濾器始終在每個其他類型的過濾器之後執行操作過濾器和異常過濾器之前執行。
授權過濾器 用於實現控制器操作的身份驗證和授權。 例如,授權過濾器是授權過濾器的一個例子。
下面來看一個簡單的例子,創建一個新的ASP.Net MVC項目。打開Visual Studio,然後單擊菜單:文件 -> 新建 -> 項目 選項。創建一個名稱爲:MVCFiltersDemo 的MVC項目。
詳細創建過程請參考:http://www.yiibai.com/asp.net\_mvc/asp.net\_mvc\_getting\_started.html
通過在解決方案資源管理器 中右鍵單擊 Controllers 文件夾來添加一個控件器:HomeController。在彈出菜單項中選擇:添加 -> 控制器 。
應用操作篩選器
動作過濾器可以應用於單獨的控制器動作或整個控制器。 例如,操作篩選器OutputCache
應用於名爲Index()
的操作,該操作返回字符串。 此過濾器會將該操作返回的值緩存15秒。
爲了使這個實現這個例子,讓我們修改控制器類通過改變稱爲Index
操作方法使用下面的代碼 -
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
namespace MVCFiltersDemo.Controllers
{
public class HomeController : Controller
{
// GET: Home
// GET: Home
[OutputCache(Duration = 15)]
public string Index()
{
return "This is ASP.Net MVC Filters Tutorial";
}
}
}
運行此應用程序時,將看到瀏覽器正在顯示Index
操作方法的結果,如下所示 -
再添加另一個操作方法,它用於顯示當前時間 -
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
namespace MVCFiltersDemo.Controllers
{
public class HomeController : Controller
{
// GET: Home
[OutputCache(Duration = 15)]
public string Index()
{
return "This is ASP.Net MVC Filters Tutorial";
}
// 返回當前時間
[OutputCache(Duration = 20)]
public string GetCurrentTime()
{
return DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
}
}
}
請求以下URL:http://localhost:54713/Home/GetCurrentTime
,將收到以下輸出 -
如果刷新瀏覽器,則會看到相同的時間,因爲該操作被緩存了20
秒。 20
秒後刷新它將被更新。
自定義過濾器
要創建自己的自定義過濾器,ASP.NET MVC框架提供了一個叫作ActionFilterAttribute
的基類。 這個類實現了IActionFilter
和IResultFilter
接口,都是從Filter
類派生的。
下面來看看看自定義過濾器的一個簡單的例子,通過在項目中創建一個新的文件夾:ActionFilters 。添加一個類,右鍵單擊ActionFilters 文件夾並選擇:添加 -> 類 。
在類名稱字段中輸入MyLogActionFilter,然後單擊「添加」 按鈕。
這個類將從ActionFilterAttribute
派生,它是一個基類,並覆蓋下面的方法。 以下是MyLogActionFilter
的完整實現。
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.Web.Routing;
namespace MVCFiltersDemo.ActionFilters
{
public class MyLogActionFilter: ActionFilterAttribute
{
public override void OnActionExecuted(ActionExecutedContext filterContext)
{
Log("##########OnActionExecuted", filterContext.RouteData);
}
public override void OnResultExecuting(ResultExecutingContext filterContext)
{
Log("##########OnResultExecuting", filterContext.RouteData);
}
public override void OnResultExecuted(ResultExecutedContext filterContext)
{
Log("##########OnResultExecuted", filterContext.RouteData);
}
private void Log(string methodName, RouteData routeData)
{
var controllerName = routeData.Values["controller"];
var actionName = routeData.Values["action"];
var message = String.Format(
"{0} controller:{1} action:{2}", methodName, controllerName, actionName);
System.Console.WriteLine("############################# YES ##################");
Debug.WriteLine(message, "Action Filter Log");
}
}
}
現在,使用以下代碼將日誌過濾器應用於HomeController
控制器。
using MVCFiltersDemo.ActionFilters;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
namespace MVCFiltersDemo.Controllers
{
[MyLogActionFilter]
public class HomeController : Controller
{
// GET: Home
[OutputCache(Duration = 10)]
public string Index()
{
return "This is ASP.Net MVC Filters Tutorial";
}
// 返回當前時間
[OutputCache(Duration = 10)]
public string GetCurrentTime()
{
return DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
}
}
}
打開項目中的App_Start,打開文件FilterConfig.cs ,添加以下代碼註冊過濾器:MyLogActionFilter -
using MVCFiltersDemo.ActionFilters;
using System.Web;
using System.Web.Mvc;
namespace MVCFiltersDemo
{
public class FilterConfig
{
public static void RegisterGlobalFilters(GlobalFilterCollection filters)
{
filters.Add(new HandleErrorAttribute());
// 註冊自定義Action過濾器:優先級最低,但是可以作用到所有的控制器和Action
filters.Add(new MyLogActionFilter());
}
}
}
運行應用程序,然後觀察輸出窗口。應該會看到類似(輸出的最後幾行)的結果 -
如上圖所示,處理動作的每個階段都有被記錄到Visual Studio輸出窗口中了。