markg
markg

Reputation: 349

MEF - ApiController - IHttpController not resolved

I am new to MEF and played around with MVC and it's working alright. However, when I tried with Web API, external api controllers weren't resolved. Here's my code for the DependencyResolver:

public class MefDependencyResolver : System.Web.Http.Dependencies.IDependencyResolver,  IDependencyResolver
        {
            private readonly CompositionContainer _container;

            public MefDependencyResolver(CompositionContainer container)
            {
                this._container = container;
            }

            public object GetService(Type serviceType)
            {
                string name = AttributedModelServices.GetContractName(serviceType);
                var service = this._container.GetExportedValueOrDefault<object>(name);
                return service;
            }

            public IEnumerable<object> GetServices(Type serviceType)
            {
                string name = AttributedModelServices.GetContractName(serviceType);

                try
                {
                    var service = this._container.GetExportedValues<object>(name);

                    return service;
                }
                catch
                {
                    return new object[] { };
                }
            }

            public System.Web.Http.Dependencies.IDependencyScope BeginScope()
            {
                return this;
            }

            public void Dispose()
            {}
        }

and here's how it was used:

var _resolver = new MefDependencyResolver(_container);
System.Web.Http.GlobalConfiguration.Configuration.DependencyResolver = _resolver;

and here's the external api controller:

[Export]
[PartCreationPolicy(CreationPolicy.NonShared)]
public class ValuesController : ApiController
{
        // GET api/values
        public IEnumerable<string> Get()
        {
            return new string[] { "value1", "value2" };
        }
}

but when I visit my site:

http://localhost:65232/api/values

I got this error:

<Error>
<Message>
No HTTP resource was found that matches the request URI 'http://localhost:65232/api/values'.
</Message>
<MessageDetail>
No type was found that matches the controller named 'values'.
</MessageDetail>
</Error>

the same container works with my MVC Controller but can't seem to make it work with API controllers.

Am I missing anything?

Upvotes: 0

Views: 1052

Answers (1)

Dejan
Dejan

Reputation: 10323

There are two interfaces involved here, both with the same name IDependencyResolver hence the confusion. One is for MVC, and one is for Web API.

I solved it like this. I have:

public class WebApiDependencyResolver : System.Web.Http.Dependencies.IDependencyResolver
{
    ...
}

and

public class MvcDependencyResolver : WebApiDependencyResolver, System.Web.Mvc.IDependencyResolver
{
    public MvcDependencyResolver(CompositionContainer container)
        : base(container)
    {
    }
}

The MvcDependencyResolver inherits from the WebApiDependencyResolver to avoid code duplication.

Then you need to register the resolver with MVC and Web API. So somewhere in your startup code you should have something like this:

        var resolver = new MvcDependencyResolver(Container);
        System.Web.Mvc.DependencyResolver.SetResolver(resolver); // install MEF dependency resolver for MVC
        System.Web.Http.GlobalConfiguration.Configuration.DependencyResolver = resolver; // install MEF dependency resolver for Web API

Having said all this, I personally wouldn't go with MEF for controller resolution as it introduces a memory leak because MEF keeps references to IDisposable types and ApiController is IDisposable.

Upvotes: 2

Related Questions