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


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

1. 使用IApplicationBuilder.User注冊中間件是有先后順序關系的。

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

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

 

進入正文

OWIN middleware 必須是具有以下代碼特征,要么是直接在startup類中直接注冊,要么就是寫的中間件類中方法返回。

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

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

 我們會以這種形式注冊中間件

IApplicationBuilder Use(Func<RequestDelegate, RequestDelegate> middleware); //middleware 可以是委托 or  類型 or 實例

中間件注冊進入管道,由於中間件返回一個Task,就能保證管道在處理的時候能找到下一個執行的Task就是下邊代碼中的next參數,那么next就是已知的第一個RequestDelegate參數來處理請求和響應。Task就是返回的具有中間件特征的中間件。

 


 

 

下面我們看下第一種寫法

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

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

有時候組件里沒啥規則,但是也必須接受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()方法注冊的中間件。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM