22

Castle Windsor を使用する MVC4 サイトに WebAPI 呼び出しを追加したいので、インターウェブについて少し調べてみました。

今、私は IoC の内外を知りません。プロジェクトでキャッスル ウィンザーをセットアップする方法のチュートリアルに従い、ベース コントローラーにIUnitOfWorkFactoryIApplicationServiceをパブリック プロパティとして挿入し、コントローラー コンストラクターで必要に応じて他のいくつかのインターフェイスを挿入しました。それはスムーズに動作するので、それ以上のことをする必要はありませんでした.

私が WebAPI について読んでいるどこでも、DI はキャッスル ウィンザーを使用してうまく機能しないと言われており、IDependencyResolverとの問題について話していIDependencyScopeます。この問題を回避する方法にはいくつかの回避策と実装がありますが、私には明確ではないのは、問題が正確に何であるかです。コード スニペットが含まれていますが、それらがどのクラスに属し、どのように呼び出されるかを知っていることを前提としていますが、残念ながら私にはわかりません。さらに、私がオンラインで見たすべての例は、排他的な WebAPI プロジェクトを参照しており、いくつかの s が慎重に投入された MVC4 プロジェクトではApiControllerありません。

標準コントローラーで使用しているものが API コントローラーでは機能しないのはなぜですか? 同じアプリケーションで WebAPI 呼び出しと標準の Web 呼び出しを機能させるには、どのようなコード アクロバットを行う必要がありますか?

4

4 に答える 4

13

既存のキャッスル ウィンザー 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. 必要なアダプターの実装は次のとおりです。

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 キャッスル ウィンザー コンテナーの実装を使用すると、それを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" };
    }
}
于 2014-09-27T14:50:52.520 に答える
6

次のサンプル プロジェクトは、私が探していた答えを与えてくれました。依存性注入に Castle Windsor を使用します。同じアプリケーションで Web API コントローラーと一緒に MVC コントローラーを使用することができました。

ミラジャヴォラ / WebAPISample


詳細を説明した投稿は次のとおりです。

ASP.NET Web API の概要

于 2013-10-26T23:41:48.663 に答える
1

最初に Iko が述べたように、実装するクラスを作成する必要がありますIHttpControllerActivator

次に、以下ContainerBootstrapperBootstrap()追加して、デフォルトを実装されたものに置き換えます。

 //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()    
);
于 2018-08-12T08:54:47.430 に答える