2 Stimmen

Wie zu tun Aktion Injektion für MVC 3 mit Autofac?

Ich erstelle eine ASP.NET MVC 3-Anwendung, die versucht, die Vorteile der Controller-Action-Injection wie beschrieben zu nutzen aquí .

Controller Konstruktor Injektion funktioniert ohne Probleme, aber ich kann nicht scheinen, um Aktion Injektion zu arbeiten.

Ich habe Autofac in der Datei Global.asax wie folgt eingerichtet:

var builder = new ContainerBuilder();

builder.Register<ITestInject>(c => new TestInject { TestString = "hi" });

builder.RegisterType<ExtensibleActionInvoker>().As<IActionInvoker>();
builder.RegisterControllers(typeof(MvcApplication).Assembly).InjectActionInvoker();

var container = builder.Build();
DependencyResolver.SetResolver(new AutofacDependencyResolver(container));

Und mein Controller hat eine Aktion wie diese:

public ActionResult Test(ITestInject testInject)
{
        return View(testInject);
}

Die Klasse/Schnittstelle TestInject/ITestInject ist definiert als :

public interface ITestInject
{
    string TestString { get; }
}
public class TestInject : ITestInject
{
    public string TestString { get; set; }
}

Wenn ich versuche, zur Aktion "Test" zu navigieren, sehe ich diesen Fehler:

Serverfehler in der Anwendung '/'.

Eine Instanz einer Schnittstelle kann nicht erstellt werden.

Beschreibung: Während der Ausführung der aktuellen Webanfrage ist eine unbehandelte Ausnahme aufgetreten. Bitte überprüfen Sie den Stack-Trace für weitere Informationen über den Fehler und wo er im Code entstanden ist.

Details zur Ausnahme: System.MissingMethodException: Es kann keine Instanz einer Schnittstelle erstellt werden.

Fehlerquelle:

Während der Ausführung der aktuellen Webanfrage wurde eine unbehandelte Ausnahme erzeugt. Informationen über den Ursprung und den Ort der Ausnahme können anhand der nachstehenden Stapelverfolgung der Ausnahme ermittelt werden.

Stack Trace:

\[MissingMethodException: Cannot create an instance of an interface.\]
   System.RuntimeTypeHandle.CreateInstance(RuntimeType type, Boolean publicOnly, Boolean noCheck, Boolean& canBeCached, RuntimeMethodHandleInternal& ctor, Boolean& bNeedSecurityCheck) +0
   System.RuntimeType.CreateInstanceSlow(Boolean publicOnly, Boolean skipCheckThis, Boolean fillCache) +98
   System.RuntimeType.CreateInstanceDefaultCtor(Boolean publicOnly, Boolean skipVisibilityChecks, Boolean skipCheckThis, Boolean fillCache) +241
   System.Activator.CreateInstance(Type type, Boolean nonPublic) +69
   System.Web.Mvc.DefaultModelBinder.CreateModel(ControllerContext controllerContext, ModelBindingContext bindingContext, Type modelType) +199
   System.Web.Mvc.DefaultModelBinder.BindComplexModel(ControllerContext controllerContext, ModelBindingContext bindingContext) +572
   System.Web.Mvc.DefaultModelBinder.BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext) +449
   System.Web.Mvc.ControllerActionInvoker.GetParameterValue(ControllerContext controllerContext, ParameterDescriptor parameterDescriptor) +317
   Autofac.Integration.Mvc.ExtensibleActionInvoker.GetParameterValue(ControllerContext controllerContext, ParameterDescriptor parameterDescriptor) +122
   System.Web.Mvc.ControllerActionInvoker.GetParameterValues(ControllerContext controllerContext, ActionDescriptor actionDescriptor) +117
   System.Web.Mvc.ControllerActionInvoker.InvokeAction(ControllerContext controllerContext, String actionName) +343
   System.Web.Mvc.Controller.ExecuteCore() +116
   System.Web.Mvc.ControllerBase.Execute(RequestContext requestContext) +97
   System.Web.Mvc.ControllerBase.System.Web.Mvc.IController.Execute(RequestContext requestContext) +10 
   System.Web.Mvc.`<`\>c\__DisplayClassb.`<`BeginProcessRequest>b_\_5() +37
   System.Web.Mvc.Async.`<`\>c\__DisplayClass1.`<`MakeVoidDelegate>b_\_0() +21
   System.Web.Mvc.Async.`<`\>c\__DisplayClass8\`1.`<`BeginSynchronous>b_\_7(IAsyncResult _) +12
   System.Web.Mvc.Async.WrappedAsyncResult\`1.End() +62
   System.Web.Mvc.`<`\>c_\_DisplayClasse.`<`EndProcessRequest>b\__d() +50
   System.Web.Mvc.SecurityUtil.`<`GetCallInAppTrustThunk>b_\_0(Action f) +7
   System.Web.Mvc.SecurityUtil.ProcessInApplicationTrust(Action action) +22
   System.Web.Mvc.MvcHandler.EndProcessRequest(IAsyncResult asyncResult) +60
   System.Web.Mvc.MvcHandler.System.Web.IHttpAsyncHandler.EndProcessRequest(IAsyncResult result) +9
   System.Web.CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute() +8841105
   System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously) +184

Versionsinformationen: Microsoft .NET Framework Version:4.0.30319; ASP.NET Version:4.0.30319.1

Hat jemand eine Idee, was ich hier falsch mache?

Ich verwende Autofac Version 2.4.5.724.

Danke.

7voto

Nicholas Blumhardt Punkte 27718

Action Injection ist in der aktuellen Autofac MVC3-Implementierung standardmäßig ausgeschaltet.

Um sie zu aktivieren, übergeben Sie einen Parameter an ExtensibleActionInvoker :

builder.RegisterType<ExtensibleActionInvoker>()
    .As<IActionInvoker>()
    .WithParameter("injectActionMethodParameters", true);

Diese Änderung ist noch nicht lange her, und einige Unterlagen müssen aktualisiert werden - bitte entschuldigen Sie die Unannehmlichkeiten.

0voto

Peter Lillevold Punkte 32995

Das Problem ist diese Zeile

builder.Register<ITestInject>(c => new TestInject { TestString = "hi" });

Der erste Parameter in jeder Register Methode ist die konkrete Dienstleistung die Sie registrieren möchten. Nach diesem Typ folgt das "Wie wird instanziiert" und dann die Parameter, die die eigentliche Schnittstelle definieren, als die der Dienst dargestellt werden soll. Sie erhalten die Ausnahme, weil Autofac versucht, die Implementierung zu instanziieren, die im obigen Fall eine Schnittstelle ist. Offensichtlich wird kein Konstruktor für einen Schnittstellentyp gefunden.

Und nun sehen Sie sich das an:

builder.Register<TestInject>(c => new TestInject { TestString = "hi" }).As<ITestInject>();

Dieser Ansatz ist IMO eine der Stärken von Autofac im Vergleich zu anderen DI-Frameworks. Während andere die Registrierung mit der Schnittstelle beginnen, die Sie offenlegen wollen, und mit der Implementierung enden, beginnt Autofac mit der eigentlichen Implementierung und endet mit der Schnittstelle. Dies sorgt für eine sauberere Syntax, insbesondere in Fällen, in denen eine konkrete Implementierung als mehrere Schnittstellen in einer Registrierung dargestellt werden kann.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X