2016-07-25 48 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());