How is the Controller created through ASP. NET Web API? We have a deep understanding of the core objects of the HttpController activation system, these objects include AssembliesResolver and parser for parsing the Assembly and valid HttpController types, HttpControllerSelector selected for the complete target HttpController according to the request, HttpControllerActivator activated for the target HttpController instance, and DependencyResolver used as the IoC container.
1. HttpController activation process for message processing pipelines that constitute the core framework of ASP. NET Web APIs, The HttpMessageHandler at the end is an HttpRoutingDispatcher object. After it completes route resolution (HttpRoutingDispatcher's route resolution only takes place in Self Host mode. For the Web Host mode, routing resolution is implemented by ASP. by default, it will pass the request to an HttpControllerDispatcher object.
HttpControllerDispatcher activates and executes the target HttpController object, and returns the HttpResponseMessage object representing the execution result to the HttpRoutingDispatcher object, the latter sends the HttpResponseMessage back to the Message Queue for corresponding processing, and finally completes the response to the request.
The UML shown in the right figure shows the entire process of activating HttpController. After the HttpControllerDispatcher takes over the request, it obtains the registered HttpControllerSelector object and calls its SelectController method to obtain the HttpControllerDescriptor object describing the target HttpController.
By default, the registered HttpControllerSelector is a DefaultHttpControllerSelector object. The latter obtains all HttpController types by means of the registered HttpControllerTypeResolver object, and creates a ing between the HttpControllerDescriptor object and the HttpController name. After its SelectController method is executed, it only needs to obtain the name of the target HttpController Based on the HttpRouteData object carried by the request, and select the corresponding HttpControllerDescriptor from the ing relationship.
HttpControllerDispatcher then calls the CreateController method of the HttpControllerDescriptor object to obtain the activated HttpController object. For this HttpControllerDescriptor object, when its CreateController method is called, it will get the registered HttpControllerActivator object, call the Create method to activate the target HttpController object and return the activated object.
The default registered DefaultHttpControllerActivator object uses the registered DependencyResolver to obtain the object representing the target HttpController instance based on the HttpController type. If the latter returns a specific HttpController object, the object will be taken directly as the return value of the method. Otherwise, DefaultHttpControllerActivator will create the target HttpController object in the form of reflection and return it.
The default registered DependencyResolver is an EmptyResolver object, and the returned HttpController object is always Null. Therefore, the activated HttpController object is always created in the form of reflection by default. Because of this, the defined HttpController type must have a default constructor.
Ii. Release of HttpController
We know that the IDispoable interface is implemented as the ApiController type of the default base class of the custom HttpController. The resource release can be completed by calling the implemented Dispose method, so when will this method be executed? In addition, we know that the requested HttpRequestMessage type has a dictionary-type property Properties. We can use it to attach any object to an HttpRequestMessage object, if these additional objects need to be released, when will these operations be executed?
In fact, HttpRequestMessage reserves a bucket for the resources to be released through the attribute dictionary represented by the Properties attribute. The corresponding Key is "MS_DisposableRequestResources", and the corresponding value is a List <IDisposable> object. You can call HttpRequestMessage to obtain this list by using the extension method GetResourcesForDisposal defined below. You can also call the extension method RegisterForDispose to put objects of one or more types that implement the IDisposable interface into this list.
The ASP. NET Web API defines the above Extension Method DisposeRequestResources for the objects attached to HttpRequestMessage. When is this method called?
The time to release these resources depends on the boarding mode. For Web Host, ASP. the HttpMessageHandler pipeline used by the NET Web API to process requests and responses is created by HttpControllerHandler, the latter creates an HttpRequestMessage object that indicates the current request based on the current HTTP context and passes it into this pipeline for processing. HttpControllerHandler is responsible for completing the following three tasks related to resource release after the entire pipeline processes the request and finally responds to the request.
- Call the extended method DisposeRequestResources of the HttpRequestMessage object to release the object attached to its own attribute dictionary.
- Call the Dispose method of the HttpRequestMessage object to release the request message.
- Call the returned HttpResponseMessage object to release the Response Message.
For Self Host, how does the ASP. NET Web API in Self Host Mode listen for and process requests? We know that the request listening, receiving, and response are completed through the channel stack created by HttpBinding. The type of messages processed by the channel stack is HttpMessage. The HttpMessage representing the request message and Response Message is encapsulation of the HttpRequestMessage and HttpResponseMessage objects respectively. In WCF, the Message itself is an object that needs to be finally released. After processing the Message, it will call its Close or Dispose method to release the resource.
When the Close or Dispose method of an HttpMessage object is called, The encapsulated HttpRequestMessage or HttpResponseMessage will be released accordingly. For request messages, the specific resource release work includes releasing the HttpRequestMessage itself and releasing the resources attached to the attribute dictionary.
We can use a simple example to demonstrate how to release the encapsulated HttpRequestMessage object along with the release of the HttpMessage object in Self Host mode. In a console application, we define the following three types to be released: Foo, Bar, and Baz. Their common base class DisposableObject implements the IDisposable interface, in the implementation of the Dispose method, a piece of text is output to determine whether the specific release operation is executed.
Then we wrote the following short program in the Main method. We created three objects of the type Foo, Bar, and Baz respectively, and registered them to the created HttpRequestMessage object by calling the extension method RegisterForDispose. We created an HttpMessage object Using Reflection for this HttpRequestMessage object, and finally called its Close method to release it accordingly.
After running this program, we will get the following output results on the console. It can be seen that resources registered to an HttpRequestMessage object by calling the extension method RegisterForDispose can be released when it is released. (S406)
For ApiController, when its ExecuteAsync method is executed, it will call the extension method RegisterForDispose to register itself to the HttpRequestMessage object representing the current request. There is no doubt that the release of the ApiController object will be completed by releasing the HttpRequestMessage.