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);
    }
}