Castle Windsorを使用しているMVC4サイトにWebAPI呼び出しを追加したいので、インターウェブについて少し調べてみます。
今、私はIoCの内外を知りません。プロジェクトにCastle Windsorをセットアップする方法のチュートリアルに従い、IUnitOfWorkFactory
とIApplicationService
をベースコントローラーのパブリックプロパティとして注入し、コントローラーコンストラクターで必要に応じて他のいくつかのインターフェイスを注入しました。 。それは水泳で機能するので、私はそれでこれ以上何もする必要がありませんでした。
WebAPIで読んでいるところはどこでも、Castle Windsorを使用するとDIがうまく機能しないと言われ、IDependencyResolver
とIDependencyScope
の問題について話します。この問題を回避する方法にはいくつかの回避策と実装がありますが、私には明確ではないのは問題が何であるかです。コードスニペットは含まれていますが、想定されているのは、それらがどのクラスに属していて、どのように呼び出されているかを知っているということです。さらに、私がオンラインで見たすべての例は、独占的なWebAPIプロジェクトを参照しており、いくつかのApiController
sが賢明に投げ込まれたMVC4プロジェクトを参照していません。
標準コントローラーで使用しているものがAPIコントローラーで使用できないのはなぜですか? WebAPI呼び出しと標準のWeb呼び出しを同じアプリケーションで機能させるには、どのような種類のコードアクロバットが必要ですか?
Windapiをwebapiで使用するには、次のようにしてください http://blog.ploeh.dk/2012/10/03/DependencyInjectioninASP.NETWebAPIwithCastleWindsor/ (BEH:fixed link)
同じアプリでwebapiとMVCコントローラーを使用できますが(別々にしておくことをお勧めします)、ルーティングとコントローラーファクトリは異なり、2つの異なる構成をセットアップしてルーティングの重複を処理する必要があります... MVCとウィンザーの場合は、すごい
Castle Windsor MVCチュートリアル と同様にMVCとCastle Windsorをセットアップしていると仮定すると、IoCを追加して、依存関係注入を利用するWeb APIコントローラーを取得するのは Mark Seemannの投稿(IDependencyResolverを使用しない理由を説明していることに注意してください)。
Castle Windsorチュートリアルの_Global.asax.cs
_には、次のようなものが含まれているはずです。
_ private static IWindsorContainer container;
protected void Application_Start()
{
//... MVC / Web API routing etc.
BootStrapper bs = new BootStrapper();
container = bs.ConfigureCastleWindsorMVC();
}
_
BootStrapper.ConfigureCastleWindsorMVC()
切り取り
_ IWindsorContainer container = new WindsorContainer()
.Install(
new LoggerInstaller()
//...,
, new ControllersInstaller()
);
var controllerFactory = new WindsorControllerFactory(container.Kernel);
ControllerBuilder.Current.SetControllerFactory(controllerFactory);
return container;
_
Mark Seemannの投稿から、IHttpControllerActivator
を通じてWeb APIの entry point(Composition Root) にアクセスする必要があります。ここにあなたが必要とする彼のアダプター実装があります。
_public class WindsorCompositionRoot : IHttpControllerActivator
{
private readonly IWindsorContainer container;
public WindsorCompositionRoot(IWindsorContainer container)
{
this.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) { this.release = release; }
public void Dispose()
{
this.release();
}
}
}
_
IHttpControllerActivatorアダプターとMVC Castle Windsorコンテナーの実装では、_Global.asax.cs
_(または、使用した場合はBootStrapper)で構成するだけです。 MVC初期化にはすべてのインストーラーがあるため、MVC初期化の後にする必要があります。
_ private static IWindsorContainer container;
protected void Application_Start()
{
// MVC / Web API routing etc.
BootStrapper bs = new BootStrapper();
container = bs.ConfigureCastleWindsorMVC();
// Web API Castle Windsor ++ ADD THIS ++
GlobalConfiguration.Configuration.Services.Replace(
typeof(IHttpControllerActivator),
new WindsorCompositionRoot(container));
}
_
Web APIコントローラーは、MVCコントローラーと同じように、注入された依存関係を使用できます。
_public class TestController : ApiController
{
private readonly ITestService TestService;
public TestController(ITestService testService)
{
this.TestService = testService;
}
// GET api/<controller>
public IEnumerable<string> Get()
{
return TestService.GetSomething();
//return new string[] { "value1", "value2" };
}
}
_
次のサンプルプロジェクトは、私が探していた答えをくれました。依存関係の注入にCastle Windsorを使用します。同じアプリケーションでWeb APIコントローラーと一緒にMVCコントローラーを使用できました。
詳細は次のとおりです。
最初にIkoが述べたように、IHttpControllerActivator
を実装するクラスを作成する必要があります。
次に、ContainerBootstrapper
のBootstrap()
に以下を追加します。デフォルトを実装されたものに置き換えます。
_ //This will help in creating Web api with Dependency injection
GlobalConfiguration.Configuration.Services.Replace(
typeof(IHttpControllerActivator),
new WindsorCompositionRoot(container));
_
最後に、ここでは触れていませんが、それがなければ私は機能しませんでした。IWindsorInstaller
サービスをinstall()
内に実装して、次のコードを追加する必要があります。
_container.Register(
Classes.FromThisAssembly()
.BasedOn<ApiController>()
.LifestyleTransient()
);
_