[Web API] Web API 2 深入系列(2) 消息管道


目錄

  1. HttpMessageHandler

  2. Web Host模式處理過程

  3. Self Host模式處理過程

HttpMessageHandler

Web API處理管道由一系列HttpMessageHandler組成

public abstract class HttpMessageHandler : IDisposable
{
    protected internal abstract Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken);
    
    protected virtual void Dispose(bool disposing)

    public void Dispose()
}

而一般在管道中,我們使用DelegatingHandler

public abstract class DelegatingHandler : HttpMessageHandler
{
    public HttpMessageHandler InnerHandler { get; set; }
    protected internal override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
    {
        return this.innerHandler.SendAsync(request, cancellationToken);
    }
}

頭部是HttpServer

public class HttpServer : DelegatingHandler
{
    public HttpMessageHandler Dispatcher { get; }
    public HttpConfiguration Configuration { get; }
    protected virtual void Initialize()
    {
        this.InnerHandler = HttpClientFactory.CreatePipeline(this._dispatcher, (IEnumerable<DelegatingHandler>) this._configuration.MessageHandlers);
    }
    protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
    {
        this.EnsureInitialized();
        return await base.SendAsync(request, cancellationToken);
    }
}

其中Dispatcher就是管道的尾部
默認為HttpRoutingDispatcher

public class HttpRoutingDispatcher : HttpMessageHandler
{
    public HttpConfiguration Configuration { get; }
    private readonly HttpMessageInvoker _defaultInvoker = new HttpControllerDispatcher(configuration);

    public HttpRoutingDispatcher(HttpConfiguration configuration, HttpMessageHandler defaultHandler)

    protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
    {
        //1. Routing
        IHttpRouteData routeData = request.GetRouteData();
        if (routeData == null)
        {
        routeData = this._configuration.Routes.GetRouteData(request);
        if (routeData != null)
            request.SetRouteData(routeData);
        }
        //2. Dispatcher
        this._defaultInvoker.SendAsync(request, cancellationToken);
    }
}

實現Dispatcher(選擇IHttpController)的對象默認為HttpControllerDispatcher

public class HttpControllerDispatcher : HttpMessageHandler
{
    protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
    {
        HttpControllerDescriptor controllerDescriptor = this.ControllerSelector.SelectController(request);
        IHttpController controller = controllerDescriptor.CreateController(request);
        return await controller.ExecuteAsync(controllerContext, cancellationToken);
    }
}

驗證管道

public class DemoController : ApiController
{
    public IEnumerable<string> Get()
    {
        var cfg = new HttpConfiguration();
        cfg.MessageHandlers.Add(new Handler1());
        cfg.MessageHandlers.Add(new Handler1());
        cfg.MessageHandlers.Add(new Handler1());
        var server = new MyServer(cfg);
        server.Initialize();//生成HttpMessageHandler鏈
        return GetHandlers(server);
    }

    private IEnumerable<string> GetHandlers(MyServer server)
    {
        DelegatingHandler next = server;
        yield return next.ToString();
        while (next.InnerHandler != null)
        {
            yield return next.InnerHandler.ToString();
            next = next.InnerHandler as DelegatingHandler;
            if (next == null)
                break;
        }
    }
}
class MyServer : HttpServer
{
    public MyServer(HttpConfiguration cfg) : base(cfg) { }

    public new void Initialize()//暴露Initialize方法
    {
        base.Initialize();
    }
}
class Handler1 : DelegatingHandler
{
    protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
    {
        throw new NotImplementedException();
    }
}

瀏覽器中請求:

Web Host模式處理過程

上節我們說到HttpControllerHandler為Web Host下的處理程序.

public class HttpControllerHandler : HttpTaskAsyncHandler
{
    private readonly HttpMessageInvoker _server = GlobalConfiguration.DefaultServer;

    public override Task ProcessRequestAsync(HttpContext context)
    {
        response = await this._server.SendAsync(request, cancellationToken);
        await response.Content.CopyToAsync(context.Response.OutputStream);
    }
}

從上面的代碼中我們看到

  1. HttpControllerHandler實現的是異步HttpControllerHandler接口

  2. 在ProcessRequestAsync方法中 通過GlobalConfiguration.DefaultServer 啟動了WebAPI管道

Self Host模式處理過程

Self Host目前可以說分為2種

  1. OWIN
  2. HttpBinding

本節重點說明一下傳統方式的HttpBinding,WebAPI使用的Message為HttpMessage
通過Nuget可以非常方便的操作

Install-Package Microsoft.AspNet.WebApi.SelfHost

using (var server = new HttpSelfHostServer(new HttpSelfHostConfiguration("http://localhost:10000")))
{
    server.Configuration.Routes.MapHttpRoute("default", "{controller}");
    server.OpenAsync();
    Console.Read();
}

接下來我們將定義一個HttpSelfHostServer來實現SelfHost

API是不是相比SelfHost更方便?

using (var server = new MyHttpSelfHostServer("http://localhost:10000"))
{
    server.Configuration.Routes.MapHttpRoute("default", "{controller}");
    server.OpenAsync();
    Console.Read();
}

再看看我們具體的MyHttpSelfHostServer如何實現

public class MyHttpSelfHostServer : HttpServer
{
    private string _url;
    public MyHttpSelfHostServer(string url)
    {
        _url = url;
    }

    public async void OpenAsync()
    {
        var binding = new HttpBinding();
        var listener = binding.BuildChannelListener<IReplyChannel>(new Uri(_url));
        listener.Open();//開啟監聽
        var reply = listener.AcceptChannel();
        reply.Open();//開啟通信通道
        while (true)
        {
            var request = reply.ReceiveRequest();//接受到請求
            //獲取HttpRequestMessage
            var method = request.RequestMessage.GetType().GetMethod("GetHttpRequestMessage");
            var requestMessage = method.Invoke(request.RequestMessage, new object[] { true }) as HttpRequestMessage;
            var response = await base.SendAsync(requestMessage, new CancellationTokenSource().Token);
            request.Reply(CreateMessage(response));//回復消息
        }
    }

    Message CreateMessage(HttpResponseMessage response)
    {
        var type = Type.GetType("System.Web.Http.SelfHost.Channels.HttpMessage,System.Web.Http.SelfHost");
        return (Message)Activator.CreateInstance(type, response);
    }
}

最后我們來請求一下地址:http://localhost:10000/Demo

備注:

  • 文章中的代碼並非完整,一般是經過自己精簡后的.

  • 本篇內容使用MarkDown語法編輯

首發地址:http://neverc.cnblogs.com/p/5949974.html


免責聲明!

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



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