Autofac无法解析控制器操作参数

时间:2015-12-23 11:24:56

标签: c# asp.net-mvc autofac

我有一个名为LanguageBase的抽象类。

我还有一个名为Language的派生类(不要担心我为什么这样做 - 有一个有效的用例,但不属于本讨论的范围。)

在我的ASP.Net MVC应用程序中,我有一个控制器,其中一些操作方法将LanguageBase作为参数。在运行时,Autofac必须将其解析为语言。

在Global.asax中,我有以下方法来注册我的类型并创建我的容器:

 private void RegisterTypes()
    {
        var builder = new ContainerBuilder();

        //http://autofac.readthedocs.org/en/latest/integration/mvc.html
        builder.RegisterControllers(typeof(MvcApplication).Assembly).PropertiesAutowired();

        builder.RegisterType<Language>().As<LanguageBase>();

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

    }

但是,在运行时,我收到此错误:

  

&#39; /&#39;中的服务器错误应用

     

无法创建抽象类。

     

描述:执行期间发生了未处理的异常   当前的网络请求。请查看堆栈跟踪了解更多信息   有关错误的信息以及它在代码中的起源。

     

异常详细信息:System.MissingMethodException:无法创建   抽象类。

     

来源错误:

     

执行期间生成了未处理的异常   当前的网络请求。有关的来源和位置的信息   可以使用下面的异常堆栈跟踪来识别异常。

     

堆栈追踪:

     

[MissingMethodException:无法创建抽象类。]
  System.RuntimeTypeHandle.CreateInstance(RuntimeType类型,布尔值   publicOnly,Boolean noCheck,Boolean&amp; canBeCached,   RuntimeMethodHandleInternal&安培; ctor,布尔&amp; bNeedSecurityCheck)+0
  System.RuntimeType.CreateInstanceSlow(Boolean publicOnly,Boolean   skipCheckThis,Boolean fillCache,StackCrawlMark&amp; stackMark)+113
  System.RuntimeType.CreateInstanceDefaultCtor(Boolean publicOnly,   Boolean skipCheckThis,Boolean fillCache,StackCrawlMark&amp; stackMark)   +206 System.Activator.CreateInstance(Type type,Boolean nonPublic)+83 System.Activator.CreateInstance(Type type)+11 System.Web.Mvc.DefaultModelBinder.CreateModel(ControllerContext   controllerContext,ModelBindingContext bindingContext,Type modelType)   197

     

