ASP.NET MVC2错误:没有为此对象定义无参数构造函数

时间:2010-12-28 16:56:01

标签: asp.net asp.net-mvc-2

编辑:修复此问题 - 请参阅下面的解决方案

解决方案:首先,我错误地在/shared/web.config中定义了我的节点,而不是WebUI项目根目录中的web.config。我还没有在web.config中正确定义我的连接字符串。我已粘贴下面正确的web.config部分:

<configuration>
  <configSections>
    <section name="castle" type="Castle.Windsor.Configuration.AppDomain.CastleSectionHandler, Castle.Windsor"/>
  <!--more sectiongroup and sections redacted for brevity -->
  </configSections>
  <castle>
      <components>
          <component id="ProdsRepository" service="DomainModel.Abstract.IProductsRepository, DomainModel" type="DomainModel.Concrete.SqlProductsRepository, DomainModel">
              <parameters>
                  <connectionString>Data Source=.\SQLExpress;Initial Catalog=SportsStore; Integrated Security=SSPI</connectionString>
              </parameters>
          </component>
      </components>
  </castle>

我还必须调整WindsorControllerFactory.cs(IoC Container)的方法体,为无效请求返回null,如下所示:

protected override IController GetControllerInstance(RequestContext requestContext, Type controllerType)
{
    if (controllerType == null)
        return null;
    else
    return (IController)container.Resolve(controllerType);
}

解决方案结束

我正在关注Sanderson的Pro ASP.NET MVC2这本书。我已经实现了IoC容器,并将web.config理顺了。当我尝试运行我的应用程序时,我收到错误“没有为此对象定义无参数构造函数”

经过一番搜索后,我在SO here上发现了这个问题。解决方案是创建没有参数的构造函数,但我遇到了这样的问题。我已经粘贴了下面ProductsController.cs中的代码

namespace WebUI.Controllers
    {
        public class ProductsController : Controller
           {
               private IProductsRepository productsRepository;
               public ProductsController(IProductsRepository productsRepository)
               {
                   this.productsRepository = productsRepository;
               }

        public ViewResult List()
        {
            return View(productsRepository.Products.ToList());
        }
    }
}

在公共ProductsController上面,我有一些参数:

public ProductsRepository() : this(new productsRepository())
{
}

我不清楚“新”之后究竟需要做些什么。 IProductsRepository似乎不起作用,我写的也不行。我已粘贴下面的堆栈跟踪:

Stack Trace: 


[MissingMethodException: No parameterless constructor defined for this object.]
   System.RuntimeTypeHandle.CreateInstance(RuntimeType type, Boolean publicOnly, Boolean noCheck, Boolean& canBeCached, RuntimeMethodHandle& ctor, Boolean& bNeedSecurityCheck) +0
   System.RuntimeType.CreateInstanceSlow(Boolean publicOnly, Boolean fillCache) +86
   System.RuntimeType.CreateInstanceImpl(Boolean publicOnly, Boolean skipVisibilityChecks, Boolean fillCache) +230
   System.Activator.CreateInstance(Type type, Boolean nonPublic) +67
   System.Web.Mvc.DefaultControllerFactory.GetControllerInstance(RequestContext requestContext, Type controllerType) +80

[InvalidOperationException: An error occurred when trying to create a controller of type 'WebUI.Controllers.ProductsController'. Make sure that the controller has a parameterless public constructor.]
   System.Web.Mvc.DefaultControllerFactory.GetControllerInstance(RequestContext requestContext, Type controllerType) +190
   System.Web.Mvc.DefaultControllerFactory.CreateController(RequestContext requestContext, String controllerName) +68
   System.Web.Mvc.MvcHandler.ProcessRequestInit(HttpContextBase httpContext, IController& controller, IControllerFactory& factory) +118
   System.Web.Mvc.MvcHandler.BeginProcessRequest(HttpContextBase httpContext, AsyncCallback callback, Object state) +46
   System.Web.Mvc.MvcHandler.BeginProcessRequest(HttpContext httpContext, AsyncCallback callback, Object state) +63
   System.Web.Mvc.MvcHandler.System.Web.IHttpAsyncHandler.BeginProcessRequest(HttpContext context, AsyncCallback cb, Object extraData) +13
   System.Web.CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute() +8682818
   System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously) +155

非常感谢任何帮助。

编辑:发布WindsorControllerFactory.cs代码:

namespace WebUI
{
    public class WindsorControllerFactory : DefaultControllerFactory
    {
        WindsorContainer container;

        // The contructor:
        // 1. Sets up a new IoC container
        // 2. Registers all components specified in web.config
        // 3. Registers all controller types as components
        public WindsorControllerFactory()
        {
            // Instantiate a container, taking config from web.config
            container = new WindsorContainer(new XmlInterpreter(new ConfigResource("castle")));

            // Also register all the controller types as transient
            var controllerTypes = from t in Assembly.GetExecutingAssembly().GetTypes()
                                  where typeof(IController).IsAssignableFrom(t)
                                  select t;
            foreach (Type t in controllerTypes)
                container.AddComponentLifeStyle(t.FullName, t, Castle.Core.LifestyleType.Transient);
        }

        // Constructs the controller instance needed to service each request
        protected override IController  GetControllerInstance(RequestContext requestContext, Type controllerType)
        {
            return (IController)container.Resolve(controllerType);
        }

    }
}

Edit2:Pertinent Web.config节点:

<configSections>
    <section name="castle"
             type="Castle.Windsor.Configuration.AppDomain.CastleSectionHandler,
                 Castle.Windsor" />
  </configSections>
  <castle>
    <components>
      <component id="ProdsRepository"
                 service="DomainModel.Abstract.IproductsRepository, DomainModel"
                 type="DomainModel.Concrete.SqlProductsRepository, DomainModel"></component>
      <parameters>
      </parameters>
    </components>
  </castle>

2 个答案:

答案 0 :(得分:4)

您需要配置自定义控制器工厂,以便在global.asax中的Application_Start方法内连接DI框架。因此,例如,如果您使用Unity作为DI框架,您可以:

ControllerBuilder.Current.SetControllerFactory(
    typeof(UnityControllerFactory)
);

查看this blog post了解详情。

答案 1 :(得分:0)

你可以使用基于setter的注射

    public class ProductsController : Controller 

{   
    private IProductsRepository productsRepository; 

    public ProductsController()
    {

    } 
    public ViewResult List() 
    {
        return View(productsRepository.Products.ToList());
    }

    public IProductsRepository MyRepository
    {
        get
        {
            return productsRepository;
        }

        set
        {
            productsRepository = value;
        }
    }
}

在这里,您需要手动设置MyRepository。

但最好的情况是,如果您将存储库注册到容器并且认为您正在使用Unity框架,那么您可以通过IUnityContainer.RegisterType()方法来实现它