I have some controllers that require a web service connection (an instance of MS Dynamics CRM CrmService) and I would like the controllers to receive this through their constructors. The CRM service has to be set up with a token that is based on who the currently logged in user is (when the user logs in the application authenticates against the CRM and can store the returned token in Session).

I'm not sure how best to supply this instance using Dependency Injection and Ninject. It seems a bit rubbish for the Ninject ToMethod() Func<> to access FormsAuth/Session for the current request (to obtain the token if authenticated) to create the appropriate instance. I'm also not sure what should happen if the user is not authenticated - I don't need these users be able to access the controller but the controller will be instantiated before any filters like [Authorize] will run so the dependency will always have to be met. From what I have read returning null is not ideal and I would have to change the Ninject configuration to do this anyway.

I was thinking that maybe the controller could get an instance of ICrmServiceFactory or something but that doesn't help me if the controllers end up having other dependencies which also rely on CrmService directly (and don't want to be passed a factory).

Any advice on how to solve this would be appreciated.

有帮助吗?

解决方案 3

I have ended up implementing this as follows:

private static void RegisterServices(IKernel kernel)
{
  kernel.Bind<CrmService>()
          .ToMethod(context =>
          {
            //return unauthenticated instance if user not logged in.
            if (!HttpContext.Current.User.Identity.IsAuthenticated) return new CrmService();

            return GetConnection(HttpContext.Current);

          })
          .InRequestScope();
}

private static CrmService GetConnection(HttpContext ctx)
{
   //get stuff out of session and return service
}

其他提示

I usually set up a binding for IPrincipal:

kernel.Bind<IPrincipal>().ToMethod(c => HttpContext.Current.User);

Never really had a problem with this approach.

If I understand your question correctly then your controller has a dependency to CrmService and the CrmService requires some token stored in the session.

In that case you could inject a CrmTokenProvider to CrmService and add a property to that class which gets the value from the session whenever it is requested by the CrmService.

public class CrmService
{
    public CrmService(CrmTokenProvider tokenProvider)
    {
        this.tokenProvider = tokenProvider;
    }

    public void DoSomeWork() 
    {
        ...
        this.tokenProvider.Token;
        ...
    }
}
许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top