I just had to solve the same issue. This is how i did it:
First I created a new facade class to map the IServiceCollection
from the host builder to the interface HttpSelfHostConfiguration
supports:
using System;
using System.Collections.Generic;
using System.Web.Http.Dependencies;
using Microsoft.Extensions.DependencyInjection;
namespace IntegrationReceiver.WebApi
{
public class HttpSelfHostDependencyResolver : IDependencyResolver
{
private readonly IServiceProvider sp;
private readonly IServiceScope scope;
public HttpSelfHostDependencyResolver(IServiceProvider sp)
{
this.sp = sp;
this.scope = null;
}
public HttpSelfHostDependencyResolver(IServiceScope scope)
{
this.sp = scope.ServiceProvider;
this.scope = scope;
}
public IDependencyScope BeginScope() => new HttpSelfHostDependencyResolver(sp.CreateScope());
public void Dispose() => scope?.Dispose();
public object GetService(Type serviceType) => sp.GetService(serviceType);
public IEnumerable<object> GetServices(Type serviceType) => sp.GetServices(serviceType);
}
}
This required me to get the latest NuGet package Microsoft.Extensions.DependencyInjection.Abstractions
according to an answer here: How do I see all services that a .NET IServiceProvider can provide?
I then registered my HttpSelfHostServer
in the service provider with this code:
services.AddSingleton(sp => new HttpSelfHostDependencyResolver(sp));
services.AddSingleton(sp =>
{
//Starting the HttpSelfHostServer with user-level permissions requires to first run a command like
// netsh http add urlacl url=http://+:8080/ user=[DOMAINNAME]\[USERNAME]
var config = new HttpSelfHostConfiguration("http://localhost:8080");
config.Routes.MapHttpRoute("API Default", "api/{controller}/{id}", new { id = RouteParameter.Optional });
config.DependencyResolver = sp.GetRequiredService<HttpSelfHostDependencyResolver>();
return new HttpSelfHostServer(config);
});
And finally, to find my ApiController, I had to register that too in the service provider. I did that simply with:
services.AddScoped<HealthCheckController>();
For brewity, I'm just including my api controller below to illustrate how it now gets its dependencies:
using System.Net.Http;
using System.Threading.Tasks;
using System.Web.Http;
namespace IntegrationReceiver.WebApi
{
public class HealthCheckController : ApiController
{
private readonly ServiceBusRunner serviceBusRunner;
public HealthCheckController(ServiceBusRunner serviceBusRunner)
{
this.serviceBusRunner = serviceBusRunner;
}
[HttpGet]
public async Task<HttpResponseMessage> Get()
{
var response = new
{
serviceBusRunner.RunningTasks,
serviceBusRunner.MaxRunningTasks
};
return await Json(response)
.ExecuteAsync(System.Threading.CancellationToken.None);
}
}
}
This is a pretty dumb-down implementation but works for me until I can upgrade this code to net5.
I hope it helps you too!