MapMvcAttributeRoutes: このメソッドは、アプリケーションの起動前初期化フェーズ中に呼び出すことはできません。質問する

MapMvcAttributeRoutes: このメソッドは、アプリケーションの起動前初期化フェーズ中に呼び出すことはできません。質問する

ASP MVC V5 と属性ルーティングを使用したソリューションのテスト プロジェクトに、非常に単純なテストがあります。属性ルーティングとメソッドは、MapMvcAttributeRoutesASP MVC 5 の一部です。

[Test]
public void HasRoutesInTable()
{
    var routes = new RouteCollection();
    routes.MapMvcAttributeRoutes();
    Assert.That(routes.Count, Is.GreaterThan(0));
}

結果は次のようになります:

System.InvalidOperationException : 
This method cannot be called during the applications pre-start initialization phase.

このエラー メッセージに対する回答のほとんどは、web.configファイル内のメンバーシップ プロバイダーの構成に関係しています。このプロジェクトにはメンバーシップ プロバイダーもweb.configファイルもないため、エラーは他の何らかの理由で発生しているようです。テストを実行できるように、コードをこの「開始前」状態から移動するにはどうすればよいですか?

が呼び出された後、属性の同等のコードはApiController正常に機能しますHttpConfiguration.EnsureInitialized()

ベストアンサー1

最近、プロジェクトをASP.NET MVC 5にアップグレードしたところ、まったく同じ問題が発生しました。ドットピーク調査してみると、コントローラー タイプのリストを期待するパラメーターMapMvcAttributeRoutesを持つ内部拡張メソッドがあることが分かりましたIEnumerable<Type>。リフレクションを使用して属性ベースのルートをテストできる新しい拡張メソッドを作成しました。

public static class RouteCollectionExtensions
{
    public static void MapMvcAttributeRoutesForTesting(this RouteCollection routes)
    {
        var controllers = (from t in typeof(HomeController).Assembly.GetExportedTypes()
                            where
                                t != null &&
                                t.IsPublic &&
                                t.Name.EndsWith("Controller", StringComparison.OrdinalIgnoreCase) &&
                                !t.IsAbstract &&
                                typeof(IController).IsAssignableFrom(t)
                            select t).ToList();

        var mapMvcAttributeRoutesMethod = typeof(RouteCollectionAttributeRoutingExtensions)
            .GetMethod(
                "MapMvcAttributeRoutes",
                BindingFlags.NonPublic | BindingFlags.Static,
                null,
                new Type[] { typeof(RouteCollection), typeof(IEnumerable<Type>) },
                null);

        mapMvcAttributeRoutesMethod.Invoke(null, new object[] { routes, controllers });
    }
}

使い方は次のとおりです:

public class HomeControllerRouteTests
{
    [Fact]
    public void RequestTo_Root_ShouldMapTo_HomeIndex()
    {
        // Arrange
        var routes = new RouteCollection();

        // Act - registers traditional routes and the new attribute-defined routes
        RouteConfig.RegisterRoutes(routes);
        routes.MapMvcAttributeRoutesForTesting();

        // Assert - uses MvcRouteTester to test specific routes
        routes.ShouldMap("~/").To<HomeController>(x => x.Index());
    }
}

ここで問題となるのは、内部でRouteConfig.RegisterRoutes(route)呼び出すことができないroutes.MapMvcAttributeRoutes()ため、代わりにその呼び出しを Global.asax ファイルに移動したことです。

もう 1 つの懸念は、上記のメソッドがRouteCollectionAttributeRoutingExtensions内部的なものであり、いつでも削除される可能性があるため、このソリューションは潜在的に脆弱であるということです。積極的なアプローチとしては、変数が null かどうかを確認しmapMvcAttributeRoutesMethod、そうである場合は適切なエラー/例外メッセージを提供することです。

注記:これは ASP.NET MVC 5.0 でのみ機能します。ASP.NET MVC 5.1 では属性ルーティングに大幅な変更が加えられ、メソッドはmapMvcAttributeRoutesMethod内部クラスに移動されました。

おすすめ記事