1

I'm self-hosting a WebApi application in order to do some integration tests.

I set up my server like this:

var httpConfig = new HttpSelfHostConfiguration(BaseAddress);

new ApiServiceConfiguration(httpConfig)
    .Configure();

var server = new HttpSelfHostServer(httpConfig);
server.OpenAsync().Wait();
Server = server; //this is just a property on the containing class

ApiServiceConfiguration is a class that allows me to abstract the config of the WebApi (So I can use it within Global.asax for IIS hosted version of the api)

Here's an extract:

public class ApiServiceConfiguration 
   {
       private readonly HttpConfiguration _httpConfiguration;

       public ApiServiceConfiguration(HttpConfiguration httpConfiguration)
       {
           _httpConfiguration = httpConfiguration;
       }

       public void Configure()
       {
           //setup routes
           RouteConfig.RegisterRoutes(_httpConfiguration.Routes);

           //setup autofac
           AutofacConfig.Setup(_httpConfiguration);

My AutofacConfig.Setup static method is just:

public static void Setup(HttpConfiguration config)
{
    var builder = new ContainerBuilder();

    // Register the Web API controllers.
    builder.RegisterApiControllers(Assembly.GetAssembly(typeof(MyController)));

    // Register dependencies.

    // Build the container.
    var container = builder.Build();

    // Configure Web API with the dependency resolver.
    //notice config is passed in as a param in containing method
    config.DependencyResolver = new AutofacWebApiDependencyResolver(container);
}

However, when I call my api from my unit test:

using (var client = new HttpClient(Server))
{
    var result = client.PostAsync(BaseAddress + "api/content/whatever"

    var message = result.Content.ReadAsStringAsync().Result;
}

The value of message is:

An error has occurred.","ExceptionMessage":"An error occurred when trying to create a controller of type 'ContentController'. Make sure that the controller has a parameterless public constructor.","ExceptionType":"System.InvalidOperationException","StackTrace":" at System.Web.Http.Dispatcher.DefaultHttpControllerActivator.Create(HttpRequestMessage request, HttpControllerDescriptor controllerDescriptor, Type controllerType) at System.Web.Http.Controllers.HttpControllerDescriptor.CreateController(HttpRequestMessage request) at System.Web.Http.Dispatcher.HttpControllerDispatcher.SendAsyncCore(HttpRequestMessage request, CancellationToken cancellationToken) at System.Web.Http.Dispatcher.HttpControllerDispatcher.d__0.MoveNext()","InnerException":{"Message":"An error has occurred.","ExceptionMessage":"Type 'My.Namespace.ContentController' does not have a default constructor","ExceptionType":"System.ArgumentException","StackTrace":" at System.Linq.Expressions.Expression.New(Type type) at System.Web.Http.Inteal.TypeActivator.Create[TBase](Type instanceType) at System.Web.Http.Dispatcher.DefaultHttpControllerActivator.GetInstanceOrActivator(HttpRequestMessage request, Type controllerType, Func`1& activator) at System.Web.Http.Dispatcher.DefaultHttpControllerActivator.Create(HttpRequestMessage request, HttpControllerDescriptor controllerDescriptor, Type controllerType)

Which indicates to me that the Autofac controller registration has not worked.

If I stick a breakpoint on the following line in my set up:

var server = new HttpSelfHostServer(httpConfig);

And use the immediate window to check httpConfig.DependencyResolver it is indeed related to Autofac

3
  • Can you post the MyController class? Commented Nov 6, 2013 at 14:05
  • I could... but it's just a regular controller with a dependency, and it works in a "live" setting (ie hosted in IIS / cassini) Commented Nov 6, 2013 at 14:07
  • Are you using MVC4 with WebApi1 or MVC5 with WebApi2? Because I cannot repro your issue using your code in a newly created MVC4/WebApi1 application with using a console application as a selfhost... In your clientcode try to log out that the Server.Configuration.DependencyResolver is still the autofac dependency resolver. Otherwise try to repro this in a new project and upload it to somewhere. Commented Nov 6, 2013 at 16:13

2 Answers 2

1

You need to move the ContainerBuilder and the DependencyResolver out of the static class. Your implementation is using a late binding and the autofac dependency resolver is not replacing the default resolver.

You can see this in the error message: "Make sure that the controller has a parameterless public constructor."

The default resolver ist not able to handle Controllers without a parameterless constructor, which is required for constructor injection.

Sign up to request clarification or add additional context in comments.

Comments

0

I had the same problem. In my case, the issue was with using Assembly.GetCallingAssembly(). I wanted to get the calling assembly and pass it to Autofac to register the controllers. But in release mode it didn't work.

After reading the following article:

http://www.ticklishtechs.net/2010/03/04/be-careful-when-using-getcallingassembly-and-always-use-the-release-build-for-testing/

I just removed GetCallingAssembly call and replaced with passing the assembly explicitly, like typeof(Startup).Assembly

Comments

Your Answer

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

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.