Problems encountered by MVC 2.0 + Entity Framework when using dependency Injection

Source: Internet
Author: User
Preface:

Recently, when I was reading the MVC 3.0 Beta release note, I found the idependencyresolver interface. I also saw two articles about using dependency injection in MVC (Portal 1, portal 2 ).

Therefore, I learned about dependency injection and reconstructed a previous website (using unity ).

In fact, there is no need, because it cannot fully reflect the advantages of dependency injection, but it is a little performance loss, so let's get started with it ~

 

In this process (the website is developed by mvc2.0), it is found that mvc2.0 and Entity Framework have some problems in the dependency injection process. So here, let's take a closer look.

 

Implement dependency injection in MVC 2.0:

Mvc2.0 has little support for dependency injection. After understanding the principle of dependency injection, we all know that the key here is to find a starting point. After analyzing the relationship between objects and the lifecycle, we find that, it is a wise choice to switch from the Controller.

How can we intercept the original controller creation process and replace it with our own creation process?

 

After reading the source code and Portal 1 of rorowoblog, I found that the Controller in MVC was created by the defaultcontrollerfactory class. Obviously, this is a controller factory class, it is used to create a controller object.

Decompilation:

 

We can find that there are a lot of internal virtual methods, and we can see from the name that this is the key to this factory, just inherit and rewrite it.

public class MyConrtollerFctory : DefaultControllerFactory{    protected override IController GetControllerInstance(RequestContext requestContext, Type controllerType)    {        if (requestContext == null || controllerType == null)        {            throw new ArgumentNullException("controller");        }        return MvcApplication.Container.Resolve(controllerType) as IController;    }}

 

Next, use a static method to replace the default controller factory in global. asax.

Protected void application_start () {arearegistration. registerallareas (); registerglobalfilters (globalfilters. filters); registerroutes (routetable. routes); // Replace the default controller factory controllerbuilder. current. setcontrollerfactory (New myconrtollerfctory ());}

 

How to throw exceptions normally:

Everything seems so smooth. Run it. it's successful!

However, the problem suddenly exists!

 

When I input a non-existent controller, an error is returned! Instead of returning Error 404!

The highlighted section shows the problem. It seems that the exception is not thrown correctly when the method is replaced.

 

Continue decompilation. Check this method:

protected internal virtual IController GetControllerInstance(RequestContext requestContext, Type controllerType){    if (controllerType == null)    {        throw new HttpException(0x194, string.Format(CultureInfo.CurrentCulture, MvcResources.DefaultControllerFactory_NoControllerFound, new object[] { requestContext.HttpContext.Request.Path }));    }    if (!typeof(IController).IsAssignableFrom(controllerType))    {        throw new ArgumentException(string.Format(CultureInfo.CurrentCulture, MvcResources.DefaultControllerFactory_TypeDoesNotSubclassControllerBase, new object[] { controllerType }), "controllerType");    }    return this._activatorResolver.Current.Create(requestContext, controllerType);}

 

This seems to be the problem. Because we throw a custom exception, the outer layer is not caught, so it does not think this is a 404 error.

 

Now that you know the reason, isn't it easy to solve it? Just copy the code ~

But the problem comes again. Several objects in this Code are internal (the assembly is visible)

Our code is not in the same Assembly as it, and of course it cannot be accessed... What should I do? Continue decompilation? Copy the code?

 

I am afraid this solution is unfriendly. In fact, there is a small trick. Although it does not look very good, it does work ~

Public class authorization: defaultcontrollerfactory {protected override icontroller getcontrollerinstance (requestcontext, type controllertype) {If (requestcontext = NULL | controllertype = NULL) {// key base. getcontrollerinstance (requestcontext, controllertype);} return mvcapplication. container. resolve (controllertype) as icontroller ;}}

 

When the Controller factory class is overwritten, if an exception needs to be thrown, you can directly access the base class method and let the base class throw it ~ So you don't have to worry about anything ~

 

Problems encountered in Entity Framework:

Not only mvc2.0, but EF does not have high support for dependency injection.

It is mainly reflected in that objectcontext is automatically generated by the tool and can be modified, but it is not recommended to be modified.

Objectcontext has multiple constructors. You can either write the configuration file or add the injectionconstructor attribute to the constructor.

The former is too troublesome. I am only a small project and there is no need to write the configuration file. The latter needs to modify the core code, which does not comply with the above principles.

 

In fact, there is also a very convenient way to solve this problem, as long as you register the objectcontext constructor in the unitycontainer.

/// <Summary> // unity container // </Summary> static private unitycontainer container; static public unitycontainer container {get {If (Container = NULL) {Container = new unitycontainer (); // register the constructor container. registerinstance <modelcontainer> (New modelcontainer () ;}return container ;}}

 

Postscript:

According to VC 3.0 Beta, dependency injection is well supported (portal 2 ~ I hope I can confirm the usage in the official version. Don't change it all the time ~

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.