ASP.NET MVC2 Error: No parameterless constructor defined for this object
Edit: This is fixed -- See Solution below
Solution: First I incorrectly had my node defined in /shared/web.config instead of the web.config in the root of the WebUI project. I also had not correctly defined my connection string within web.config. I have pasted the proper web.config sections below:
<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>
I also had to adjust the method body of WindsorControllerFactory.cs (IoC Container) to return null for invalid requests like so:
protected override IController GetControllerInstance(RequestContext requestContext, Type controllerType)
{
if (controllerType == null)
return null;
else
return (IController)container.Resolve(controllerType);
}
End of Solution
I'm following the book Pro ASP.NET MVC2 by Sanderson. I've implemented the IoC container and gotten the web.config straightened out. When I attempt to run my application I get the error "No parameterless constructor defined for this object"
After some searching I found this exact issue on SO here. The solution is to create the constructor with no parameters but I'm having an issue doing this. I've pasted the code from ProductsController.cs below
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());
}
}
}
Above the public ProductsController that has parameters I tried doing:
public ProductsRepository() : this(new productsRepository())
{
}
I'm unclear about exactly what needs to go after the "new". IProductsRepository doesn't seem to work and neither does what I have written. I have pasted the stack trace below:
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
Any help would be greatly appreciated.
Edit: Posting WindsorControllerFactory.cs code:
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 nodes:
<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>
&l开发者_运维知识库t;/castle>
You need to configure a custom controller factory in order to wire up your DI framework inside Application_Start
method in global.asax. So for example if you are using Unity as DI framework you could:
ControllerBuilder.Current.SetControllerFactory(
typeof(UnityControllerFactory)
);
Check out this blog post for more information.
you can make use of setter based injection
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;
}
}
}
here , you need to manually set the MyRepository.
but best would be , if you register your repository to a container and beliving that you are using Unity framework , so you can do it by IUnityContainer.RegisterType() method
精彩评论