Unity IoC and MVC 3 Beta - Passing IRepository to

2019-04-14 19:45发布

问题:

Did something change in MVC 3? I have tried all the examples on the Internet for setting up Unity as my IoC Container, but I keep getting an error saying that Unity cannot resolve my UserController. Here is my constructor on my UserController:

public UserController(IUserService userService)
{
    _userService = userService;
}

I have the IUserService registered, that is not the problem. I keep getting errors, no matter what example I try. Does anyone have a good tutorial, or code, that works with Asp.Net MVC 3?

For reference, I have tried this, this, this, and this ... and tons of others.

Error:

The type UserController cannot be constructed.  You must configure the container to supply this value.

ErrorLine:

controller = MvcUnityContainer.Container.Resolve(controllerType) as IController;

Configuration:

MvcUnityContainer.Container = new UnityContainer().RegisterType<IUserService, UserService>();

ControllerBuilder.Current.SetControllerFactory(typeof(UnityControllerFactory));

回答1:

To answer your question "What has changed in MVC3": MVC3 now has native support for dependency injection. Along with that change has come a redesign of the way controller objects are activated. Check out Brad Wilson's post (and the whole series about MVC 3.0) for more information:

http://bradwilson.typepad.com/blog/2010/10/service-location-pt10-controller-activator.html

Developers who previously implemented IControllerFactory by deriving from DefaultControllerFactory just to override the GetControllerInstance method for dependency injection purposes should now implement IControllerActivator instead.

In short, the unity controller factory (as well as the Ninject controller factory) are probably going to be broken until they release a new compatible version. A quick google did find this, however I have no idea if it works.



回答2:

This worked for me for MVC3 RC. Notice IControllerFactory now has GetControllerSessionBehavior in MVC3 RC.

UnityMvcControllerFactory.cs:

using System;
using System.Web.Mvc;
using System.Web.Routing;
using Microsoft.Practices.Unity;
using System.Web.SessionState;

public class UnityMvcControllerFactory : IControllerFactory
{
  private IUnityContainer _container;
  private IControllerFactory _innerFactory;

  public UnityMvcControllerFactory(IUnityContainer container)
    : this(container, new DefaultControllerFactory())
  {
  }

  protected UnityMvcControllerFactory(IUnityContainer container,
                                   IControllerFactory innerFactory)
  {
    _container = container;
    _innerFactory = innerFactory;
  }

  public IController CreateController(RequestContext requestContext, string controllerName)
  {
    try
    {
      return _container.Resolve<IController>(controllerName.ToLowerInvariant());
    }
    catch (Exception)
    {
      return _innerFactory.CreateController(requestContext, controllerName);
    }
  }

  public void ReleaseController(IController controller)
  {
    _container.Teardown(controller);
  }

  public SessionStateBehavior GetControllerSessionBehavior(RequestContext requestContext, string controllerName)
  {
    return SessionStateBehavior.Default;
  }
}

Global.asax.cs:

  public class MvcApplication : System.Web.HttpApplication
  {
    public static void RegisterGlobalFilters(GlobalFilterCollection filters)
    {
      filters.Add(new HandleErrorAttribute());
    }

    public static void RegisterRoutes(RouteCollection routes)
    {
      routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

      routes.MapRoute(
          "Default", // Route name
          "{controller}/{action}/{id}", // URL with parameters
          new { controller = "Home", action = "Index", id = UrlParameter.Optional } // Parameter defaults
      );
    }

    protected void Application_Start()
    {
      // Register Types and Set Controller Factory 
      ConfigureUnityContainer();

      AreaRegistration.RegisterAllAreas();

      RegisterGlobalFilters(GlobalFilters.Filters);
      RegisterRoutes(RouteTable.Routes);
    }

    private static void ConfigureUnityContainer()
    {
      IUnityContainer container = new UnityContainer();

      // Set Controller Factory as UnityMvcControllerFactory
      ControllerBuilder.Current.SetControllerFactory(
          new UnityMvcControllerFactory(container)
      );
    }
  }