コントローラーにパラメーターのないパブリックコンストラクターエラーがあることを確認してください


105

追加のコンストラクターを持つように変更するまで、私はこのチュートリアルを素晴らしく機能しましたDbContext。私は現在、解決策に問題があり、これを修正するために何をすべきかわかりません。パラメータなしのコンストラクタを取得するように強制する簡単な方法はありますか、またはこれに間違ってアプローチしていますか?

DbContext 2つのコンストラクター:

public class DashboardDbContext : DbContext
{
    public DashboardDbContext() : base("DefaultConnection") { }

    public DashboardDbContext(DbConnection dbConnection, bool owns)
        : base(dbConnection, owns) { }
}

SiteController コンストラクタ:

private readonly IDashboardRepository _repo;

public SiteController(IDashboardRepository repo)
{
    _repo = repo;
}

リポジトリ:

DashboardDbContext _context;

public DashboardRepository(DashboardDbContext context)
{
    _context = context;
}

UnityResolver コード:

public class UnityResolver : IDependencyResolver
{
    private readonly IUnityContainer _container;

    public UnityResolver(IUnityContainer container)
    {
        _container = container;
    }

    public object GetService(Type serviceType)
    {
        try
        {
            return _container.Resolve(serviceType);
        }
        catch (ResolutionFailedException)
        {
            return null;
        }
    }

    public IEnumerable<object> GetServices(Type serviceType)
    {
        try
        {
            return _container.ResolveAll(serviceType);
        }
        catch (ResolutionFailedException)
        {
            return new List<object>();
        }
    }

    public IDependencyScope BeginScope()
    {
        var child = _container.CreateChildContainer();
        return new UnityResolver(child);
    }

    public void Dispose()
    {
        _container.Dispose();
    }
}

WebApiConfig:

var container = new UnityContainer();
container.RegisterType<IDashboardRepository, DashboardRepository>(new HierarchicalLifetimeManager());
config.DependencyResolver = new UnityResolver(container);

WebApi呼び出しからのエラー:

System.InvalidOperationException:タイプ「SiteController」のコントローラーを作成しようとしたときにエラーが発生しました。コントローラにパラメータのないパブリックコンストラクタがあることを確認してください。

at System.Web.Http.Dispatcher.DefaultHttpControllerActivator.Create(HttpRequestMessage request, HttpControllerDescriptor controllerDescriptor, Type controllerType) 
at System.Web.Http.Controllers.HttpControllerDescriptor.CreateController(HttpRequestMessage request) 
at System.Web.Http.Dispatcher.HttpControllerDispatcher.SendAsyncCore(HttpRequestMessage request, CancellationToken cancellationToken) 
at System.Web.Http.Dispatcher.HttpControllerDispatcher.<SendAsync>d__0.MoveNext()

InnerException:System.ArgumentException:タイプ 'Dashboard.Web.Controllers.SiteController'にはデフォルトのコンストラクターがありません。

