I'm trying to set up IoC (Castle Windsor) in my MVC 2 project here, using the section in Pro Asp.net MVC Framework book.
However, I cannot compile after creating a custom controller factory as stated in the book.
This part give me error:
// Constructs the controller instance needed to service each request
protected override IController GetControllerInstance(Type controllerType)
{
return (IController) container.Resolve(controllerType);
}
Telling me that no suitable method have been found to override?
Does someone know if there's a problem with the code in the book or something changed with recent versions of things (wont suprise me..got some books on MVC here rendered completely useless with the evolution of asp.net mvc)
Here is my working WindsorControllerFactory based on the book:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using Castle.Windsor;
using Castle.Windsor.Configuration.Interpreters;
using Castle.Core.Resource;
using System.Reflection;
namespace WebUI {
public class WindsorControllerFactory : DefaultControllerFactory {
private WindsorContainer container;
public WindsorControllerFactory() {
this.container = new WindsorContainer(
new XmlInterpreter(new ConfigResource("castle"))
);
var controllerTypes = from t in Assembly.GetExecutingAssembly().GetTypes()
where typeof(IController).IsAssignableFrom(t)
select t;
foreach (Type t in controllerTypes)
this.container.AddComponentLifeStyle(t.FullName, t, Castle.Core.LifestyleType.Transient);
}
protected override IController GetControllerInstance(System.Web.Routing.RequestContext requestContext, Type controllerType) {
return (IController)this.container.Resolve(controllerType);
}
}
}
Yep, that did the trick (my lack of knowledge driving me bananas). Bit of refactoring to keep to the standards:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Web.Mvc;
using System.Web.Routing;
using Castle.Core;
using Castle.Core.Resource;
using Castle.Windsor;
using Castle.Windsor.Configuration.Interpreters;
namespace MySite.Web.Core
{
public class WindsorControllerFactory : DefaultControllerFactory
{
private readonly WindsorContainer _container;
public WindsorControllerFactory()
{
_container = new WindsorContainer(
new XmlInterpreter(new ConfigResource("castle"))
);
IEnumerable<Type> controllerTypes = from t in Assembly.GetExecutingAssembly().GetTypes()
where typeof (IController).IsAssignableFrom(t)
select t;
foreach (Type t in controllerTypes)
_container.AddComponentWithLifestyle(t.FullName, t, LifestyleType.Transient);
}
protected override IController GetControllerInstance(RequestContext requestContext, Type controllerType)
{
return (IController) _container.Resolve(controllerType);
}
}
}
ASP.NET Full Trust Mode
If your application requires ASP.NET Full Trust mode to execute, please open a ticket with our support department mentioning the domain name of the website which you need to execute in Full Trust mode.
One of our tech will thereafter allow ASP.NET Full Trust mode for your website and update you.
Hi, I'm doing the same example with MVC 2 as well and I've tried the above solution and still run into this exception:
Castle.MicroKernel.Handlers.HandlerException was unhandled by user code Message=Can't create component 'WebUI.Controllers.ProductsController' as it has dependencies to be satisfied. WebUI.Controllers.ProductsController is waiting for the following dependencies:
Services: - DomainModel.Abstract.IProductsRepository which was not registered.
Source=Castle.MicroKernel StackTrace: at Castle.MicroKernel.Handlers.DefaultHandler.AssertNotWaitingForDependency() at Castle.MicroKernel.Handlers.DefaultHandler.ResolveCore(CreationContext context, Boolean track) at Castle.MicroKernel.Handlers.AbstractHandler.Resolve(CreationContext context) at Castle.MicroKernel.DefaultKernel.ResolveComponent(IHandler handler, Type service, IDictionary additionalArguments) at Castle.MicroKernel.DefaultKernel.ResolveComponent(IHandler handler, Type service) at Castle.MicroKernel.DefaultKernel.get_Item(Type service) at Castle.Windsor.WindsorContainer.Resolve(Type service) at WindsorControllerFactory.GetControllerInstance(RequestContext requestContext, Type controllerType) in C:\Users\tommysu\documents\visual studio 2010\Projects\ShoppyTown\WebUI\WindsorControllerFactory.cs:line 36 at System.Web.Mvc.DefaultControllerFactory.CreateController(RequestContext requestContext, String controllerName) at System.Web.Mvc.MvcHandler.ProcessRequestInit(HttpContextBase httpContext, IController& controller, IControllerFactory& factory) at System.Web.Mvc.MvcHandler.BeginProcessRequest(HttpContextBase httpContext, AsyncCallback callback, Object state) at System.Web.Mvc.MvcHandler.BeginProcessRequest(HttpContext httpContext, AsyncCallback callback, Object state) at System.Web.Mvc.MvcHandler.System.Web.IHttpAsyncHandler.BeginProcessRequest(HttpContext context, AsyncCallback cb, Object extraData) at System.Web.HttpApplication.CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute() at System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously) InnerException:
Here's my code:
public class WindsorControllerFactory : DefaultControllerFactory
{
private WindsorContainer container;
// Constructor
// 1. Sets up new IoC container
// 2. Registers all components specified in web.config
// 3. Registers all controller types as components
public WindsorControllerFactory()
{
// Instantiate a container, taking configuration 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);
}
// Construct the controller instance needed to service each request
protected override IController GetControllerInstance(System.Web.Routing.RequestContext requestContext, Type controllerType)
{
return (IController)container.Resolve(controllerType);
}
}
Yes, connection string is fine since it worked before implementing IoC container. I just copied it from the Sql version of the repository example. I'm just not sure why the registration is not occuring...the code is exactly the same as the book plus the
one change for mvc2.
krokonoster
Contributor
4291 Points
1352 Posts
Asp.Net MVC 2 - IoC (Castle Windsor)
Feb 08, 2010 08:37 AM|LINK
I'm trying to set up IoC (Castle Windsor) in my MVC 2 project here, using the section in Pro Asp.net MVC Framework book.
However, I cannot compile after creating a custom controller factory as stated in the book.
This part give me error:
// Constructs the controller instance needed to service each request protected override IController GetControllerInstance(Type controllerType) { return (IController) container.Resolve(controllerType); }Telling me that no suitable method have been found to override?
Does someone know if there's a problem with the code in the book or something changed with recent versions of things (wont suprise me..got some books on MVC here rendered completely useless with the evolution of asp.net mvc)
pumox
Member
12 Points
7 Posts
Re: Asp.Net MVC 2 - IoC (Castle Windsor)
Feb 08, 2010 09:06 AM|LINK
Here is my working WindsorControllerFactory based on the book:
using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.Web.Mvc; using Castle.Windsor; using Castle.Windsor.Configuration.Interpreters; using Castle.Core.Resource; using System.Reflection; namespace WebUI { public class WindsorControllerFactory : DefaultControllerFactory { private WindsorContainer container; public WindsorControllerFactory() { this.container = new WindsorContainer( new XmlInterpreter(new ConfigResource("castle")) ); var controllerTypes = from t in Assembly.GetExecutingAssembly().GetTypes() where typeof(IController).IsAssignableFrom(t) select t; foreach (Type t in controllerTypes) this.container.AddComponentLifeStyle(t.FullName, t, Castle.Core.LifestyleType.Transient); } protected override IController GetControllerInstance(System.Web.Routing.RequestContext requestContext, Type controllerType) { return (IController)this.container.Resolve(controllerType); } } }ali62b
Contributor
4750 Points
690 Posts
Re: Asp.Net MVC 2 - IoC (Castle Windsor)
Feb 08, 2010 09:07 AM|LINK
protected override IController GetControllerInstance(Type controllerType) { return (IController) container.Resolve(controllerType); }to :
protected override IController GetControllerInstance (RequestContext requestContext, Type controllerType) { return (IController)container.Resolve(controllerType); }For more info check out this link :
http://mvcsharp.wordpress.com/2010/01/09/setting-up-ioc-in-asp-net-mvc-using-castle-windsor/
Hope this helps.
@BlueCoder
Regards
krokonoster
Contributor
4291 Points
1352 Posts
Re: Asp.Net MVC 2 - IoC (Castle Windsor)
Feb 08, 2010 12:03 PM|LINK
Yep, that did the trick (my lack of knowledge driving me bananas). Bit of refactoring to keep to the standards:
using System; using System.Collections.Generic; using System.Linq; using System.Reflection; using System.Web.Mvc; using System.Web.Routing; using Castle.Core; using Castle.Core.Resource; using Castle.Windsor; using Castle.Windsor.Configuration.Interpreters; namespace MySite.Web.Core { public class WindsorControllerFactory : DefaultControllerFactory { private readonly WindsorContainer _container; public WindsorControllerFactory() { _container = new WindsorContainer( new XmlInterpreter(new ConfigResource("castle")) ); IEnumerable<Type> controllerTypes = from t in Assembly.GetExecutingAssembly().GetTypes() where typeof (IController).IsAssignableFrom(t) select t; foreach (Type t in controllerTypes) _container.AddComponentWithLifestyle(t.FullName, t, LifestyleType.Transient); } protected override IController GetControllerInstance(RequestContext requestContext, Type controllerType) { return (IController) _container.Resolve(controllerType); } } }krokonoster
Contributor
4291 Points
1352 Posts
Re: Asp.Net MVC 2 - IoC (Castle Windsor)
Feb 08, 2010 12:37 PM|LINK
Yikes...Now I'm stuck as I'm running with medium trust (as I'm on shared hosting) and Castle dont like that.
Seems the only way is to compile Castle myself, a thought that put me off...maybe I should try a different IoC Container....
krokonoster
Contributor
4291 Points
1352 Posts
Re: Asp.Net MVC 2 - IoC (Castle Windsor)
Feb 09, 2010 01:03 AM|LINK
SoftSysHosting Rocks!
titaniumtomm...
Member
4 Points
4 Posts
Re: Asp.Net MVC 2 - IoC (Castle Windsor)
Mar 09, 2010 06:06 PM|LINK
Hi, I'm doing the same example with MVC 2 as well and I've tried the above solution and still run into this exception:
Castle.MicroKernel.Handlers.HandlerException was unhandled by user code
Message=Can't create component 'WebUI.Controllers.ProductsController' as it has dependencies to be satisfied.
WebUI.Controllers.ProductsController is waiting for the following dependencies:
Services:
- DomainModel.Abstract.IProductsRepository which was not registered.
Source=Castle.MicroKernel
StackTrace:
at Castle.MicroKernel.Handlers.DefaultHandler.AssertNotWaitingForDependency()
at Castle.MicroKernel.Handlers.DefaultHandler.ResolveCore(CreationContext context, Boolean track)
at Castle.MicroKernel.Handlers.AbstractHandler.Resolve(CreationContext context)
at Castle.MicroKernel.DefaultKernel.ResolveComponent(IHandler handler, Type service, IDictionary additionalArguments)
at Castle.MicroKernel.DefaultKernel.ResolveComponent(IHandler handler, Type service)
at Castle.MicroKernel.DefaultKernel.get_Item(Type service)
at Castle.Windsor.WindsorContainer.Resolve(Type service)
at WindsorControllerFactory.GetControllerInstance(RequestContext requestContext, Type controllerType) in C:\Users\tommysu\documents\visual studio 2010\Projects\ShoppyTown\WebUI\WindsorControllerFactory.cs:line 36
at System.Web.Mvc.DefaultControllerFactory.CreateController(RequestContext requestContext, String controllerName)
at System.Web.Mvc.MvcHandler.ProcessRequestInit(HttpContextBase httpContext, IController& controller, IControllerFactory& factory)
at System.Web.Mvc.MvcHandler.BeginProcessRequest(HttpContextBase httpContext, AsyncCallback callback, Object state)
at System.Web.Mvc.MvcHandler.BeginProcessRequest(HttpContext httpContext, AsyncCallback callback, Object state)
at System.Web.Mvc.MvcHandler.System.Web.IHttpAsyncHandler.BeginProcessRequest(HttpContext context, AsyncCallback cb, Object extraData)
at System.Web.HttpApplication.CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute()
at System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously)
InnerException:
Here's my code:
public class WindsorControllerFactory : DefaultControllerFactory { private WindsorContainer container; // Constructor // 1. Sets up new IoC container // 2. Registers all components specified in web.config // 3. Registers all controller types as components public WindsorControllerFactory() { // Instantiate a container, taking configuration 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); } // Construct the controller instance needed to service each request protected override IController GetControllerInstance(System.Web.Routing.RequestContext requestContext, Type controllerType) { return (IController)container.Resolve(controllerType); } }With my web.config:
<configuration> <configSections> <section name="castle" type="Castle.Windsor.Configuration.AppDomain.CastleSectionHandler,Castle.Windsor" /> </configSections> <castle> <components> <component id="ProductsRepository" services="DomainModel.Abstract.IProductsRepository,DomainModel" type="DomainModel.Concrete.SqlProductsRepository,DomainModel"> <parameters> <connectionString>Server=.;Database=SportsStore;Trusted_Connection=yes;</connectionString> </parameters> </component> </components> </castle> <system.web> .....It's basically the example in the book line for line with the modification for MVC 2 but I still hit the exception...any ideas?
ali62b
Contributor
4750 Points
690 Posts
Re: Asp.Net MVC 2 - IoC (Castle Windsor)
Mar 10, 2010 02:04 PM|LINK
Are you sure your connection string is true ? did you use express edition or not ?
@BlueCoder
Regards
titaniumtomm...
Member
4 Points
4 Posts
Re: Asp.Net MVC 2 - IoC (Castle Windsor)
Mar 10, 2010 07:00 PM|LINK
Yes, connection string is fine since it worked before implementing IoC container. I just copied it from the Sql version of the repository example. I'm just not sure why the registration is not occuring...the code is exactly the same as the book plus the one change for mvc2.
bradleylandi...
Member
233 Points
109 Posts
Re: Asp.Net MVC 2 - IoC (Castle Windsor)
Apr 22, 2010 02:48 PM|LINK
In your castle config change "services=" to "service=".