[MissingMethodException:无法创建抽象类。对象类型   &#39; Visia.PartyRoles.Generic.IDomain.LanguageBase&#39 ;.]
  System.Web.Mvc.DefaultModelBinder.CreateModel(ControllerContext   controllerContext,ModelBindingContext bindingContext,Type modelType)   +233 System.Web.Mvc.DefaultModelBinder.BindComplexModel(ControllerContext   controllerContext,ModelBindingContext bindingContext)+531
  System.Web.Mvc.DefaultModelBinder.BindModel(ControllerContext   controllerContext,ModelBindingContext bindingContext)+330
  System.Web.Mvc.ControllerActionInvoker.GetParameterValue(ControllerContext   controllerContext,ParameterDescriptor parameterDescriptor)+331
  System.Web.Mvc.ControllerActionInvoker.GetParameterValues(ControllerContext   controllerContext,ActionDescriptor actionDescriptor)+105
  System.Web.Mvc.Async&LT;&GT; c__DisplayClass21.b__19(的AsyncCallback   asyncCallback,Object asyncState)+743
  System.Web.Mvc.Async.WrappedAsyncResult 1.CallBeginDelegate(AsyncCallback callback, Object callbackState) +14
System.Web.Mvc.Async.WrappedAsyncResultBase
1.Begin(的AsyncCallback   回调,对象状态,Int32超时)+128
  System.Web.Mvc.Async.AsyncControllerActionInvoker.BeginInvokeAction(ControllerContext   controllerContext,String actionName,AsyncCallback callback,Object   州)+343
  System.Web.Mvc.Controller.b__1c(AsyncCallback的   asyncCallback,Object asyncState,ExecuteCoreState innerState)+25
  System.Web.Mvc.Async.WrappedAsyncVoid 1.CallBeginDelegate(AsyncCallback callback, Object callbackState) +30
System.Web.Mvc.Async.WrappedAsyncResultBase
1.Begin(的AsyncCallback   回调,对象状态,Int32超时)+128
  System.Web.Mvc.Controller.BeginExecuteCore(AsyncCallback回调,   对象状态)+465
  System.Web.Mvc.Controller.b__14(AsyncCallback的   asyncCallback,Object callbackState,Controller controller)+18
  System.Web.Mvc.Async.WrappedAsyncVoid 1.CallBeginDelegate(AsyncCallback callback, Object callbackState) +20
System.Web.Mvc.Async.WrappedAsyncResultBase
1.Begin(的AsyncCallback   回调,对象状态,Int32超时)+128
  System.Web.Mvc.Controller.BeginExecute(RequestContext requestContext,   AsyncCallback回调,对象状态)+374
  System.Web.Mvc.Controller.System.Web.Mvc.Async.IAsyncController.BeginExecute(的RequestContext   requestContext,AsyncCallback回调,对象状态)+16
  System.Web.Mvc.MvcHandler.b__4(AsyncCallback的   asyncCallback,Object asyncState,ProcessRequestState innerState)+52   System.Web.Mvc.Async.WrappedAsyncVoid 1.CallBeginDelegate(AsyncCallback callback, Object callbackState) +30
System.Web.Mvc.Async.WrappedAsyncResultBase
1.Begin(的AsyncCallback   回调,对象状态,Int32超时)+128
  System.Web.Mvc.MvcHandler.BeginProcessRequest(HttpContextBase   httpContext,AsyncCallback回调,对象状态)+384
  System.Web.Mvc.MvcHandler.BeginProcessRequest(HttpContext httpContext,   AsyncCallback回调,对象状态)+48
  System.Web.Mvc.MvcHandler.System.Web.IHttpAsyncHandler.BeginProcessRequest(HttpContext的   context,AsyncCallback cb,Object extraData)+16
  System.Web.CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute()   +103 System.Web.HttpApplication.ExecuteStep(IExecutionStep step,Boolean&amp; completedSynchronously)+155

我错过了什么吗?

更新

这是我的控制器代码......

using System;
using System.Linq;
using System.Net;
using System.Web.Mvc;
using Visia.MasterData.Banking.DAL;
using Visia.PartyRoles.Core.Banking.IDataServices;
using Visia.PartyRoles.Generic.IDomain;

namespace Visia.CrediScan.UI.Views
{
    public class LanguagesController : Controller
    {
        private readonly QueryBase _query;
        private readonly CommandBase _command;

        public LanguagesController(QueryBase query, CommandBase command)
        {
            if (query == null) throw new ArgumentNullException(nameof(query));
            if (command == null) throw new ArgumentNullException(nameof(command));
            _query = query;
            _command = command;
        }

        // GET: /Languages/Edit/5
        public ActionResult Edit(long? id, long CountryId)
        {
            if (id == null)
            {
                return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
            }
            var language = _query.GetLanguage((long)id);
            if (language == null)
            {
                return HttpNotFound();
            }
            ViewBag.CountryId = CountryId;
            return View(language);
        }

        // POST: /Languages/Edit/5
        // To protect from overposting attacks, please enable the specific properties you want to bind to, for
        // more details see http://go.microsoft.com/fwlink/?LinkId=317598.
        [HttpPost]
        [ValidateAntiForgeryToken]
        public ActionResult Edit(LanguageBase language, long CountryId)
        {
            if (ModelState.IsValid)
            {
                language.CountryId = CountryId.ToString();
                _command.Update(language);
                return RedirectToAction("Index", new { CountryId = CountryId });
            }
            return View(language);
        }
    }
}

1 个答案:

答案 0 :(得分:2)

您的问题与Autofac无关。 MVC框架负责根据请求中的数据为action方法创建参数。

虽然您可以创建自定义模型绑定器(通过IModelBinder界面)来解决您的问题,但我建议您没有包含行为的操作参数。

相反,创建一个仅包含数据并将其用作操作参数的简单模型(例如Language)。并且有另一项服务(例如ILanguageService)包含您可能希望使用DI改变的行为。这种服务将被注入控制器的构造函数中。

看看this article。我看到它的方式,动作方法是你的应用程序的边界。所以你的动作参数不应该是面向对象的,即它们不应该包含行为。它们应该是简单的数据对象。然后,您可以使用其他服务将简单数据对象转换为面向对象(包含行为)的某个对象。然后通过构造函数注入此类服务(因此Autofac可以处理它)。