Using Dependency Injection in ASP.NET MVC3 Model Binder

為{幸葍}努か 提交于 2019-11-28 07:17:38

问题


I'm working on MVC3 website, trying to use Ninject to resolve my dependencies. I have the following scenario:

public class UserModelBinder : IModelBinder
{
    //[Inject]
    public UserDataService userData { get; set; }

    public object BindModel(
        ControllerContext controllerContext,
        ModelBindingContext bindingContext)
    {
        Guid UserID =
            (Guid)Membership.GetUser().ProviderUserKey;

        //userDataService = DependencyResolver.Current
        //    .GetService<UserDataService>();

        User user = userDataService.GetUser(UserID);

        return user;
    }
}

noticed the commented lines of code?

I do register the binder in Global.asax as

ModelBinders.Binders[typeof(User)] = new UserModelBinder();

So I can't really do injection through the construction.

UserDataService has a chain of dependencies: UserDataService -> UserRepository -> Context. So it would be good to use Ninject here.

The problem is, when I uncomment [Inject] above userData declaration, and try getting Ninject to inject object as a parameter, it does not work for some reason: I get null reference exceptions.

(could it be that UserDataService does not have an interface and I'm binding the object to itself: kernel.Bind<UserDataService>().ToSelf(); ??)

I have another commented line in the code:

userDataService = DependencyResolver.Current
    .GetService<UserDataService>();

When this is uncommented, the set up works, I get correct objects inserted, but now we depend on DependencyResolver and that is not much better than saying userDataService = new UserDataService()

Am I missing something? Is there another way to inject an object as a parameter and not introducing dependency on Ninject or DependencyResolver?


回答1:


A model binder should just do data conversion and should not depend on any services and certainly not trigger any database communication. That should be done in another part of your application. Your Action method should just take a Guid userId and you should call userDataService.GetUser(UserID); from within your controllers (or in a lower layer, for instance, inside a business command). By doing this, your problem will not exist.




回答2:


You could do this:

public class UserModelBinder : IModelBinder
{
    public Func<UserDataService> UserData { get; set; }

    public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
    {
        Guid UserID = (Guid)Membership.GetUser().ProviderUserKey;

        User u = UserData().GetUser(UserID);

        return u;
    }
}

Then when you wire it up:

ModelBinders.Binders[typeof(User)] = new UserModelBinder() 
{  
    userData = () => DependencyResolver.Current.GetService<UserDataService>();
}

The benefit is that your UserModelBinder isn't aware that a container is being used, while still being open for injection.

But I agree with Steven - using a model binder for this doesn't seem quite right. Instead you might inject an ICurrentUserContext into your controllers, where the implementation returns the current user. Then you don't even need to add a parameter to your controller actions.




回答3:


Use the DependencyResolver.Current to get your service. This is actually much better than using new, because it means you have not coupled getting that service to the type of the service. You can decide later to make UserDataService an abstraction and plug in different variants without changing your client code, which is really the whole point.

Also, DependencyResolver.Current is a settable IDependencyResolver, so you could implement that interface yourself, with a class that backs it with Ninject if you like that framework.

Another way to do dependency injection in MVC3 is to setup your own IControllerActivator, which allows you to do constructor injection instead, if you like.



来源:https://stackoverflow.com/questions/10848560/using-dependency-injection-in-asp-net-mvc3-model-binder

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!