2

I am injecting a dependency into a custom API controller I've created that is inheriting from ServicesApiController. I have found that I need to use our service locator class to do this as otherwise, I get an error saying 'Make sure that the controller has a parameterless public constructor'. Here is some example code:

   public class CustomApiController : ServicesApiController
        {
            private readonly ISomeDependancy _someDependancy;

            public CustomApiController() : this(LocatorContainerManager.Current.Resolve<ISomeDependancy>())
            {

            }

            public CustomApiController(ISomeDependancy someDependancy)
            {
                _someDependancy = someDependancy;
            }

            [HttpGet]
            public IHttpActionResult Get()
            {
               //return some items here
            }
    }

Obviously I'd rather not use ServiceLocator. The custom routes are patched in replacing Sitecore's (Sitecore.Mvc.Pipelines.Loader.InitializeRoutes, Sitecore.Mvc)

We are using SimpleInjector and as I understand it the problem might be that the configuration is being overwritten by Sitecore as the custom routes are patched in before the ServicesWebApiInitializer.

Therefore I may need to move where they are registered to after the WebApiInitializer as explained here by Corey:

WebApi failing to resolve dependencies

Does this sound right or am I miss-understanding something?

Further info: Sitecore 8.2 Update 6. We are using xDB.

4
  • Did you ever resolve this?
    – Mark Cassidy
    Commented Jan 9, 2020 at 12:50
  • I don't think so unfortunately Mark, I think I just ended up using service locator in the end :-( Commented Jan 10, 2020 at 9:31
  • The problem exists on a 9.2 as well. And everything is patched in via <services> configuration element and so on.
    – Mark Cassidy
    Commented Jan 10, 2020 at 9:58
  • Right ok, thats interesting. If you find a fix I'd be interested to know what it is. Commented Jan 10, 2020 at 9:59

1 Answer 1

1

We had the exact same issue, using SimpleInjector. We resolved this by implementing a 'chained' dependency resolver. Not the most beautiful solution, and actually more of a work around, as basically the Sitecore/Microsoft dependency injection would fail and throw an exception first, and then you would be falling back to your own SimpleInjector implementation. But it works.

Hereby the code to get this to work:

In our SimpleInjector initializer we do:

var chainedMvcResolver = new ChainedMvcResolver(new SimpleInjectorDependencyResolver(container), System.Web.Mvc.DependencyResolver.Current);
System.Web.Mvc.DependencyResolver.SetResolver(chainedMvcResolver);

//WebAPI
var chainedWebApiResolver = new ChainedWebApiResolver(new SimpleInjectorWebApiDependencyResolver(container),
GlobalConfiguration.Configuration.DependencyResolver);

GlobalConfiguration.Configuration.DependencyResolver = chainedWebApiResolver;

Then the following implementation for these chained resolvers:

public class ChainedMvcResolver : System.Web.Mvc.IDependencyResolver
{
    private readonly System.Web.Mvc.IDependencyResolver fallbackResolver;
    private readonly System.Web.Mvc.IDependencyResolver newResolver;

    public ChainedMvcResolver(System.Web.Mvc.IDependencyResolver newResolver, System.Web.Mvc.IDependencyResolver fallbackResolver)
    {
        this.newResolver = newResolver;
        this.fallbackResolver = fallbackResolver;
    }

    public object GetService(Type serviceType)
    {
        object result = null;

        try
        {
            result = newResolver.GetService(serviceType);
        }
        catch
        {
            // Some containers throw exceptions when they are not able to resolve a dependency
        }

        return result ?? fallbackResolver.GetService(serviceType);
    }

    public IEnumerable<object> GetServices(Type serviceType)
    {
        List<object> result = null;

        try
        {
            result = newResolver.GetServices(serviceType).ToList();
        }
        catch
        {
            // Some containers throw exceptions when they are not able to resolve a dependency
        }

        return result?.Any() == true ? result : fallbackResolver.GetServices(serviceType);
    }
}


public class ChainedWebApiResolver : ChainedWebApiDependencyScope, System.Web.Http.Dependencies.IDependencyResolver
{
    public ChainedWebApiResolver(System.Web.Http.Dependencies.IDependencyResolver newResolver, System.Web.Http.Dependencies.IDependencyResolver currentResolver)
        : base(newResolver, currentResolver)
    {
        this.newResolver = newResolver;
        this.fallbackResolver = currentResolver;
    }

    public IDependencyScope BeginScope()
    {
        return new ChainedWebApiDependencyScope(newResolver, fallbackResolver);
    }
}

In this way we at least did not have to use the ServiceLocator.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.