web-dev-qa-db-ja.com

SimpleInjector-コントローラーに本番環境でパラメーターのないパブリックコンストラクターがあることを確認してください

私は奇妙な状況で立ち往生しています。私はOnion Architectureをフォローしていますが、私のアーキテクチャは次のようなものです。

1-Core
     - Domain Classes
     - Repository Interfaces
     - Service Interfaces
2-Infrastructure
     - Data
     - Dependency Injection // Here I am using Simple Injector as dependency injection
     - Repository Interfaces Implementation
     - Service Interfaces Implementation
3-WebApi
     - Web Api Project
4-WebClient
     - My AngularJs App
5-Test
     - Test Project

依存性注入:

[Assembly: PreApplicationStartMethod(typeof(IocConfig), "RegisterDependencies")]
namespace Infrastructure.DependencyResolution
{
    public class IocConfig
    {
        public static void RegisterDependencies()
        {
            var container = new Container();

            container.RegisterWebApiRequest<IRepositoryAsync<Category>, Repository<Category>>();
            container.RegisterWebApiRequest<ICategoryService, CategoryService>();
            container.RegisterWebApiRequest<IDataContextAsync>(() => new MyContext());
            container.Verify();
            GlobalConfiguration.Configuration.DependencyResolver =
            new SimpleInjectorWebApiDependencyResolver(container);

        }
    }
}

Web Apiプロジェクト:

public class HomeController : ApiController
{
    private readonly ICategoryService _categoryService;
    public HomeController(ICategoryService categoryService)
    {
        _categoryService = categoryService;
    }
}

私のlocal IISではすべてが正常に機能しています。しかし今、私はこのアプリケーションを本番サーバーに公開しました、そして今それは私に以下のエラーを与えています:

{"message": "エラーが発生しました。"、 "exceptionMessage": "タイプ 'HomeController'のコントローラーを作成しようとしたときにエラーが発生しました。コントローラーにパラメーターのないパブリックコンストラクターがあることを確認してください。"、 "exceptionType": "System.InvalidOperationException"、 "stackTrace": "at System.Web.Http.Dispatcher.DefaultHttpControllerActivator.Create(HttpRequestMessage request、HttpControllerDescriptor controllerDescriptor、Type controllerType)\ r\n at System.Web.Http.Controllers.HttpControllerDescriptor.CreateController( HttpRequestMessageリクエスト)\ r\nSystem.Web.Http.Dispatcher.HttpControllerDispatcher.d__1.MoveNext() "、" innerException ":{" message ":"エラーが発生しました。 "、" exceptionMessage ":" Type'JetAdz .WebApi.Controllers.HomeController 'には、System.Linq.Expressions.Expression.New(Type type)\ r\nのデフォルトのコンストラクター "、" exceptionType ":" System.ArgumentException "、" stackTrace ":"がありません。 .Web.Http.Internal.TypeActivator.Create [TBase](Type instanceType)\ r\n at System.Web.Http.Dispatcher.D efaultHttpControllerActivator.GetInstanceOrActivator(HttpRequestMessage request、Type controllerType、Func`1&activator)\ r\n at System.Web.Http.Dispatcher.DefaultHttpControllerActivator.Create(HttpRequestMessage request、HttpControllerDescriptor controllerDescriptor、Type controllerType) "}}

5
Usman Khalid

スローされた例外の内部例外を確認してください。これが発生している理由を説明する詳細が含まれています。

ここには複数の問題があります。 すべてのルートタイプを明示的に登録するコンテナに確認する必要があります。コントローラーは直接解決されるため、ルートタイプです(コントローラーに依存するものはありませんが、依存関係があります)。明示的に登録しないと、コンテナはVerify()を呼び出したときに作成できるかどうかを確認できません。以下を呼び出すことにより、コントローラーを登録できます。

_container.RegisterWebApiControllers(GlobalConfiguration.Configuration);
_

これは ドキュメント で説明されています。

