2016-07-25 44 views
0

我有集成了Castle Windsor容器的ASP.NET MVC应用程序。当我添加ApiController并尝试执行POST时,出现错误消息:“确保控制器具有无参数公共构造函数。”感谢您的任何建议。带有WEB.API和Castle Windsor容器的ASP.NET MVC

温莎城堡集成:

public class CastleControllerFactory : DefaultControllerFactory 
{ 
    public IWindsorContainer Container { get; protected set; } 

    public CastleControllerFactory(IWindsorContainer container) 
    { 
     if (container == null) 
     { 
      throw new ArgumentException("container"); 
     } 

     this.Container = container; 
    }   

    protected override IController GetControllerInstance(RequestContext requestContext, Type controllerType) 
    { 
     if (controllerType == null) 
     { 
      return null; 
     } 

     return Container.Resolve(controllerType) as IController; 

    }    

    public override void ReleaseController(IController controller) 
    { 
     var disposableController = controller as IDisposable; 
     if (disposableController != null) 
     { 
      disposableController.Dispose(); 
     } 

     Container.Release(controller); 
    } 
} 

public class DefaultCastleInstaller : IWindsorInstaller 
{ 
    public void Install(IWindsorContainer container, IConfigurationStore store) 
    { 
     container.AddFacility<TypedFactoryFacility>(); 

     //Functions 
     //container.Register(Component.For<IGetIPAddressesFromRange>().ImplementedBy<GetIPAddressesFromRange>().LifestylePerWebRequest()); 
     container.Register(Component.For<IUnitOfWork>().ImplementedBy<UnitOfWork>().LifestylePerWebRequest()); 

     var contollers = Assembly.GetExecutingAssembly().GetTypes().Where(x => x.BaseType == typeof(Controller)).ToList(); 
     foreach (var controller in contollers) 
     { 
      container.Register(Component.For(controller).LifestyleTransient()); 
     } 

     var apiContollers = Assembly.GetExecutingAssembly().GetTypes().Where(x => x.BaseType == typeof(ApiController)).ToList(); 
     foreach (var apiController in apiContollers) 
     { 
      container.Register(Component.For(apiController).LifestyleTransient()); 
     } 
    } 
} 

public class MvcApplication : System.Web.HttpApplication 
{ 
    protected void Application_Start() 
    { 
     AreaRegistration.RegisterAllAreas(); 
     GlobalConfiguration.Configure(WebApiConfig.Register); 
     FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters); 
     RouteConfig.RegisterRoutes(RouteTable.Routes); 
     BundleConfig.RegisterBundles(BundleTable.Bundles); 

     //Integrace CastleWindsor 
     var container = new WindsorContainer(); 
     container.Install(new DefaultCastleInstaller()); 
     var castleControllerFactory = new CastleControllerFactory(container); 
     ControllerBuilder.Current.SetControllerFactory(castleControllerFactory); 
    } 
} 

ApiController:

public class UserVerificationController : ApiController 
{ 
    private readonly IUnitOfWork _unitOfWork; 

    /// <summary> 
    /// Konstruktor 
    /// </summary> 
    /// <param name="unitOfWork"></param> 
    public UserVerificationController(IUnitOfWork unitOfWork) 
    { 
     _unitOfWork = unitOfWork; 
    } 

    // GET api/<controller> 
    public IEnumerable<string> Get() 
    { 
     return new string[] { "value1", "value2" }; 
    } 
} 

回答

0

的问题是,由于MVC和Web API控制器是独立的实体,您需要两个温莎配置。您已将Windsor配置为创建您的MVC控制器。您只需要为您的Web API控制器使用相同的功能。

这是一个Web API控制器激活器,主要从this blog post中解除。

public class WindsorWebApiControllerActivator : IHttpControllerActivator 
{ 
    private readonly IWindsorContainer _container; 

    public WindsorWebApiControllerActivator(IWindsorContainer container) 
    { 
     _container = container; 
    } 

    public IHttpController Create(
     HttpRequestMessage request, 
     HttpControllerDescriptor controllerDescriptor, 
     Type controllerType) 
    { 
     var controller = 
      (IHttpController)this._container.Resolve(controllerType); 

     request.RegisterForDispose(
      new Release(
       () => this._container.Release(controller))); 

     return controller; 
    } 

    private class Release : IDisposable 
    { 
     private readonly Action _release; 

     public Release(Action release) 
     { 
      _release = release; 
     } 

     public void Dispose() 
     { 
      _release(); 
     } 
    } 
} 

而且您需要在容器中注册所有控制器类型。这里有一个IWindsorInstaller是注册所有MVC 的Web API控制器:

public class ControllersInstaller : IWindsorInstaller 
{ 
    public void Install(IWindsorContainer container, IConfigurationStore store) 
    { 
     container.Register(
      Classes. 
       FromThisAssembly(). 
       BasedOn<IController>(). //MVC 
       If(c => c.Name.EndsWith("Controller")). 
       LifestyleTransient()); 

     container.Register(
      Classes. 
       FromThisAssembly(). 
       BasedOn<IHttpController>(). //Web API 
       If(c => c.Name.EndsWith("Controller")). 
       LifestyleTransient()); 
    } 
} 

然后在启动时你替换默认的Web API控制器激活:

GlobalConfiguration.Configuration.Services.Replace(
    typeof(IHttpControllerActivator), 
    new WindsorWebApiControllerActivator(container)); 

,并确保调用安装程序:

container.Install(new ControllersInstaller());