[Nacay] Nancy 的 Before, After and OnError pipelines

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

nancypipeline

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

Image result for microsoft+mvp+logo