OWIN katana註冊中間件的幾種寫法

首先特別說明下在startup中註冊完中間件的兩個注意事項,看到有人寫的東西有誤導人的做用。關於startup啓動發現類的內容,參照這裏 http://www.asp.net/aspnet/overview/owin-and-katana/owin-startup-class-detectionapp

1. 使用IApplicationBuilder.User註冊中間件是有前後順序關係的。asp.net

2. 註冊的中間件的執行過程是這樣的:輸入初始化是按照順序來的,輸出執行是反順序來的。

請求發生-->初始化中間件1--->初始化中間件n-->app忽略中間件方法,直接響應輸出--------->中間件n Invoke執行處理-->中間件1 Invoke執行處理--->響應輸出async

 

進入正文ide

OWIN middleware 必須是具備如下代碼特徵,要麼是直接在startup類中直接註冊,要麼就是寫的中間件類中方法返回。ui

Func<IDictionary<string, object>, Task> //這個function具備一個上下文的字典參數(OWIN environment dictionary),並返回Task

這段特徵碼中的IDictionary<string, object>其實已經被katana的server層包裝成字典形式的請求上下文(HttpContext)IOwinContext,能夠使用上下文屬性environment訪問字典值this

 咱們會以這種形式註冊中間件spa

IApplicationBuilder Use(Func<RequestDelegate, RequestDelegate> middleware); //middleware 能夠是委託 or  類型 or 實例

中間件註冊進入管道,因爲中間件返回一個Task,就能保證管道在處理的時候能找到下一個執行的Task就是下邊代碼中的next參數,那麼next就是已知的第一個RequestDelegate參數來處理請求和響應。Task就是返回的具備中間件特徵的中間件。.net

 


 

 

下面咱們看下第一種寫法code

app.Use(new Func<RequestDelegate, RequestDelegate>(next => (async context =>
{
    Console.WriteLine("初始化組件開始");
    await next.Invoke(context);
    Console.WriteLine("管道下步執行完畢");
})));

以上代碼中會在請求時在控制檯輸出「初始化組件開始」,當組件的下一個步驟執行完畢後,會再打印出「管道下步執行完畢」。server

有時候組件裏沒啥規則,可是也必須接受next做爲參數,可是能夠忽略它,而且仍然須要返回一個task,因此能夠這樣寫

app.Use(new Func<RequestDelegate, RequestDelegate>(ignoreNext => (content=>
{
    Console.WriteLine("The request ends with me!");
    return Task.FromResult(0);
})));

 



第二種寫法
是將已有的方法傳遞給委託。若是你有一些邏輯須要抽象出來,但又不想單獨寫一箇中間件類,這個寫法就比較合適

public class Startup
{
    public void Configuration(IAppBuilder app)
    {
        app.Use(new Func<RequestDelegate, RequestDelegate>(next => content=> Invoke(next, content)));
    }

    private async Task Invoke(RequestDelegate next, IDictionary<string, object> environment) 
    {
        Console.WriteLine("初始化組件開始");
        await next.Invoke(environment);
        Console.WriteLine("管道下步執行完畢");
    }
}

 


 

若是使用一下代碼註冊組件,那麼久必須寫一個實際的中間件類了

app.Use(typeof(LoggingMiddleware));

或者以中間件實例來註冊

app.Use(new LoggingMiddleware());

第三種寫法是實現一個實際的中間件類

public class LoggingMiddleware
{
    private RequestDelegate next;

    public LoggingMiddleware(RequestDelegate next)
    {
        this.next = next;
    }

    public async Task Invoke(IDictionary<string, object> environment)
    {
        Console.WriteLine("初始化組件開始");
        await next.Invoke(environment);
        Console.WriteLine("管道執行完畢");
    }
}

 


 

 第四種寫法咱們能夠集成Microsoft.Owin庫中的OwinMiddleware基類來實現中間件類。它提供了強類型訪問IOwincontext。

public class LoggingMiddleware : OwinMiddleware
{
    public LoggerMiddleware(OwinMiddleware next)
        : base(next)
    {
    }

    public async override Task Invoke(IOwinContext context)
    {
        Console.WriteLine("初始化組件開始");
        await Next.Invoke(context);
        Console.WriteLine("管道執行完畢");
    }
}

以上幾種寫法實現都幹了同樣的事情,其實更多複雜的中間件定義能夠參考下Microsoft.AspNet.Diagnostics下的幾種中間件實現方式,比入WelcomePageMiddleware.cs,就是咱們在app中使用UserWelcomPage()方法註冊的中間件。

相關文章
相關標籤/搜索