【问题标题】:ASP.NET MVC with WEB.API and Castle Windsor container带有 WEB.API 和 Castle Windsor 容器的 ASP.NET MVC
【发布时间】:2016-07-26 08:46:09
【问题描述】:

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

温莎城堡整合:

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" };
   }
}

【问题讨论】:

    标签: c# asp.net-mvc asp.net-web-api


    【解决方案1】:

    问题在于,由于 MVC 和 Web API 控制器是独立的实体,因此您需要对两者进行 Windsor 配置。您已将 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();
            }
        }
    }
    

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

    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());
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-05-16
      • 1970-01-01
      • 2014-11-11
      相关资源
      最近更新 更多