web-dev-qa-db-ger.com

Unity IoC fügt keine Abhängigkeit in den Web API Controller ein

Ich bin sehr neu mit Unity, aber mein Problem ist, dass ich immer dann, wenn ich meinen Webservice anrufe, eine Ausnahme bekomme

"Stellen Sie sicher, dass der Controller über einen öffentlichen Parameter ohne Parameter verfügt."

Ich habe mehrere Tutorials durchlaufen und bekomme immer noch das gleiche Problem. 

In der Register-Funktion meiner WebApiConfig-Klasse habe ich 

var container = new UnityContainer();
container.RegisterType<IValidator, Validator>(new HierarchicalLifetimeManager());
config.DependencyResolver = new UnityResolver(container);

Hier ist meine UnityResolver-Klasse

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

Ich habe keine Controller registriert, da jedes Tutorial behauptet, dass ich dies nicht tun muss. Hier ist mein tatsächlicher Controller

public class Controller: ApiController
{
    private IValidator _validator;

    public Controller(IValidator validator)
    {
        this._validator = validator;
    }

    [HttpPost]
    public void ReceiveIPN()
    {

    }
}

Hat jemand eine Idee, was ich falsch machen kann? Vielen Dank!

EDIT 1: Hier ist die "Implementierung" der Validator-Klasse. Es ist ziemlich leer, weil ich hier keinen Fehler einführen wollte, bis ich das Unity-Problem gelöst habe. 

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;


public class Validator: IValidator
{
    public bool ValidateIPN(string body)
    {
        throw new NotImplementedException();
    }
}

BEARBEITEN 2: Hier ist die gesamte Fehlerantwort, die ich bekomme, wenn ich versuche, die Web-API-Route mit Fiddler aufzurufen

{"message": "Ein Fehler ist aufgetreten.", "exceptionMessage": "Beim Erstellen eines Controllers vom Typ 'Controller' ist ein Fehler aufgetreten. . constructor. "," exceptionType ":" System.InvalidOperationException "," stackTrace ":" um System.Web.Http.Dispatcher.DefaultHttpControllerActivator.Create (HttpRequestMessage request, HttpControllerDescriptor controller controllerType) um System.Web.Http.Controllers.HttpControllerDescriptor.CreateController (HttpRequestMessage request) um System.Web.Http.Dispatcher.HttpControllerDispatcher.d__1.MoveNext () "," : {"message": "Ein Fehler ist aufgetreten.", "exceptionMessage": "Geben Sie 'Project.Controller' ein hat keinen Standard Konstruktor", "exceptionType": "System.ArgumentException "," stackTrace ":" bei System.Linq.Expressions.Expression.New (Typ type) um System.Web.Http.Internal.TypeActivator.Create [TBase] (Typ instanc eType) um System.Web.Http.Dispatcher.DefaultHttpControllerActivator.GetInstanceOrActivator (HttpRequestMessage Request, Typ controllerType, Func`1 und Aktivator) um System.Web.Http.Dispatcher.DefaultHttpControllerActivator.Create (HttpRequestMessage Request, HttpControllerDescriptor controllerDescriptor, Typ ControllerType) "}}

21

Nachdem ich stundenlang meinen Kopf gegen eine Wand geschlagen hatte, stellte sich heraus, dass dies nicht funktionierte, da ich eine OWIN/Katana Startup.cs-Klasse in meinem Projekt hatte. Jetzt weiß ich nicht genau, was hier los ist, also wären weitere Informationen großartig.

Grundsätzlich hatte ich, da ich OWIN/Katana verwendet hatte, eine Startup.cs-Datei, die ein neues HttpConfiguration-Objekt erstellt und konfiguriert hat, ähnlich wie in der WebApiConfig.cs-Klasse. 

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

Es scheint, als würde der Code zuerst durch die Register-Funktion von WebApiConfig laufen, und THEN überschreibt das HttpConfiguration-Objekt mit dem in der Datei Startup.cs generierten. Ich musste mein Container-Setup-Zeug hierher verschieben, damit es funktioniert. 

Es tut mir leid, dass ich das OWIN-Zeug nicht zuvor angesprochen habe. Das ist ziemlich neu für mich und ich wusste nicht, dass es relevant ist. Hoffentlich erspart dies jemandem den Schmerz, den ich gerade erlebt habe. 

26

Ihr Unity-Container wird wahrscheinlich verworfen, da er nur im Rahmen Ihrer WebApiConfig.Register()-Methode definiert ist. Wenn Sie Ihren Container als Mitglied von Global definieren, wodurch der Container für die gesamte Lebensdauer der App erhalten bleibt, sollte er funktionieren.

Bearbeiten: Vergessen Sie auch nicht, den Container in Application_End zu entsorgen.

1
moarboilerplate
  • Installieren Sie Unity.mvc5 und Unity.WebApi über ein Nuget-Paket in einem Projekt
  • Geben Sie den vollständigen Namen wie in der folgenden Zeile an

Beispiel:

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