コントローラーをMvc Web Apiの別のクラスライブラリプロジェクトに配置していました。以前は、Web APIプロジェクトのglobal.asaxに次の行を追加して、別のプロジェクトでコントローラーを探していました。
ControllerBuilder.Current.DefaultNamespaces.Add("MyClassLibraryProject.Controllers");
上記の行を追加する以外は、他の構成を行う必要はありませんでした。これはいつも私にとってはうまくいきました。
ただし、上記の方法を使用してWebApi2で同じことを行うことはできません。うまくいきません。 WebApi2プロジェクトは、自身のプロジェクトのコントローラーフォルダーでコントローラーを見つけようとします。
-2か月後に要約の更新をほとんど行わない(これに報いを始めたため):
WebApiOneソリューションを作成しました。2つのプロジェクトがあり、最初のプロジェクトはWebApiプロジェクトで、2番目のプロジェクトはコントローラーのクラスライブラリです。コントローラクラスライブラリプロジェクトへの参照をWebApiプロジェクトに追加すると、すべてが期待どおりに機能します。つまり、 http://mydevdomain.com/api/values に移動すると、正しい出力が表示されます。
WebApiTwoという2番目のプロジェクトを作成しました。2つのプロジェクトがあり、最初のプロジェクトはWebApi2プロジェクト、2番目はコントローラーのクラスライブラリです。コントローラクラスライブラリプロジェクトへの参照をWebApi2プロジェクトに追加すると、期待どおりに機能しません。つまり、 http://mydevdomain.com/api/values にアクセスすると、「「values」という名前のコントローラーに一致するタイプが見つかりませんでした。」
最初のプロジェクトでは、カスタム設定をまったく行っていません。
ControllerBuilder.Current.DefaultNamespaces.Add("MyClassLibraryProject.Controllers");
私のglobal.asaxでは、StrathWebが彼の2つのブログ投稿で提案したカスタムソリューションを実装していません。これは、コントローラープロジェクトの参照をWebApiプロジェクトに追加するだけですべてが機能するためです。
だから、私はすべてがWebApi2でも同じように動作することを期待するでしょう...しかし、そうではありません。 WebAPi2でこれを実際に試した人はいますか?
これが正常に機能することを確認しました。確認事項:
参照:メインのWeb APIプロジェクトは外部クラスライブラリを参照していますか?
ルーティング:外部コントローラーに干渉する可能性のあるルートを設定しましたか?
保護レベル:外部ライブラリのコントローラーはpublic
ですか?
継承:外部ライブラリのコントローラーはApiController
を継承しますか?
バージョン管理: Web APIプロジェクトとクラスライブラリの両方が同じバージョンのWeb APIライブラリを使用していますか?
問題が解決した場合は、テストソリューションをパッケージ化し、利用できるようにします。また、注意すべき点として、Global.asax
に追加した行を持つコントローラーを検索するようにWeb APIに指示する必要はありません。システムはそれらが参照されていれば自動的にコントローラーを検索します。
そのまま動作するはずです。チェックリスト
ApiController
を継承ValuesController
Clean
ソリューション、手動でbin
フォルダーを削除して再構築Temporary ASP.NET Files
フォルダーを削除します。 WebApiおよびMVCキャッシュコントローラーのルックアップ結果このコントローラー:
[RoutePrefix("MyValues")]
public class AbcController : ApiController
{
[HttpGet]
[Route("Get")]
public string Get()
{
return "Ok!";
}
}
このURLに一致します:
http://localhost/MyValues/Get
(RoutePrefix
で指定されていないため、ルートに/api/
がないことに注意してください。
コントローラールックアップキャッシュ: これは既定のコントローラーリゾルバーです 。ソースコードで、検索結果がキャッシュされていることがわかります。
/// <summary>
/// Returns a list of controllers available for the application.
/// </summary>
/// <returns>An <see cref="ICollection{Type}" /> of controllers.</returns>
public override ICollection<Type> GetControllerTypes(IAssembliesResolver assembliesResolver)
{
HttpControllerTypeCacheSerializer serializer = new HttpControllerTypeCacheSerializer();
// First, try reading from the cache on disk
List<Type> matchingTypes = ReadTypesFromCache(TypeCacheName, IsControllerTypePredicate, serializer);
if (matchingTypes != null)
{
return matchingTypes;
}
...
}
同じシナリオに直面していて、@ justmaraが私を正しい道に導きました。 @justmaraの答えから依存アセンブリの強制ロードを達成するためのhowは次のとおりです。
1)DefaultAssembliesResolverクラスをオーバーライドします
_public class MyNewAssembliesResolver : DefaultAssembliesResolver
{
public override ICollection<Assembly> GetAssemblies()
{
ICollection<Assembly> baseAssemblies = base.GetAssemblies();
List<Assembly> assemblies = new List<Assembly>(baseAssemblies);
var controllersAssembly = Assembly.LoadFrom(@"Path_to_Controller_DLL");
baseAssemblies.Add(controllersAssembly);
return baseAssemblies;
}
}
_
2)設定セクションで、デフォルトを新しい実装に置き換えます
_config.Services.Replace(typeof(IAssembliesResolver), new MyNewAssembliesResolver());
_
このブログのポインターを使用して、この構文をまとめました。
http://www.strathweb.com/2013/08/customizing-controller-discovery-in-asp-net-web-api/
他の人が言ったように、コントローラを直接参照することで強制的にロードする場合、この問題に直面しているかどうかを知っています。別の方法は、CurrentDomain.GetAssemblies()
の結果を例にして、アセンブリがリストにあるかどうかを確認することです。
また、OWINコンポーネントを使用してセルフホスティングしている場合は、これに遭遇します。テスト時には、最初のWebAPI要求が送信されるまでDefaultAssembliesResolverが起動しないことに注意してください(それを実現するのに時間がかかりました)。
IAssembliesResolverサービスが呼び出される前に、参照されるアセンブリがロードされたことを確認しますか?次のようなダミーコードをアプリケーションに挿入してみてください。
var a = new MyClassLibraryProject.Controllers.MyClass();
設定方法(ただし、「a」を使用しない場合、コンパイラはこのコードを「最適化」して完全に削除できることを忘れないでください)。アセンブリの読み込み順序でも同様の問題が発生しました。起動時に依存アセンブリを強制的に読み込むことになりました。
参照先のアセンブリを読み込むようwebapi/mvcに指示する必要があります。それには、web.configのコンパイル/アセンブリセクションを使用します。
<compilation debug="true" targetFramework="4.5.2">
<assemblies>
<add Assembly="XYZ.SomeAssembly" />
</assemblies>
</compilation>
そのような単純な。 @ user1821052が提案した方法でコードでそれを行うことができますが、このweb.configバージョンには同じ効果があります。
すでに言われたこと以外に:
異なる名前空間に同じ名前の2つのコントローラーがないことを確認してください。
1つのコントローラー(foo.UserApiController)を新しいネームスペース(bar.UserApiController)とURIに部分的に移行する必要がある場合がありました。古いコントローラーは慣例により/ userapiにマップされ、新しいコントローラーはRoutePrefix["api/users"]
を介して属性ルーティングされました。新しいコントローラーは、名前をbar.UserFooApiControllerに変更するまで機能しませんでした。
AttributeRoutingを使用する場合、特にコントローラークラスでRoute
属性を使用している場合、RoutePrefix
属性を使用してメソッドを修飾することは簡単に忘れられます。コントローラーアセンブリは、Web APIパイプラインによってピックアップされなかったようです。
クラスライブラリがEF
で構築されている場合、クラスライブラリプロジェクトのApp.config
で指定された接続文字列があることを確認してください[〜 #〜] and [〜#〜] Web API MVC
プロジェクトのWeb.config
で。