ASP. NET Web API Selfhost
Pipelines and routes in the ASP. NET Web API Selfhost host environmentPreface
The previous sections briefly introduced the routes and pipelines in Web APIs and did not describe in detail. However, ASP. NET Web API framework, because of the different host environments, the implementation mechanism of pipelines in different host environments is very different from the routing processing method, therefore, I will give a brief explanation of the corresponding host environments.
ASP. NET Web API routing and Pipelines
- ASP. NET Web APIExample
- ASP. NET Web APIRoute object Introduction
- ASP. NET Web APIMPs Queue Model
- ASP. NET Web API selfhostPipelines and routes in the host environment
- ASP. NET Web API webhostPipelines and routes in the host environment
ASP. NET Web API SelfHost host environment Pipeline
First, let's take a look at the pipeline form in the SelfHost host environment.
Figure 1
Because ASP. NET Web API, the pipeline request receiving and response responses are finally returned by ASP. NET (explained in the next article), but in the SelfHost host environment, it is not that simple.
As illustrated in figure 1, after the project in the SelfHost host environment is started (the project must use the Web API framework), an HttpBinding object (System. web. http. selfHost. channels), so what is the HttpBinding object? The Httpbinding object corresponds to some BindingElement objects, and these bindingelements generate corresponding pipeline layer listeners, as shown in 1. Now let's take a look at the following sample code, check which BindingElement objects correspond to HttpBinding.
Sample Code 1-1
public class HttpBinding : Binding, IBindingRuntimePreferences { public HttpBinding() { this.Initialize(); } private void Initialize() { this._security = new HttpBindingSecurity(); this._httpTransportBindingElement = new HttpTransportBindingElement(); this._httpTransportBindingElement.ManualAddressing = true; this._httpsTransportBindingElement = new HttpsTransportBindingElement(); this._httpsTransportBindingElement.ManualAddressing = true; this._httpMessageEncodingBindingElement = new HttpMessageEncodingBindingElement(); } }
In the example code 1-1, we can clearly see that several bindingelements are instantiated and assigned values in the HttpBinding object constructor, we will only explain HttpTransportBindingElement and HttpMessageEncodingBindingElement, as shown in figure 1.
The main responsibility of the HttpTransportBindingElement object is to generate the corresponding pipeline listener, which corresponds to the IChannelListener <TChannel> generic type. After the corresponding pipeline listener is generated, the listener starts to listen to the corresponding pipeline layer, which corresponds to the HttpTransportBindingElement object and the TransprotChannel pipeline layer of the listener. It is responsible for receiving and sending response messages.
The operations performed on HttpMessageEncodingBindingElement are the same as those on HttpTransportBindingElement. Both of them must generate the corresponding pipeline listener. Here the corresponding types are HttpMessageEncodingChannelListener, after the listener is generated, it will listen to the corresponding EncodingChannel channel layer. The main function of the EncodingChannel channel layer is to encapsulate the request information as a message object of the HttpMessage type, then, the HttpMessage message object enters ASP.. NET Web API framework.
The above is when the request does not reach ASP. some external processing and operations are performed in the pipeline system of the NET Web API framework. Next we will describe the internal, in the previous article ASP. NET Web API pipeline model contains sample code to demonstrate the registration of pipelines in the SelfHost environment, here we will take a look at some types of objects in the Web API Framework's own pipeline system in the SelfHost environment.
HttpSelfHostServerMessage Processing Program (Implementation class-Pipeline header) System. Web. Http. SelfHost
public sealed class HttpSelfHostServer : HttpServer { public HttpSelfHostServer(HttpSelfHostConfiguration configuration); public HttpSelfHostServer(HttpSelfHostConfiguration configuration, HttpMessageHandler dispatcher); public Task CloseAsync(); protected override void Dispose(bool disposing); public Task OpenAsync(); }
We can see that the HttpSelfHostServer type inherits from HttpServer. in the previous article, we mentioned that HttpServer is the base class of the Message Processing Program inherited from the DelegatingHandler abstract type, the difference between DelegatingHandler and HttpMessageHandler is that there is an additional reference pointing to the next processing program, of course, as the first message handler in an MPS system, it is reasonable to have such an identifier referenced by the next handler. Let's look at the parameter types of the HttpSelfHostServer Type constructor.
The HttpSelfHostConfiguration type inherits from the HttpConfiguration type. We also mentioned in the previous article that most information in the pipeline can be configured in HttpConfiguration. You can take a look at it yourself. There is a second constructor parameter in the overload constructor. The HttpMessageHandler type parameter does not use this overload constructor when HttpSelfHostServer is used by default, then, before the HttpSelfHostServer is instantiated, the constructor of the base class HttpServer starts to execute, so when we look at the HTTP Server Type constructor, we can see what the default HttpMessageHandler type parameters look like here.
public HttpServer() : this(new HttpConfiguration()) { } public HttpServer(HttpMessageHandler dispatcher) : this(new HttpConfiguration(), dispatcher) { } public HttpServer(HttpConfiguration configuration) : this(configuration, new HttpRoutingDispatcher(configuration)) { } public HttpServer(HttpConfiguration configuration, HttpMessageHandler dispatcher) { this._initializationLock = new object(); if (configuration == null) { throw System.Web.Http.Error.ArgumentNull("configuration"); } if (dispatcher == null) { throw System.Web.Http.Error.ArgumentNull("dispatcher"); } this._dispatcher = dispatcher; this._configuration = configuration; }
Here we can clearly see that the HttpRoutingDispatcher type is used as the type of the last handler of the pipeline. For this type and detailed information, it will be described in the following routing section.
ASP. NET Web API SelfHost host environment route
I will not talk about other routing knowledge here, but I will briefly introduce some details about routing and pipelines in SelfHost.
Figure 2
The SendAsync () method in the HttpRoutingDispatcher type is described in detail here. It is clearer to see the implementation in the source code.
public class HttpRoutingDispatcher : HttpMessageHandler { // Fields private readonly HttpConfiguration _configuration; private readonly HttpMessageInvoker _defaultInvoker; // Methods public HttpRoutingDispatcher(HttpConfiguration configuration) : this(configuration, new HttpControllerDispatcher(configuration)) { } protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) { IHttpRouteData routeData; if (!request.Properties.TryGetValue<IHttpRouteData>(HttpPropertyKeys.HttpRouteDataKey, out routeData)) { routeData = this._configuration.Routes.GetRouteData(request); if (routeData == null) { return TaskHelpers.FromResult<HttpResponseMessage>(request.CreateErrorResponse(HttpStatusCode.NotFound, Error.Format(SRResources.ResourceNotFound, new object[] { request.RequestUri }), SRResources.NoRouteData)); } request.Properties.Add(HttpPropertyKeys.HttpRouteDataKey, routeData); } RemoveOptionalRoutingParameters(routeData.Values); HttpMessageInvoker invoker = (routeData.Route.Handler == null) ? this._defaultInvoker : new HttpMessageInvoker(routeData.Route.Handler, false); return invoker.SendAsync(request, cancellationToken); } }
Let's take a look at the constructor in the HttpRoutingDispatcher type. We can see the constructor next to the defined constructor In the instance base class, and the second HttpMessageHandler type parameter is the object of the HttpControllerDispatcher instance, remember this first.
Next we will return to the SendAsync () method of the HttpRoutingDispatcher type. First we will see the route data object obtained from the Properties attribute set of the HttpRequestMessage object instance.
This cannot be obtained in the SelfHost environment. Why? Because the preceding and earlier sections did not mention processing routes and Generating Route data in pipeline processing. Therefore, the Routes attribute is obtained based on the HttpRouteCollection type attribute Routes in HttpConfiguration, and the Routes attribute is obtained based on the request information of the SendAsync () method whose parameter type is HttpRequestMessage.Route Data ObjectIHttpRouteData.
After the matching succeeds, the route data object (IHttpRouteData) will be added to the Properties attribute set of the HttpRequestMessage object instance (request.
Previously, the Handler is defined in the routing object at the beginning. In actual situations, we did not register the routing, if this happens now, you can see routeData. route. hander = null this is true, so the execution is the SendAsync () of the HttpControllerDispatcher type instance in the constructor we previously mentioned () method (in practice, the HttpControllerDispatcher type is encapsulated by the HttpMessageInvoker type ).
The HttpControllerDispatcher type is related to the Web API controller. We will not talk about it in advance here, but we will definitely talk about it later.
Author: Jin Yuan
Source: http://www.cnblogs.com/jin-yuan/
The copyright of this article is shared by the author and the blog Park. You are welcome to reprint this article. However, you must keep this statement without the author's consent and go to the Article Page.