I have setup Castle Windsor and WebApi after reading about it in the below 2 posts. Here is my a highlight of my setup:
Reference Posts:
- How do I get Web API / Castle Windsor to recognize a Controller?
- Dependency Injection in WebAPI with Castle Windsor
Code Setup:
public static class GlassMapperScCustom
{
public static void CastleConfig(IWindsorContainer container)
{
container.AddFacility<TypedFactoryFacility>();
var config = new Config
{
UseWindsorContructor = true
};
//MVC
container.Register(Component.For<SitecoreController>().LifestyleTransient());
container.Register(Types.FromThisAssembly().BasedOn<Controller>().LifestyleTransient());
DependencyResolver.SetResolver(new WindsorMvcDependencyResolver(container));
ControllerBuilder.Current.SetControllerFactory(new WindsorMvcControllerFactory(container.Kernel));
//WebApiInstaller
container.Register(Types.FromThisAssembly().BasedOn<ApiController>().LifestyleTransient());
var resolver = new WindsorResolver(container); //Shown Below
GlobalConfiguration.Configuration.DependencyResolver = resolver;
GlobalConfiguration.Configuration.Services.Replace(typeof(IHttpControllerActivator), new WindsorWebApiControllerActivator(resolver));
}
}
public class WindsorMvcDependencyResolver : IDependencyResolver
{
private readonly IWindsorContainer _container;
public WindsorMvcDependencyResolver(IWindsorContainer container)
{
if (container == null) throw new ArgumentNullException("container");
_container = container;
}
public object GetService(Type serviceType)
{
return _container.Kernel.HasComponent(serviceType) ? _container.Resolve(serviceType) : null;
}
public IEnumerable<object> GetServices(Type serviceType)
{
return _container.ResolveAll(serviceType).Cast<object>().ToArray();
}
}
public class WindsorMvcControllerFactory : DefaultControllerFactory
{
private readonly IKernel _kernel;
public WindsorMvcControllerFactory(IKernel kernel)
{
this._kernel = kernel;
}
public override void ReleaseController(IController controller)
{
_kernel.ReleaseComponent(controller);
}
protected override IController GetControllerInstance(RequestContext requestContext, Type controllerType)
{
if (controllerType == null)
{
throw new HttpException(404, string.Format("The controller for path '{0}' could not be found.",
requestContext.HttpContext.Request.Path));
}
return (IController)_kernel.Resolve(controllerType);
}
}
internal class WindsorResolver : IDependencyResolver, IDependencyScope, IDisposable
{
private readonly IWindsorContainer _container;
public WindsorResolver(IWindsorContainer container)
{
this._container = container;
}
public IDependencyScope BeginScope()
{
return new WindsorDependencyScope(this._container);
}
public void Dispose()
{
this._container.Dispose();
}
public object GetService(Type serviceType)
{
if (!this._container.Kernel.HasComponent(serviceType))
return (object)null;
else
return this._container.Resolve(serviceType);
}
public IEnumerable<object> GetServices(Type serviceType)
{
if (!this._container.Kernel.HasComponent(serviceType))
return (IEnumerable<object>)new object[0];
else
return Enumerable.Cast<object>((IEnumerable)this._container.ResolveAll(serviceType));
}
}
public class WindsorWebApiControllerActivator : IHttpControllerActivator
{
private readonly IDependencyResolver _container;
public WindsorWebApiControllerActivator(IDependencyResolver container)
{
_container = container;
}
public IHttpController Create(HttpRequestMessage request, HttpControllerDescriptor controllerDescriptor, Type controllerType)
{
var scope = _container.BeginScope();
var controller = (IHttpController)scope.GetService(controllerType);
request.RegisterForDispose(scope);
return controller;
}
}
//WebApiConfig.cs
public static class WebApiConfig
{
public static void Start()
{
GlobalConfiguration.Configure(WebApiConfig.Register);
}
public static void Register(HttpConfiguration config)
{
// initialize and map all attribute routed Web API controllers (note: this does not enable MVC attribute routing)
config.MapHttpAttributeRoutes();
config.EnsureInitialized();
//config.Routes.MapHttpRoute(
// name: "DefaultApi",
// routeTemplate: "api/{controller}/{id}",
// defaults: new {id = RouteParameter.Optional});
// force JSON responses only (no XML)
config.Formatters.Clear();
config.Formatters.Add(new JsonMediaTypeFormatter());
}
}
//Global.asax.cs
public class MvcApplication : Sitecore.Web.Application
{
public static void RegisterGlobalFilters(GlobalFilterCollection filters)
{
filters.Add(new HandleErrorAttribute());
}
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
}
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
RegisterGlobalFilters(GlobalFilters.Filters);
RegisterRoutes(RouteTable.Routes);
}
}
If I add a test ApiController and try to go to '/api/Test' it gives me a 404 everytime. I used RouteDebugger to view whats wrong and I get the below error everytime:
public IEnumerable<string> Get()
{
return new string[] { "value1", "value2" };
}
public string Get(int id)
{
return "value";
}
I am not sure where "api/sitecore" is coming from. I followed the instructions on [WebApi2 Attribute Routing with Sitecore][1] post as well but unable to get it working. Can someone point me to what I am doing wrong?