at System.Linq.Expressions.Expression.New(Type type) 
at System.Web.Http.Internal.TypeActivator.Create[TBase](Type instanceType) 
at System.Web.Http.Dispatcher.DefaultHttpControllerActivator.GetInstanceOrActivator(HttpRequestMessage request, Type controllerType, Func`1& activator) 
at System.Web.Http.Dispatcher.DefaultHttpControllerActivator.Create(HttpRequestMessage request, HttpControllerDescriptor controllerDescriptor, Type controllerType)

チュートリアルは素晴らしく、2番目のコンストラクターを追加するまではうまく機能していました。


2
エラーは、それSiteControllerがでなく、パラメータなしのコンストラクタを持つ必要があることを示していDashboardDbContextます。
Neil Smith

こんにちはSmith.h.Neilですが、追加のコンストラクターがdbcontextに追加されたときにのみ、このエラーがスローされます。それを削除するか、コメントアウトすると(2番目のコンストラクター)、正常に動作します。
scarpacci 2014年

のコンストラクタを見ることができますSiteControllerか?
Neil Smith

そして、私はあなたがDbContextリポジトリに注入していると思いますか?
Neil Smith

@scarpacci行っている唯一の変更は、DbContextから2番目のコンストラクタを削除することですか?2番目のDbContextコンストラクターがないことでコントローラーのインスタンス化をバイパスしているのでない限り、エラーがDbContextのコンストラクターに依存していることは意味がありません。
Asad Saeeduddin 2014年

回答:


130

起こっているのは、あなたがこの問題に噛まれているということです。基本的に、何が起こったのかは、コントローラーをコンテナーに明示的に登録しなかったことです。Unityは未登録の具象型を解決しようとしますが、(構成のエラーが原因で)解決できないため、nullを返します。IDependencyResolver契約のためにWeb APIがnullを強制するため、nullを強制的に返します。Unityはnullを返すため、Web APIはコントローラー自体を作成しようとしますが、デフォルトのコンストラクターがないため、「コントローラーにパラメーターのないパブリックコンストラクターがあることを確認する」例外をスローします。この例外メッセージは誤解を招くものであり、実際の原因を説明していません。

コントローラーを明示的に登録すると、より明確な例外メッセージが表示されます。そのため、常にすべてのルートタイプを明示的に登録する必要があります。

ただし、もちろん、構成エラーは、2番目のコンストラクタをに追加したことが原因ですDbContext。Unityは常に最も引数の多いコンストラクターを選択しようとしますが、この特定のコンストラクターを解決する方法はわかりません。

したがって、本当の原因は、Unityの自動配線機能を使用してを作成しようとしていることですDbContextDbContext自動配線されるべきではない特別なタイプです。これはフレームワークタイプであるため、ファクトリデリゲートを使用して登録するようにフォールバックする必要があります。

container.Register<DashboardDbContext>(
    new InjectionFactory(c => new DashboardDbContext())); 

注意してくださいあなたは、このソリューションくださいを適用しようとする前に...あなたのプロジェクト、あなたのログイン資格情報をリセットすることを再構築:プロジェクトを再構築し、自分自身をログアウトし、再度には、だけにして-あなたのページを更新し、問題が解決しないかどうかを観察します
ymz 2017年

ありがとう-私のバックエンドチームのこれらのdingleberriesは、Unity構成で多くのルールを破っています。それがすべてのチームがIOCコンテナを使用する方法かどうか疑問に思われ始めています。
ダグルームズ2017年

@Dagrooms:多くの開発者はこれに少しばかり悩んでいますが、これはすべてのDIコンテナーに存在する問題ではありません。たとえば、Simple Injectorを使用すると、このような事態が発生した場合に常に表現上のエラーが表示されるようになります。別のヒント:カスタムを使用せず、カスタムIDependencyResolverのみを使用してくださいIControllerActivator
スティーブン

46

私の場合は、注入された依存関係のコンストラクター内の例外が原因でした(例では、DashboardRepositoryコンストラクター内)。例外はMVCインフラストラクチャ内のどこかでキャッチされました。関連する場所にログを追加した後、これを見つけました。


7
これは本当に重要な答えです。Unityでセットアップの問題を追跡するという罠に陥るのは非常に簡単Make sure that the controller has a parameterless public constructor.ですが、依存関係がセットアップされている可能性は十分にありますが、腸の奥深くにある例外が原因で問題が解決されていません。
Phil Cooper

2
この。百万回!Ninject構成に依存マップを追加するのを忘れました。
Travo 2016年

腸の例外の深いところは、「DateTime?」であるはずの「string」のプロパティタイプでした。私がこの答えを見なければ、それを探していなかっただろう。どうもありがとうございました。
Jazzy

LousyErrorMessageException()に似ています
Simon_Weaver

ログを配置した場所はどこですか?デバッガーから実行しましたが、すべてのCLR例外をチェックしても例外は発生しませんでした。私は手動のコンストラクター解決を追加する必要があり、それから初めてエラーが発生しました。Diagnosticsを追加して使用可能なエラーを取得するように指示されたため、最終的には何か操作できるようになりました
Arjan

6

同じ問題があり、UnityConfig.csファイルに変更を加えることで解決しましたUnityConfig.csファイルの依存関係の問題を解決するには、追加する必要があります。

public static void RegisterComponents()    
{
    var container = new UnityContainer();
    container.RegisterType<ITestService, TestService>();
    DependencyResolver.SetResolver(new UnityDependencyResolver(container));
}

4

ContainerBootstraper.csでインターフェースを解決しているためにエラーをキャッチすることが非常に難しい場合があります。私の場合、APIコントローラに注入したインターフェイスの実装を解決するときにエラーが発生しました。次のようにbootstraperContainerのインターフェイスを解決したため、エラーを見つけることができませんでした: container.RegisterType<IInterfaceApi, MyInterfaceImplementaionHelper>(new ContainerControlledLifetimeManager());
次に、ブートストラップコンテナーに次の行を追加 container.RegisterType<MyController>(); しました。 。


4

私も同じ問題を抱えていました。2日間ググった。ついに、問題がコントローラーのコンストラクターのアクセス修飾子であることに偶然気づきました。publicコントローラーのコンストラクターの後ろにキーワードを付けませんでした。

public class MyController : ApiController
    {
        private readonly IMyClass _myClass;

        public MyController(IMyClass myClass)
        {
            _myClass = myClass;
        }
    }

この経験を別の答えとして追加します。おそらく誰か他の人が同様の間違いを犯したのでしょう。


0

コントローラにインターフェースがある場合

public myController(IXInterface Xinstance){}

それらをDependency Injectionコンテナーに登録する必要があります。

container.Bind<IXInterface>().To<XClass>().InRequestScope();

0

UnityContainerで定義したインターフェイスタイプではなく、特定のオブジェクトタイプとして誤ってプロパティを定義したときに、このエラーが発生しました。

例えば:

UnityContainerの定義:

var container = new UnityContainer();
container.RegisterInstance(typeof(IDashboardRepository), DashboardRepository);
config.DependencyResolver = new UnityResolver(container);

SiteController(間違った方法-リポジトリのタイプに注意してください):

private readonly DashboardRepository _repo;

public SiteController(DashboardRepository repo)
{
    _repo = repo;
}

SiteController(正しい方法):

private readonly IDashboardRepository _repo;

public SiteController(IDashboardRepository repo)
{
    _repo = repo;
}

0

UnityConfig.csを使用して、以下のようにタイプのマッピングを登録する場合。

public static void RegisterTypes(IUnityContainer container)
    {
     container.RegisterType<IProductRepository, ProductRepository>();
    }

あなたは**webApiConfig.cs**コンテナについて知らせなければなりません

config.DependencyResolver = new Unity.AspNet.WebApi.UnityDependencyResolver(UnityConfig.Container);

0

私の場合、Unityは赤いニシンであることがわかりました。私の問題は、.NETの異なるバージョンを対象とする異なるプロジェクトの結果でした。Unityが正しくセットアップされ、すべてがコンテナーに正しく登録されました。すべてがうまくコンパイルされました。ただし、型はクラスライブラリ内にあり、クラスライブラリは.NET Framework 4.0をターゲットにするように設定されていました。Unityを使用するWebApiプロジェクトは、.NET Framework 4.5をターゲットに設定されました。クラスライブラリも4.5を対象とするように変更すると、問題が解決しました。

これを発見するには、DIコンストラクターをコメント化し、デフォルトのコンストラクターを追加します。コントローラメソッドをコメントアウトし、それらにNotImplementedExceptionをスローさせました。コントローラに到達できることを確認し、NotImplementedExceptionがコントローラを正常にインスタンス化していることを通知したことを確認しました。次に、デフォルトのコンストラクターで、Unityに依存する代わりに、依存関係チェーンを手動でインスタンス化しました。それでもコンパイルされましたが、実行するとエラーメッセージが返されました。これにより、Unityの問題が解決されていなくてもエラーが発生することが確認されました。最後に、チェーンの一番下から始めて、1行ずつコメント化し、エラーメッセージが表示されなくなるまで再テストしていきました。これは、問題のあるクラスの方向を示し、そこから単一のアセンブリに分離されていることがわかりました。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.