Включение зависимостей не работает с автономными Web-серверами Owin 2 и Autofac
Я нахожу свои ноги с Web Api 2, Owin и Autofac и нуждаюсь в некоторых рекомендациях.
Обзор
У меня есть автономный веб-Apo, основанный на Owin, который использует Autofac для IoC и инъекции зависимостей. Проект представляет собой консольное приложение, действующее как услуга, то есть его можно остановить и запустить. У меня есть контроллер проверки подлинности с двумя конструкторами: один параметр-меньше, а другой - репозиторий.
Проблема
Когда я запускаю службу и вызываю api, вызывается мой конструктор без параметров и мой репозиторий никогда не вводится (_repository = null).
Исследование
Я провел немало исследований и нашел полезные проекты на Github, которые я воспроизвел на тройнике, но мне не хватает большой части головоломки. Это было полезно, но не решило мою проблему. Я прочитал этот вопрос о переполнении стека и Dane Sparza имел приятный демонстрационный проект , но Я не мог найти четкое решение. Проблема заключается не в самообслуживании, а в инъекции зависимостей.
Мой код (разрежен для объяснения)
public class Startup
{
public void Configuration(IAppBuilder app)
{
HttpConfiguration config = new HttpConfiguration();
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
var json = config.Formatters.JsonFormatter;
json.SerializerSettings.PreserveReferencesHandling = Newtonsoft.Json.PreserveReferencesHandling.Objects;
config.Formatters.Remove(config.Formatters.XmlFormatter);
var connectioninfo = ConnectionInfo.FromAppConfig("mongodb");
var builder = new ContainerBuilder(); // Create the container builder.
builder.RegisterApiControllers(Assembly.GetExecutingAssembly()); // Register the Web API controllers.
builder.Register(c => new Logger()).As<ILogger>().InstancePerRequest(); // Register a logger service to be used by the controller and middleware.
builder.RegisterType<AuthenticationRepository>().As<IAuthenticationRepository>().WithParameter(new NamedParameter("connectionInfo", connectioninfo)).InstancePerRequest();
var container = builder.Build();
var resolver = new AutofacWebApiDependencyResolver(container); // Create an assign a dependency resolver for Web API to use.
GlobalConfiguration.Configuration.DependencyResolver = resolver; // Configure Web API with the dependency resolver
app.UseCors(CorsOptions.AllowAll);
app.UseWebApi(config);
app.UseAutofacWebApi(config); // Make sure the Autofac lifetime scope is passed to Web API.
}
Program.cs
static void Main(string[] args)
{
var service = new ApiService(typeof(Program), args);
var baseAddress = "http://localhost:9000/";
IDisposable _server = null;
service.Run(
delegate()
{
_server = WebApp.Start<Startup>(url: baseAddress);
},
delegate()
{
if (_server != null)
{
_server.Dispose();
}
}
);
}
ApiController
public class AuthenticationController : ApiController
{
private IAuthenticationRepository _repository;
public AuthenticationController() { }
public AuthenticationController(IAuthenticationRepository repository)
{
_repository = repository;
}
[AllowAnonymous]
public IHttpActionResult Authenticate(string name, string password)
{
if (_repository == null)
return BadRequest("User repository is null.");
var valid = _repository.AuthenticateUser(name, password);
return Ok(valid);
}
}
Ответы
Ответ 1
Вы должны использовать HttpConfiguration
, с которым вы загружаете OWIN всюду.
Итак, это:
GlobalConfiguration.Configuration.DependencyResolver = resolver;
Должно стать:
config.DependencyResolver = resolver;
Кроме того, все выглядит хорошо. Контроллеры Api зарегистрированы, хотя вы не даете им возможности. Не уверен, что по умолчанию для автооблоков по умолчанию для запросов на контроллеры или если у него вообще есть понятие охвата запроса (я знаю, что LightInject имеет его).
Оглядываясь, я думаю, что вы следовали примеру репозитория Google Code для Autofac, который действительно использует GlobalConfiguration. Вместо этого, если вы посмотрите на пример GitHub, это немного отличается. Постарайтесь внести изменения в соответствии с этим. В том числе:
// This should be the first middleware added to the IAppBuilder.
app.UseAutofacMiddleware(container);
Обновление 2016
То, что я сказал выше, по-прежнему применяется, но что-то дополнительное из документов Autofac (спасибо Brad):
Общей ошибкой в интеграции OWIN является использование GlobalConfiguration.Configuration. В OWIN вы создаете конфигурация с нуля. Вы не должны ссылаться GlobalConfiguration.Configuration где угодно при использовании OWIN интеграции.