Objective
The previous sections briefly introduce the routes and pipelines in the Web API and do not describe anything in detail, however, the framework of the ASP.net Web API is very different from the host environment and the way in which the implementation mechanism and route are handled in different hosting environments. So I will make a simple explanation for the different hosting environment.
asp.net Web API routing, piping
asp.net Web API Opening Introduction Example
Introduction to asp.net Web API routing objects
asp.net Web API piping model
asp.net Web API selfhost the pipeline, routing in the hosting environment
asp.net Web API webhost the pipeline, routing in the hosting environment
asp.net Web API selfhost hosting environment Pipeline
First we'll look at a schematic, presumably describing the shape of the pipe in the selfhost hosting environment.
Figure 1
Because in the webhost hosting environment asp.net the Web API's pipeline request receives and the response return finally all is arranged by the ASP.net (in the next article to explain), but in the Selfhost host environment is painstakingly forced, is not so simple.
We explain this in Figure 1, first after the project in the Selfhost hosting environment is started (of course the project will use the Web API framework), There will be a Httpbinding object (System.Web.Http.SelfHost.Channels), what is this httpbinding type of object? The Httpbinding object corresponds to some BindingElement objects, and these bindingelement generate corresponding pipe layer listeners, as shown in Figure 1, and now we look at the following sample code, Look at the BindingElement objects that httpbinding exactly correspond to.
Example 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 example code 1-1, we can clearly see that in the constructor of the Httpbinding object, several bindingelement are instantiated separately, and we Only HttpTransportBindingElement and Httpmessageencodingbindingelement are explained in the same way as shown in Figure 1.
The primary responsibility of the HttpTransportBindingElement object is to generate a corresponding pipe listener, which corresponds to the ichannellistenergeneric type, and after generating a good corresponding pipe listener, The listener then starts listening to the corresponding pipe layer, which corresponds to the HttpTransportBindingElement object and the listener, which is the Transprotchannel pipeline layer, which is responsible for requesting the receipt of the message and sending the response message.
Httpmessageencodingbindingelement Type objects do the same thing as the httptransportbindingelement type, which is to generate the corresponding pipe listener, which corresponds to the The Httpmessageencodingchannellistener type, after the listener is generated, will also listen to the corresponding Encodingchannel pipeline layer, The main function of the Encodingchannel pipeline layer is to encapsulate the request information as a httpmessage type of message object, followed by the Httpmessage message object into the pipeline system of the ASP.net Web API framework.
It says that when the request does not reach the ASP.net Web API framework of the pipeline system in the external processing and operations, we will explain the internal, in the previous "ASP.net Web API Piping Model" The sample code in space demonstrates the registration of pipelines under the selfhost environment, and here we look at some types of objects in the piping system of the Web API framework itself in the selfhost environment.
Httpselfhostserver Message handlers (Implementation class - pipe head) 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();
}
You can see that the Httpselfhostserver type inherits from Httpserver, and we mentioned in the previous article that Httpserver is the base class for message handlers that inherit from Delegatinghandler abstract types. The difference between Delegatinghandler and Httpmessagehandler is that there is a reference to the next handler, of course, it is reasonable to be the first message handler in a piping system to have such an identifier that points to the next handler reference. Let's look at the parameter types of the constructor for the Httpselfhostserver type.
The
Httpselfhostconfiguration type is inherited from the httpconfiguration type, and as we said in the previous article, most of the information in the pipeline can be configured in Httpconfiguration, which you can take a look at yourself. There is a second constructor parameter in the overloaded constructor, a parameter of type Httpmessagehandler, and if you do not use the overloaded constructor when using Httpselfhostserver by default, then the Before instantiating the Httpselfhostserver, the constructor of its base class Httpserver starts executing, so look at the httpserver type of constructor, we can see the default setting of the Httpmessagehandler type parameter in the end.
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 you can see clearly that the type of httproutingdispatcher type as the last handler for the pipe, for this type and detailed information, is described in the following routing section.
asp.net Web API selfhost hosting environment Routing
For other knowledge of routing here is a brief mention of some of the details of the selfhost and piping in the middle of the road.
Figure 2
Here to explain in detail is the httproutingdispatcher type of SendAsync () method, look at the implementation of the source code in this clearer.
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, you can see the constructor of the instance base class immediately after the defined constructor, and the second The Httpmessagehandler type argument is the object of the Httpcontrollerdispatcher instance, which we'll remember first.
Let's go back to the Httproutingdispatcher type of SendAsync () method, and first we'll see a route data object from the Properties collection of the Httprequestmessage object instance.
In the Selfhost environment this is not to be obtained, why? Because there is no mention of processing routing and generating routing data in the pipeline processing in the above and previous space. So this time will be based on the attributes of the httproutecollection type in Httpconfiguration routes,routes attribute based on SendAsync () The parameter type of the method gets the routing data Object ihttproutedatafor the httprequestmessage request information.
After the match is successfully fetched to the routed data object (Ihttproutedata), it is added to the Properties collection of the Httprequestmessage object instance (request).
Prior to the understanding of the route, the final implementation of the handler is initially defined in the routing object, and in fact, we register the route does not, if this happens now, you can see routedata.route.hander==null this is set up, So the SendAsync () method of the instance of the Httpcontrollerdispatcher type in the constructor, as we said earlier, is actually httpcontrollerdispatcher Type is encapsulated by the Httpmessageinvoker type).