C# Owin 創建與測試自己的中間件Middleware(二)


本文純屬介紹怎么簡單地創建自己的Owin。還沒有理解owin概念的請看上一篇文章:http://www.cnblogs.com/alunchen/p/7049307.html

 

目錄

1.創建項目

2.導入Nuget包

3.創建Startup類

4.創建自己的中間件Middleware

5.把中間件加入owin

6.測試

7.總結

 

 

本文是以WebApi空項目來創建owin的。使用工具VS2017

1.創建項目

創建一個空的webapi項目

 

2.導入Nuget包

Install-Package Owin

Install-Package Microsoft.Owin

Install-Package Microsoft.Owin.Host.SystemWeb

可以看到導入成功后,項目的引用多了下面的包。

image

 

3.創建Startup類

為什么要創建Startup類呢?

因為owin中有這樣的規定:啟動類定義為:Startup。在這個類中有一個Configuration方法,這是它的規定,owin會自動查找此類此方法並執行。

下面是我的Startup類

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using Microsoft.Owin;
using MyTestOwin.Middleware;
using Owin;

[assembly: OwinStartup(typeof(MyTestOwin.Startup))]
namespace MyTestOwin
{
    public class Startup
    {
        public void Configuration(IAppBuilder app)
        {
        }

    }
}

 

4.創建自己的中間件Middleware

創建自己的中間件的話,首先要繼承OwinMiddleware類,他是抽象類。可以看看此類上有什么內容:

image

此類主要有1個構造函數、1個屬性、1個抽象方法。

構造函數OwinMiddleware:作用是初始化下一個可選的中間件。

屬性Next:意思是下一個中間件。

抽象方法Invoke:創建自己的中間件都要重寫此方法。此方法在中間件運行的時候就運行,處理個人請求。

 

下面我們來繼承OwinMiddleware類,並且重構構造函數、重寫Invoke方法。類名字為Middleware1

直接貼代碼,沒什么可說的,可以看注釋:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Web;
using Microsoft.Owin;

namespace MyTestOwin.Middleware
{
    public class Middleware1:OwinMiddleware
    {

        public Middleware1(OwinMiddleware next):base(next)
        { }


        public override Task Invoke(IOwinContext context)
        {
            if (context.Request.Path == new PathString("/owin1"))
            {
                var msg = "Owin1";
                var msgBytes = Encoding.UTF8.GetBytes(msg);
                context.Response.ContentType = "text/html;charset=utf-8";
                context.Response.Write(msgBytes, 0, msgBytes.Length);
                //解答者告訴Server解答已經完畢,后續Middleware不需要處理
                return Task.FromResult(0);
            }
            //如果不是要處理的路徑,那么交付后續Middleware處理
            return Next.Invoke(context);
        }
    }
}

解析一下上面代碼:

  1. 首先,我們判斷一下請求的link是否為’/owin1’?
  2. 如果是,則執行我們想要的方法,並且執行完畢,后續所有的中間件以及controller等都不做執行處理。
  3. 如果不是,則執行下一個中間件,直到找到對應的中間件為止。如果中間件最后找不到,則到controller里面找。

下面理清一下:

  • PathString是Miscrosoft.Owin下一個類,封裝了URL處理的一些功能.
  • Task.FromResult(0) 表示一個空的Task,說明該Middleware在某些情況下不再觸發后續的Middleware運行—也就是”到此為止”.
  • 最后Next.Invoke(context)是一個非常標准的實現,把上下文交付下一個Middleware繼續處理—相當於”交出接力棒”.
  • 這個Middleware是一個標准的解答者.它給出了”/owin1”這個問題的最終答案.

 

5.把中間件加入owin

下面我們把中間件Middleware1加入到owin中。

很簡單,只需要在Startup類的Configuration方法中,加入下面的代碼:

app.Use<Middleware1>();

 

6.測試

1)為了方便測試&理解,我們再加入一個中間件Middleware2類,並且執行owin2 的path,代碼如下:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Web;
using Microsoft.Owin;

namespace MyTestOwin.Middleware
{
    public class Middleware2 : OwinMiddleware
    {

        public Middleware2(OwinMiddleware next):base(next)
        { }


        public override Task Invoke(IOwinContext context)
        {
            if (context.Request.Path == new PathString("/owin2"))
            {
                var msg = "owin2";
                var msgBytes = Encoding.UTF8.GetBytes(msg);
                context.Response.ContentType = "text/html;charset=utf-8";
                context.Response.Write(msgBytes, 0, msgBytes.Length);
                //解答者告訴Server解答已經完畢,后續Middleware不需要處理
                return Task.FromResult(0);
            }
            //如果不是要處理的路徑,那么交付后續Middleware處理
            return Next.Invoke(context);
        }
    }
}

2)再在Startup類中加入自定義中間件:

app.Use<Middleware2>();

整體代碼如下:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using Microsoft.Owin;
using MyTestOwin.Middleware;
using Owin;

[assembly: OwinStartup(typeof(MyTestOwin.Startup))]
namespace MyTestOwin
{
    public class Startup
    {
        public void Configuration(IAppBuilder app)
        {
            //注意:這里的順序是與owin中間件類執行的順序一樣。
              app.Use<Middleware1>();
            app.Use<Middleware2>();
        }

    }
}

3)在寫一個繼續ApiController的類,請求路徑為:http://xx/api/values/get

using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Web.Http;

namespace MyTestOwin.Controllers
{
    [RoutePrefix("api/values")]
    public class ValuesController : ApiController
    {
        [Route("get")]
        [HttpGet]
        public IEnumerable<string> Get()
        {
            return new string[] { "value1", "value2" };
        }
    }
}

 

加上上面的所有東西,讓我們更好地理解owin做了什么操作,與我們平時所寫的apicontroller有什么聯系。

下面,我們開始啟動項目:

我們分別打一個斷點在Startup類的方法Configuration中、Middleware1的Invoke方法、Middleware2的Invoke方法。

項目啟動了,先執行Startup中的Configuration、再執行Middleware1、最后執行Middleware2。

請注意的是,這里的項目啟動的路徑是 http://localhost:52023/,並沒有二級路徑。上面都執行了中間件。

也就是說,我們的中間件注冊后,所有的請求都經過我們的中間件

 

測試一:在瀏覽器上輸入 http://localhost:52023/api/values/get

      第一執行Middleware1、第二執行Middleware2、最后是ValuesController。並且返回controller的結果:

image

 

測試二:在瀏覽器上輸入 http://localhost:52023/owin1
      第一執行Middleware1,最后也是它執行。返回結果是:

image

 

測試三:在瀏覽器上輸入http://localhost:52023/owin2

      第一執行Middleware1、最后執行Middleware2。返回結果是:

image

 

7.總結

我們通過自己的測試,可以總結到的是:

1)我們在startup類中注冊的中間件順序是中間件執行的順序。

2)每個請求都會執行中間件的Invoke方法,直到有請求的結果為止。

3)從測試看出,中間件有點類似於攔截器。

 

可以到github上面下載項目 https://github.com/cjt321/MyTestOwin/

 

可以關注本人的公眾號,多年經驗的原創文章共享給大家。


免責聲明!

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



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