编辑:修复此问题 - 请参阅下面的解决方案
解决方案:首先,我错误地在/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>
答案 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()方法来实现它