10

I have created a SelfHosted AspNet WebAPI with Visual Studio 2012 (.NET Framework 4.5). I enabled SSL for the WebAPI. It works fine when the controller is defined in the same project.

But when I add a reference of another project, containing controllers, it gives me the following error:

No HTTP resource was found that matches the request URI 'https://xxx.xxx.xxx.xxx:xxxx/hellowebapi/tests/'.

I have created custom classes for HttpSelfHostConfiguration and MessageHandler.

Any help to resolve this problem would be a great time-savor for me.

Thanking in advance.

1 Answers1

8

You can write a simple custom assemblies resolver which makes sure that your referenced assembly is loaded for the controller probing to work.

Following is a nice post from Filip regarding this:
http://www.strathweb.com/2012/06/using-controllers-from-an-external-assembly-in-asp-net-web-api/

Sample:

class Program
{
    static HttpSelfHostServer CreateHost(string address)
    {
        // Create normal config
        HttpSelfHostConfiguration config = new HttpSelfHostConfiguration(address);

        // Set our own assembly resolver where we add the assemblies we need
        CustomAssembliesResolver assemblyResolver = new CustomAssembliesResolver();
        config.Services.Replace(typeof(IAssembliesResolver), assemblyResolver);

        // Add a route
        config.Routes.MapHttpRoute(
          name: "default",
          routeTemplate: "api/{controller}/{id}",
          defaults: new { controller = "Home", id = RouteParameter.Optional });

        HttpSelfHostServer server = new HttpSelfHostServer(config);
        server.OpenAsync().Wait();

        Console.WriteLine("Listening on " + address);
        return server;
    }

    static void Main(string[] args)
    {
        // Create and open our host
        HttpSelfHostServer server = CreateHost("http://localhost:8080");

        Console.WriteLine("Hit ENTER to exit...");
        Console.ReadLine();
    }
}

public class CustomAssembliesResolver : DefaultAssembliesResolver
{
    public override ICollection<Assembly> GetAssemblies()
    {
        ICollection<Assembly> baseAssemblies = base.GetAssemblies();

        List<Assembly> assemblies = new List<Assembly>(baseAssemblies);

        var controllersAssembly = Assembly.LoadFrom(@"C:\libs\controllers\ControllersLibrary.dll");

        baseAssemblies.Add(controllersAssembly);

        return assemblies;
    }
}
Kiran
  • 56,921
  • 15
  • 176
  • 161
  • 1
    This shouldn't be necessary. The default resolver gets all assemblies from the current appdomain. I use controllers in other assemblies all the time and it works most of the time. I have to admit I have come across cases where it doesn't seem to work and I have never figured out why. – Darrel Miller Jun 21 '13 at 11:00
  • 5
    @DarrelMiller: It would depend on whether you are referring a type in the other assembly which is causing the assembly to be loaded, in which case the probing would work. In the above sample, for example, without using the assemblies resolver I could just do something like `Type valuesControllerType = typeof(ControllersLibrary.ValuesController);` and this would cause the assembly to be loaded. – Kiran Jun 21 '13 at 12:25
  • Ahhh, thanks for that insight. I usually have a MyApi.Configure(config) method in the DLL with the controllers, so that would guarantee that the assembly is loaded. – Darrel Miller Jun 21 '13 at 15:26
  • @DarrelMiller: I observed that if you are working with a MVC project, there is no problem in having controllers in another assembly. But, whenever you try to self-host your webapi, the self-host will not load other assemblies even if it has the project reference. You have to write your own assemblies resolver in that particular case. –  Jun 21 '13 at 16:42
  • @ImranNazir: You can look at my comment before. It not mandatory to have an assemblies resolver even in case of selfhost as long as you can cause the assembly to be loaded. – Kiran Jun 21 '13 at 16:47
  • I personally find it easier to find the assembly type-safely, like so: `var controllersAssembly = typeof(HomeController).Assembly;`. But it would need to be a controller that never gets removed, of course. – Aage Dec 21 '14 at 11:19