これを行った後、アプリケーションの起動時にVerify()メソッドが失敗するのを直接確認できます。この場合、何が問題になっているのかを説明する非常に詳細なメッセージが表示されます。

内部例外から、Web APIの_DefaultHttpControllerActivator.GetInstanceOrActivator_メソッドがTypeActivator.Create<T>(Type)を呼び出していることがわかります。これは、request.GetDependencyScope().GetService(controllerType)の呼び出しがnullを返す場合にのみ発生します。ただし、これは通常、SimpleInjectorWebApiDependencyResolverをWebAPIパイプラインにフックした場合には発生しないものです。これは、SimpleInjectorWebApiDependencyResolverの実装を解決するように要求されたときに、nullIHttpControllerを返さないためです。代わりに、コントローラーを解決できない場合に例外がスローされます。

したがって、これは、アプリケーションのバインディングリダイレクトの問題を示しています。これは、SimpleInjector.Integration.WebApi.dllが、アプリケーションが使用しているものとは異なるIHttpControllerバージョンを参照していることを意味します。バインディングリダイレクトはこれを解決することを目的としているため、アプリケーションに正しいバインディングがあることを確認してください。 System.Web.Http.dllの場合、次のようになります(ただし、他のバインディングも必要になる場合があることに注意してください)。

_<runtime>
  <assemblyBinding xmlns="urn:schemas-Microsoft-com:asm.v1">
    ... 
    <dependentAssembly>
      <assemblyIdentity name="System.Web.Http" publicKeyToken="31bf3856ad364e35" 
          culture="neutral" />
      <bindingRedirect oldVersion="0.0.0.0-5.2.3.0" newVersion="5.2.3.0" />
    </dependentAssembly>
  </assemblyBinding>
</runtime>
_

通常、バインディングはNuGetパッケージマネージャーによって管理されますが、定期的に管理することはできません。

バインディングリダイレクトの問題が修正されると、内部例外に、Verify()を呼び出したときに表示されるのと同じ情報を持つSimpleInjectorからの情報が含まれていることがわかります。

9
Steven

WebApiの正しいDependencyResolverを登録していません。 WebApi依存性注入ページ および Simple Injector WebApiページ によると、このように実行されることになっています。

public static void Register(HttpConfiguration config)
{
    var container = new Container();

    container.RegisterWebApiRequest<IRepositoryAsync<Category>, Repository<Category>>();
    container.RegisterWebApiRequest<ICategoryService, CategoryService>();
    container.RegisterWebApiRequest<IDataContextAsync>(() => new MyContext());
    container.Verify();

    config.DependencyResolver = new SimpleInjectorWebApiDependencyResolver(container);

    // Other Web API configuration not shown.
}

示した構成は、MVC依存性注入用です(これも必要になる場合があります)。

7
NightOwl888

SpringXMLファイルを使用して変数をクラスに挿入します。私の場合、新しいコントローラーを作成したときのコピー/貼り付けのバグでした。

したがって、これはOPの問題とは正確には関連していませんが、同じエラーメッセージが表示され、他の誰かを助けます。

コピーしました(山括弧が角括弧に変更されました):

[object id="className" type="Project.ClassName" scope="request"]
    [constructor-arg name="OtherClassName" ref="otherclassName"/]
[/object]

私が必要としたのは:

[object id="className" type="Project.ClassName" scope="request"]
    [property name="OtherClassName" ref="otherclassName"/]
[/object]

注意してください プロパティ の代わりに コンストラクター引数

私のクラスにはパラメーターを探すコンストラクターがなかったからです。

0
isopropanol

私にとっては、SimpleInjectorInitializer.Initialize();Application_Start()に追加するのを忘れただけでした。

私は通常、最近_App_Start_フォルダーにSimpleInjectorInitializerクラスを作成し、その中でcontainer.Verify()およびGlobalConfiguration.Configuration.DependencyResolver = new SimpleInjectorWebApiDependencyResolver(container);呼び出しを行います。すべての型登録などを行うGetInitializeContainer()メソッドを呼び出した後。

0
Scott Fraley