When the routing system finds the routedata that matches the current request, and the routehandler in the routing information is mvcroutehandler, The mvchandler returned by mvcroutehandler is responsible for processing the request. By default, mvchandler finds the corresponding controller and activity method based on the information in the request context (requestcontext), calls the activity method, returns the response content, and returns it to the client.
The mvchandler class obtains the currently specified icontrollerfactory object by using the getcontrollerfactory method of the single-instance class controllerbuilder, and generates a specific icontroller controller through this object. For mvchandler, it only cares about the icontroller object, that is, it is only responsible for calling the icontroller execute method to generate the response content. The action method is implemented in the default controller class of the MVC framework. It uses the action parameter in the routing information to determine a corresponding method in the Controller class to generate the response content.
By default, the MVC framework uses the defaultcontrollerfactory controller factory. It uses the controller parameter in the routing information to determine the specific controller class and generates a controller instance through the reflection mechanism.
The classes involved from the mvcroutehandler receiving the request to the final decision to use the controller, as shown in:
Through the setcontrollerfactory method of controllerbuilder, we can specify a custom controller factory. A custom factory can directly implement the icontrollerfactory interface, or inherit from the defaultcontrollerfactory class. If you directly implement icontrollerfactory, then we must implement a mechanism to match the routing information with the Controller. Therefore, to use the default routing parsing function in MVC, we generally inherit from defaultcontrollerfactory, and then overwrite the getcontrollerinstance and getcontrollertype methods according to the actual situation. getcontrollerinstance is used to return an icontroller controller, getcontrollertype is used to obtain the appropriate controller type based on Route information. Obviously, in the default controller factory, the createcontroller method first calls getcontrollertype to locate the type, and then calls the getcontrollerinstance method to create a controller instance.
Defaultcontrollerfactory uses the activator. createinstance method to create a controller object. Therefore, the default controller of MVC must have a no-argument constructor. Below we use the dependency injection (DI) technology to make our custom controller factory have instantiated parameter controllers.
Imagine the following scenario: There is a product class in the domain model. We have defined an iproductsrepository storage management class for it. First, we implement a sqlproductsrepository class to obtain product information from the sqlserver database. Then, to facilitate testing, we also implement a mockproductsrepository class to return a simple product list. We create a productscontroller controller. To determine which storage implementation is used, we need to input an iproductsrepository object when generating the Controller instance:
We choose ninject open source library to achieve di (: http://ninject.org/download ):
1. Download ninject and decompress it.
2. Create an empty MVC Project
3. Add reference ninject. dll and system. Data. LINQ
4. AttachSource codeTest Database in
5. implement various interfaces and classes based on the above class diagram
6. Create a productscontroller and add a constructor with the iproductsrepository parameter.
Show row number CopyCode ? Productscontroller
-
UsingSystem;
-
UsingSystem. Collections. Generic;
-
UsingSystem. LINQ;
-
UsingSystem. Web;
UsingSystem. Web. MVC;
-
-
NamespaceCnblogs. controllerfactory. Controllers
-
{
-
Public classProductscontroller:Controller
-
{
-
PrivateIproductsrepository_ Repository;
-
-
PublicProductscontroller (IproductsrepositoryRepository)
-
{
_ Repository = repository;
-
}
-
-
PublicActionresultIndex ()
-
{
-
ReturnView (_ repository. getproductslist ());
-
}
-
-
}
-
}
-
-
7. Create the View index. aspx corresponding to the index action method.
8. Create a controller Factory: ninjectcontrollerfactory
Show row number Copy code ? Ninjectcontrollerfactory
-
UsingSystem;
-
UsingSystem. Collections. Generic;
UsingSystem. LINQ;
-
UsingSystem. Web;
-
UsingSystem. Web. MVC;
-
UsingNinject. modules;
-
UsingNinject;
-
UsingCnblogs. controllerfactory. models;
-
UsingSystem. configuration;
-
-
NamespaceCnblogs. controllerfactory. Infrastructure
-
{
Public classNinjectcontrollerfactory:Defaultcontrollerfactory
-
{
-
PrivateIkernel_ KERNEL =NewStandardkernel(NewMymodule());
-
-
Protected overrideIcontrollerGetcontrollerinstance (system. Web. routing.RequestcontextRequestcontext,TypeControllertype)
{
-
If(Controllertype =Null)
-
Return null;
-
Return(Icontroller) _ KERNEL. Get (controllertype );
-
}
-
-
-
Private classMymodule:Ninjectmodule
-
{
-
Public override voidLoad ()
{
-
// Bind <iproductsrepository> ()
-
//. To <mockproductsrepository> ();
-
-
Bind <Iproductsrepository> ()
-
. To <Sqlproductsrepository> ()
-
. Withconstructorargument ("Connectstring",Configurationmanager. Connectionstrings ["Testdb"]. Connectionstring );
-
}
}
-
}
-
}
-
9. Set a custom factory in global. asax. CS
Protected voidApplication_start ()
{
Arearegistration. Registerallareas ();
Registerroutes (Routetable. Routes );
Controllerbuilder. Current. setcontrollerfactory (NewNinjectcontrollerfactory());
}
OK. to switch between the virtual product list and the real sqlserver product list, you only need to modifyMymoduleTo bind specific parameters in the Controller constructor to a specific implementation.
Note: This article involves the related knowledge of LINQ and Di. For more information, see. To run this example, first attach the MDF file in the source code to sqlserver express and modify the testdb connection string definition in APP. config.
Source code download