Domanda

Sto creando un'applicazione ASP.NET MVC 3 cercando di sfruttare l'iniezione dell'azione del controller come descritto qui.

L'iniezione del costruttore controller funziona senza problemi, ma non riesco a far funzionare l'iniezione di azione.

Ho impostato AutoFac in Global.asax in questo modo:

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

E il mio controller ha un'azione come questa:

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

La classe/interfaccia TestInject/iTestinject è definita come:

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

Quando provo a navigare all'azione del test, vedo questo errore:

Errore del server nell'applicazione '/'

Non è possibile creare un'istanza di un'interfaccia.

Descrizione: un'eccezione non gestita si è verificata durante l'esecuzione della richiesta Web corrente. Si prega di rivedere la traccia dello stack per ulteriori informazioni sull'errore e dove ha avuto origine nel codice.

Dettagli dell'eccezione: System.MissingMethodexception: non è in grado di creare un'istanza di un'interfaccia.

Errore di origine:

È stata generata un'eccezione non gestita durante l'esecuzione della richiesta Web corrente. Le informazioni relative all'origine e alla posizione dell'eccezione possono essere identificate utilizzando la traccia dello stack di eccezione di seguito.

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.wrapsyncresult`1.end () +62 System.web.mvc.<> c_DisplayClasse.<EndProcessRequest>b_D () +50 System.Web.MVC.SecurityUtil.<GetCallinapptrusThunk> 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

Informazioni sulla versione: Microsoft .NET Framework Versione: 4.0.30319; Versione ASP.NET: 4.0.30319.1

Qualche idea su cosa sto facendo di sbagliato qui?

Sto usando la versione AutoFac 2.4.5.724.

Grazie.

È stato utile?

Soluzione

L'iniezione di azione viene disattivata per impostazione predefinita nell'attuale implementazione AutoFAC MVC3.

Per abilitarlo, passare un parametro a ExtensibleActionInvoker:

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

Questa è stata una modifica piuttosto recente e alcune documentazioni dovranno aggiornare, scusate per la seccatura.

Altri suggerimenti

Il problema è questa linea

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

Il primo parametro in qualsiasi Register Il metodo è il Servizio concreto Vuoi registrarti. A seguito di quel tipo arriva "come istanziare", quindi i parametri che definiscono l'interfaccia effettiva per esporre il servizio come. Ottieni l'eccezione perché AutoFac cerca di istanziare l'implementazione, che nel caso sopra è un'interfaccia. Ovviamente, nessun costruttore si trova su un tipo di interfaccia.

Ora guarda questo:

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

Questo approccio IMO è uno dei punti di forza di AutoFAC rispetto ad altri framework DI. Laddove altri iniziano la registrazione con l'interfaccia che si desidera esporre e finisce con l'implementazione, AutoFAC inizia con l'implementazione effettiva e finisce con l'interfaccia. Ciò rende la sintassi più pulita, specialmente nei casi in cui un'implementazione concreta può essere esposta come diverse interfacce, tutte in una registrazione.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top