Filter延續了ASP.Net MVC5的設計,
可在各Pipeline執行前與執行後指定需觸發的事件,
本文將介紹ASP.Net Core Filter的使用方式。
ASP.Net Core中預設有五種Filter:
- Authorization Filter
- Resource Filter
- Action Filter
- Exception Filter
- Result Filter
(圖片來源:MSDN)
在執行優序上,
Authorization Filter
>Resource Filter
>Exception Filter
>Action Filter
>Result Filter
所以如果是在Authorization Filter
、Resource Filter
階段發生錯誤,
則無法被Exception Filter
捕捉(要自訂錯誤處理方式)。
Filter Attribute
可以在三個地方宣告,
- Startup:執行範圍為全域(Global)
- Controller:執行範圍為Controller本身
- Action:執行範圍為Action本身
在執行順序上,
Startup
>Controller
>Action
,
雖然可以透過Order自訂順序,
但筆者個人認為正常使用下不太會用到,
如果有需要的讀者可參考MSDN。
Authorization Filter
Authorization可以處理跟授權相關的邏輯,
而授權的方式有很多種,
如簡單型授權、角色授權、宣告式授權等。
當系統功能需要依據某種條件賦予使用權力時,
使用Authorization Filter會是個不錯的用法(你也可以自訂Middleware)。
礙於授權本身範疇較大,
筆者將於後面文章中進行更詳細的說明。
Resource Filter
Resource Filter可以依據自訂的條件,
決定是否繼續後面的流水線(Pipeline),
達到為網站節省資源的目的。
使用時必須實作 IResourceFilter
或 IAsyncResourceFilter
介面。
OnResourceExecuting
表Request in的Pipeline,
OnResourceExecuted
介面則代表Response out。
官方提供的使用時機為限制檔案上傳大小,
這情境雖然簡單但還蠻實用的,
我們迅速的來實作一個IResourceFilter
。
如果要使用Attribute的形式則必須要實作Attribute
。
public class AllowFileSizeAttribute : Attribute, IResourceFilter
{
private long maxSize;
public AllowFileSizeAttribute(long _maxSize)
{
this.maxSize = _maxSize;
}
public void OnResourceExecuting(ResourceExecutingContext context)
{
var contentLength = context.HttpContext.Request.ContentLength;
if (contentLength > maxSize)
{
context.Result = new ContentResult()
{
Content = $"You can't upload file size over {maxSize / 1024}KB."
};
}
}
public void OnResourceExecuted(ResourceExecutedContext context)
{
}
}
前端程式碼
我們在任意View中新增一個上傳表單,
請注意一定要給name
不然後端會認不得!
<form asp-action="Create" enctype="multipart/form-data">
<div class="form-group">
<label class="control-label">檔案上傳</label>
<input type="file" class="form-control" name="file" />
</div>
<div class="form-group">
<input type="submit" value="Create" class="btn btn-default" />
</div>
</form>
最後在Action中掛上小巧玲瓏的Attribute,
我們設定檔案大小不得超過2048B(=2KB)。
[AllowFileSize(2048)]
[HttpPost]
public IActionResult Create()
{
return View();
}
使用Debug模式觀察檔案大小。
測試結果
Action Filter & Result Filter
ActionFilter有同步跟非同步兩種版本 - IActionFilter
、 IAsyncActionFilter
。
依執行前和執行後可分 OnActionExecuting
、 OnActionExecuted
兩種方法,
主要可處理輸入值(After ModelBinding)或Controller Context相關結果。
也可直接指定回傳的Result(後面優序的Filter就不會被觸發)。
官方提供範例為處理ModelState驗證結果。
ResultFilter一樣有 IResultFilter
、 IAsyncResultFilter
兩種版本。
依執行前和執行後可分 OnResultExecuting
、 OnResultExecuted
兩種方法,
OnResultExecuted
會在回傳Response後呼叫,
所以若有跟Response相關的操作請在 OnResultExecuting
中處理。
官方有提供ActionFilterAttribute類別,
內容涵蓋了ActionFilter及ResultFilter兩種,
大家可依個人需求搭配使用。
Exception Filter
實作 IExceptionFilter
或 IAsyncExceptionFilter
可自訂Exception Filter,
官方提供範例為自訂開發環境錯誤頁面,
Exception Filter能捕捉的範圍如下:
- Model Binding Exception
- Controller Invoke Exception
- Action Filter & Result Filter Exception
筆者將於後面獨立一篇介紹Exception Filter與Exception Middleware的使用差異。
結語
自從Middleware出來之後Filter好像就有點被遺棄無力(咦?),
雖然筆者比較推Middleware的設計方式(彈性),
不過Filter還是很好用啦XD,
如果文章內容有誤的再麻煩指正,謝謝!
參考