Before, After and OnError pipelines,就像是 ASP.NET Web API / MVC .NET Web API / MVC 裡面的 Filter、Handler 一樣,可以加入我們想要處理的流程,比如集中管理 Error (Global Error Handler)、身分驗證、功能授權、記錄診斷日誌;它就是 Nancy 的攔截器。
Lifecycle
只要知道 Nacny 處理 Pipeline 的順序,接下來的實作就不卡卡
下圖出自:https://github.com/NancyFx/Nancy/wiki/Lifecycle-of-a-Nancy-Application
Pipeline
Before
- 處理 Request 之前要做的事。
- 如果返回 null,主動權交給 Route。
- 若返回 Response 物件,Route 不作用,放棄 Request。
- 可以修改、替換 Request。
After
- 完成 Action 之後要做的事。
- 沒有回傳值。
- 可以修改、替換 Response。
OnError
- 出錯之後要做的事。
而這三個 Pipeline 分别實作
AsyncNamedPipelineBase<TAsyncDelegate, TSyncDelegate> 和 NamedPipelineBase<TDelegate>
接下來來看用法
實作
用法一:在 NancyModule 使用
NancyModule 提拱了這三個屬性,在建構函數明白的定義要做的事即可,另外,定義一個 /error 來觀察 OnError 的效果
public class GeneratorNancyModule : NancyModule { public GeneratorNancyModule() { this.Before += p => { Console.WriteLine("OnBefore"); return null; }; this.After += p => { Console.WriteLine("OnAfter"); }; this.OnError += (p, ex) => { Console.WriteLine(ex.ToString()); return null; }; this.ModulePath = "api/generator"; this.Get["/guid"] = p => Guid.NewGuid().ToString(); this.Get["/error"] = p => throw new Exception("壞掉了唷"); } }
訪問 http://localhost:9527/api/generator/guid 的效果如下:
訪問 http://localhost:9527/api/generator/error 的效果如下:
當然,我們也可以將這些 Pipeline 集中到另一個基礎類別
public class BaseModule : NancyModule { public BaseModule() { this.Before += p => { Console.WriteLine("OnBefore"); return null; }; this.After += p => { Console.WriteLine("OnAfter"); }; this.OnError += (p, ex) => { Console.WriteLine(ex.ToString()); return null; }; } }
public class GeneratorNancyModule : BaseModule { public GeneratorNancyModule() { ... } }
用法二:在 CustomBootstrapper 中重寫 RequestStartup 或 ApplicationStartup
這裡我用 RequestStartup 演示,ApplicationStartup 也是一樣的用法
public class CustomBootstrapper : DefaultNancyBootstrapper
{
protected override void RequestStartup(TinyIoCContainer container, IPipelines pipelines, NancyContext context)
{
base.RequestStartup(container, pipelines, context);
pipelines.BeforeRequest += p =>
{
Console.WriteLine("OnBefore");
return null;
};
pipelines.AfterRequest += p => { Console.WriteLine("OnAfter"); };
pipelines.OnError += (p, ex) =>
{
Console.WriteLine(ex.ToString());
return null;
};
}
}
用法三:自訂 Pipeline
在 CustomApplicationStartup 實作 IApplicationStartup
public class CustomApplicationStartup : IApplicationStartup { public void Initialize(IPipelines pipelines) { pipelines.BeforeRequest.AddItemToEndOfPipeline(p => { Console.WriteLine("OnBefore"); return null; }); pipelines.AfterRequest.AddItemToEndOfPipeline(p => { Console.WriteLine("OnAfter"); }); pipelines.OnError.AddItemToEndOfPipeline((p, ex) => { Console.WriteLine(ex.ToString()); return null; }); } }
若有謬誤,煩請告知,新手發帖請多包涵
Microsoft MVP Award 2010~2017 C# 第四季
Microsoft MVP Award 2018~2022 .NET