如何使用 Autofac 为 MVC 3 进行动作注入?
我正在创建一个 ASP.NET MVC 3 应用程序,尝试利用控制器操作注入,如所述 此处。
控制器构造函数注入工作没有任何问题,但我似乎无法让操作注入工作。
我在 Global.asax 中设置了 Autofac,如下所示:
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));
我的控制器具有如下操作:
public ActionResult Test(ITestInject testInject)
{
return View(testInject);
}
TestInject/ITestInject 类/接口定义为:
public interface ITestInject
{
string TestString { get; }
}
public class TestInject : ITestInject
{
public string TestString { get; set; }
}
当我尝试导航到 Test 操作时,我看到此错误:
“/”应用程序中的服务器错误。
无法创建接口实例。
描述:执行当前 Web 请求期间发生未处理的异常。请查看堆栈跟踪以获取有关错误及其在代码中的来源的更多信息。
异常详细信息:System.MissingMethodException:无法创建接口的实例。
来源错误:
执行当前 Web 请求期间生成未处理的异常。有关异常来源和位置的信息可以使用下面的异常堆栈跟踪来识别。
堆栈跟踪:
[MissingMethodException:无法创建接口的实例。] System.RuntimeTypeHandle.CreateInstance(RuntimeType type, Boolean publicOnly, Boolean noCheck, Boolean& canBeCached, RuntimeMethodHandleInternal& ctor, Boolean& bNeedSecurityCheck) +0 System.RuntimeType.CreateInstanceSlow(布尔publicOnly,布尔skipCheckThis,布尔fillCache)+98 System.RuntimeType.CreateInstanceDefaultCtor(布尔publicOnly,布尔skipVisibilityChecks,布尔skipCheckThis,布尔fillCache)+241 System.Activator.CreateInstance(类型类型,布尔非公共)+69 System.Web.Mvc.DefaultModelBinder.CreateModel(ControllerContextcontrollerContext,ModelBindingContext绑定Context,类型modelType)+199 System.Web.Mvc.DefaultModelBinder.BindComplexModel(ControllerContext 控制器上下文,ModelBindingContext 绑定上下文)+572 System.Web.Mvc.DefaultModelBinder.BindModel(ControllerContext 控制器上下文,ModelBindingContext 绑定上下文)+449 System.Web.Mvc.ControllerActionInvoker.GetParameterValue(ControllerContextcontrollerContext,ParameterDescriptorparameterDescriptor)+317 Autofac.Integration.Mvc.ExtensibleActionInvoker.GetParameterValue(ControllerContextcontrollerContext,ParameterDescriptorparameterDescriptor)+122 System.Web.Mvc.ControllerActionInvoker.GetParameterValues(ControllerContextcontrollerContext,ActionDescriptoractionDescriptor)+117 System.Web.Mvc.ControllerActionInvoker.InvokeAction(ControllerContextcontrollerContext,字符串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(操作 f) +7 System.Web.Mvc.SecurityUtil.ProcessInApplicationTrust(操作操作)+22 System.Web.Mvc.MvcHandler.EndProcessRequest(IAsyncResult asyncResult) +60 System.Web.Mvc.MvcHandler.System.Web.IHttpAsyncHandler.EndProcessRequest(IAsyncResult 结果) +9 System.Web.CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute() +8841105 System.Web.HttpApplication.ExecuteStep(IExecutionStep 步骤,Boolean&completedSynchronously) +184版本信息:Microsoft .NET Framework 版本:4.0.30319; ASP.NET版本:4.0.30319.1
关于我在这里做错了什么有什么想法吗?
我正在使用 Autofac 版本 2.4.5.724。
谢谢。
I'm creating an ASP.NET MVC 3 application trying to take advantage of controller action injection as described here.
Controller constructor injection works without any issues, but I can't seem to get action injection to work.
I've set up Autofac in Global.asax like this:
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));
And my controller has an action like this:
public ActionResult Test(ITestInject testInject)
{
return View(testInject);
}
The TestInject/ITestInject class/interface is defined as :
public interface ITestInject
{
string TestString { get; }
}
public class TestInject : ITestInject
{
public string TestString { get; set; }
}
When I try to navigate to the the Test action, I see this error:
Server Error in '/' Application.
Cannot create an instance of an interface.
Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code.
Exception Details: System.MissingMethodException: Cannot create an instance of an interface.
Source Error:
An unhandled exception was generated during the execution of the current web request. Information regarding the origin and location of the exception can be identified using the exception stack trace below.
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) +184Version Information: Microsoft .NET Framework Version:4.0.30319; ASP.NET Version:4.0.30319.1
Any ideas on what I'm doing wrong here?
I'm using Autofac version 2.4.5.724.
Thanks.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
在当前的 Autofac MVC3 实现中,动作注入默认是关闭的。
要启用它,请将参数传递给 ExtensibleActionInvoker:
这是最近的更改,一些文档需要更新 - 抱歉给您带来麻烦。
Action injection is turned off by default in the current Autofac MVC3 implementation.
To enable it, pass a parameter to
ExtensibleActionInvoker
:This was quite a recent change and some documentation will need updating - sorry about the hassle.
问题是这一行
任何
Register
方法中的第一个参数是您要注册的具体服务。该类型之后是“如何实例化”,然后是定义要公开服务的实际接口的参数。您会得到异常,因为 Autofac 尝试实例化实现,在上面的情况下是一个接口。显然,接口类型上没有找到构造函数。现在看看这个:
与其他 DI 框架相比,这种方法在我看来是 Autofacs 的优势之一。其他人从您想要公开的接口开始注册并以实现结束,而 Autofac 从实际实现开始并以接口结束。这使得语法更清晰,特别是在一个具体实现可以作为多个接口公开的情况下,所有这些都在一次注册中。
The problem is this line
The first parameter in any
Register
method is the concrete service you want to register. Following that type comes the "how to instantiate", and then parameters that define the actual interface to expose the service as. You get the exception because Autofac tries to instantiate the implementation, which in the case above is an interface. Obviously, no constructor is found on an interface type.Now look at this:
This approach IMO is one of Autofacs strengths compared to other DI frameworks. Where others start out the registration with the interface you want to expose and ends up with the implementation, Autofac starts with the actual implementation and ends up with the interface. This makes for cleaner syntax especially in cases where one concrete implementation can be exposed as several interfaces, all in one registration.