Unity IoC не вводит зависимость в Web API Controller
Я очень новичок в использовании Unity, но моя проблема в том, что всякий раз, когда я вызываю свой веб-сервис, я получаю исключение, указывающее, что
"Убедитесь, что у контроллера есть беззадачный публичный конструктор"
Я следил за несколькими учебниками, и у меня по-прежнему возникает одна и та же проблема.
В функции Register моего класса WebApiConfig у меня есть
var container = new UnityContainer();
container.RegisterType<IValidator, Validator>(new HierarchicalLifetimeManager());
config.DependencyResolver = new UnityResolver(container);
Вот мой класс UnityResolver
using Microsoft.Practices.Unity;
using System;
using System.Collections.Generic;
using System.Web.Http.Dependencies;
public class UnityResolver : IDependencyResolver
{
protected IUnityContainer container;
public UnityResolver(IUnityContainer container)
{
if (container == null)
{
throw new ArgumentNullException("container");
}
this.container = container;
}
public object GetService(Type serviceType)
{
try
{
return container.Resolve(serviceType);
}
catch (ResolutionFailedException)
{
return null;
}
}
public IEnumerable<object> GetServices(Type serviceType)
{
try
{
return container.ResolveAll(serviceType);
}
catch (ResolutionFailedException)
{
return new List<object>();
}
}
public IDependencyScope BeginScope()
{
var child = container.CreateChildContainer();
return new UnityResolver(child);
}
public void Dispose()
{
container.Dispose();
}
}
Я не зарегистрировал никаких контроллеров, так как каждый учебник утверждает, что мне не нужно это делать. Вот мой фактический контроллер
public class Controller: ApiController
{
private IValidator _validator;
public Controller(IValidator validator)
{
this._validator = validator;
}
[HttpPost]
public void ReceiveIPN()
{
}
}
Есть ли у кого-нибудь идеи относительно того, что я могу делать неправильно? Спасибо!
EDIT 1: Вот "реализация" класса Validator. Это довольно пусто, потому что я не хотел вводить ошибку здесь, пока не разрешу проблему Unity.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
public class Validator: IValidator
{
public bool ValidateIPN(string body)
{
throw new NotImplementedException();
}
}
EDIT 2: Вот полный ответ об ошибке, который я получаю, когда пытаюсь вызвать веб-маршрут api с помощью Fiddler
{ "message": "Произошла ошибка.", "exceptionMessage": "Ошибка произошел при попытке создать контроллер типа" Контроллер ". Делать убедитесь, что контроллер имеет бесступенчатую публикацию Конструктор" "ExceptionType.": "System.InvalidOperationException" "StackTrace": "в System.Web.Http.Dispatcher.DefaultHttpControllerActivator.Create(HttpRequestMessage запрос, HttpControllerDescriptor controllerDescriptor, Тип controllerType) в System.Web.Http.Controllers.HttpControllerDescriptor.CreateController(HttpRequestMessage запрос) в System.Web.Http.Dispatcher.HttpControllerDispatcher.d__1.MoveNext()" "InnerException": { "сообщение": "ошибка"., "exceptionMessage": "Тип" Project.Controller ' не имеет значения по умолчанию конструктора "" ExceptionType ":" System.ArgumentException", "StackTrace":" в System.Linq.Expressions.Expression.New(тип типа) в System.Web.Http.Internal.TypeActivator.Create [TBase] (Тип instanceType) в System.Web.Http.Dispatcher.DefaultHttpControllerActivator.GetInstanceOrActivator(HttpRequestMessage request, Type controllerType, Func`1 & активатор) при System.Web.Http.Dispatcher.DefaultHttpControllerActivator.Create(HttpRequestMessage запрос, HttpControllerDescriptor controllerDescriptor, Тип controllerType) "}}
Ответы
Ответ 1
Итак, после нескольких часов ударов головой о стену, я обнаружил, что это не работает, потому что в моем проекте был класс OWIN/Katana Startup.cs. Теперь я точно не знаю, что здесь происходит, поэтому больше информации было бы здорово.
В принципе, поскольку я использовал OWIN/Katana, у меня был файл Startup.cs, который создал новый объект HttpConfiguration и настроил его, подобно тому, как это делается в классе WebApiConfig.cs.
private void ConfigureWebApi(HttpConfiguration config)
{
config.MapHttpAttributeRoutes();
var container = new UnityContainer();
container.RegisterType<IValidator, Validator>();
config.DependencyResolver = new UnityDependencyResolver(container);
var jsonFormatter = config.Formatters.OfType<JsonMediaTypeFormatter().First();
jsonFormatter.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver();
}
Похоже, что код сначала запускается через функцию регистрации WebApiConfig, а THEN переопределяет объект HttpConfiguration с тем, который был сгенерирован в файле Startup.cs. Мне нужно было переместить мой контейнер, чтобы он работал.
Извините, что раньше я не поднимал вещи OWIN. Это для меня совершенно новое, и я не понимал, что это актуально. Надеюсь, это спасет кого-то боль, которую я только что пережил.
Ответ 2
Контейнер Unity может быть удален, потому что он определен только в области вашего метода WebApiConfig.Register()
. Если вы определяете свой контейнер как участника Global, который будет поддерживать ваш контейнер в течение всего срока действия приложения, он должен работать.
Изменить: также не забывайте утилизировать контейнер на Application_End.
Ответ 3
- Установите Unity.mvc5 и Unity.WebApi в проекте через пакет nuget
- Укажите полное пространство имён как указано ниже
Пример:
public static class UnityConfig
{
public static void RegisterComponents()
{
var container = new UnityContainer();
// register all your components with the container here
// it is NOT necessary to register your controllers
// e.g. container.RegisterType<ITestService, TestService>();
DependencyResolver.SetResolver(new Unity.Mvc5.UnityDependencyResolver(container));
GlobalConfiguration.Configuration.DependencyResolver = new Unity.WebApi.UnityDependencyResolver(container);
}
}
Ответ 4
Я знаю, что это старый пост, но поскольку я просто столкнулся с той же проблемой, решение состояло в том, чтобы просто передать объект конфигурации в функцию регистрации Unity и использовать DependencyResolver из этого экземпляра:
РЕДАКТИРОВАТЬ: Только что отметил, что принятый ответ делает это... Извините за спам; -)
public static class UnityConfig
{
public static void Register(HttpConfiguration config)
{
var container = new UnityContainer();
// register your services here...
// replace...
/* GlobalConfiguration.Configuration.DependencyResolver = new Unity.WebApi.UnityDependencyResolver(container); */
// with this:
config.DependencyResolver = new Unity.WebApi.UnityDependencyResolver(container);
}
}