【问题标题】:ASP.NET MVC2 Error: No parameterless constructor defined for this objectASP.NET MVC2 错误:没有为此对象定义无参数构造函数
【发布时间】:2010-12-28 16:56:01
【问题描述】:

编辑:已修复——请参阅下面的解决方案

解决方案:首先我错误地将我的节点定义在 /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 容器)的方法体,为无效请求返回 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:相关的 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>

【问题讨论】:

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


【解决方案1】:

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

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

查看this blog post了解更多信息。

【讨论】:

  • 我的 Global.asax 文件中已经有这个条目,用于使用 Castle Windsor。 ControllerBuilder.Current.SetControllerFactory(new WindsorControllerFactory());
  • @Caley Woods,你能展示你的代码注册控制器及其依赖于城堡温莎的代码吗?
  • 我注意到我的组件部分中没有定义连接字符串,知道如何实现吗? 根据这本书,但我不确定两者之间的关系。
【解决方案2】:

你可以使用基于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() 方法来完成

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-11-24
    • 2013-04-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-30
    相关资源
    最近更新 更多