Castle Windsor ApiController Factory implementation for ASP.NET Web API

前端 未结 6 1949
傲寒
傲寒 2020-12-16 03:07

I know it\'s possible to use DependencyResolver and register Castle Windsor with MVC but due to the issues described in https://stackoverflow.com/a/4889222/139392 we have st

6条回答
  •  长情又很酷
    2020-12-16 04:10

    Thanks to Critiano's post and some searching on-line I managed to get it to work here's the code for anyone else having this issue. I've fgot it working with MVC3 and ASP.NET Web Api Beta but I think the same solution should work for MVC4.

    Firstly I created a WindsorHttpControllerFactory as the ApiControllers use a different factory than the MVC ones.

    public class WindsorHttpControllerFactory : IHttpControllerFactory
    {
        private readonly IKernel kernel;
        private readonly HttpConfiguration configuration;
    
        public WindsorHttpControllerFactory(IKernel kernel, HttpConfiguration configuration)
        {
            this.kernel = kernel;
            this.configuration = configuration;
        }
    
        public IHttpController CreateController(HttpControllerContext controllerContext, string controllerName)
        {
            if (controllerName == null)
            {
                throw new HttpException(404, string.Format("The controller for path '{0}' could not be found.", controllerContext.Request.RequestUri.AbsolutePath));
            }
    
            var controller = kernel.Resolve(controllerName);
            controllerContext.Controller = controller;
            controllerContext.ControllerDescriptor = new HttpControllerDescriptor(configuration, controllerName, controller.GetType());
    
            return controllerContext.Controller;
        }
    
        public void ReleaseController(IHttpController controller)
        {
            kernel.ReleaseComponent(controller);
        }
    }
    

    The tricky part was registration it seems to involved registering a whole bunch of other stuff. This is what I ended up with.

    container.Register(Component.For().ImplementedBy().LifeStyle.Singleton);
    container.Register(Component.For().ImplementedBy().LifeStyle.Singleton);
    container.Register(Component.For().ImplementedBy().LifeStyle.Singleton);
    container.Register(Component.For().ImplementedBy().LifeStyle.Transient);
    container.Register(Component.For().ImplementedBy().LifeStyle.Transient);
    container.Register(Component.For().ImplementedBy().LifeStyle.Transient);
    container.Register(Component.For().ImplementedBy().LifeStyle.Transient);
    container.Register(Component.For().ImplementedBy().LifeStyle.Transient);
    container.Register(Component.For().Instance(configuration));
    
    //Register all api controllers
    container.Register(AllTypes.FromAssembly(assemblyToRegister)
                                .BasedOn()
                                .Configure(registration => registration.Named(registration.ServiceType.Name.ToLower().Replace("controller", "")).LifeStyle.Transient));
    
    //Register WindsorHttpControllerFactory with Service resolver
    GlobalConfiguration.Configuration.ServiceResolver.SetService(typeof(IHttpControllerFactory), container.Resolve());
    

    I had to create my own implementation of an ILogger you could use a stub version like bellow.

    public class MyLogger : System.Web.Http.Common.ILogger
    {
        public void LogException(string category, TraceLevel level, Exception exception)
        {
            // Do some logging here eg. you could use log4net
        }
    
        public void Log(string category, TraceLevel level, Func messageCallback)
        {
            // Do some logging here eg. you could use log4net
        }
    }
    

提交回复
热议问题