2015-12-16 11 views
10

に、コントローラの名前空間へのルートを制限します。 ASP.NET MVCの以前のバージョンでは、私は特定の名前空間に私のASP.NETコアルートのコントローラを制限しようとしているASP.NETコア

ルートを追加するときstring[] namespacesパラメータを提供過負荷がありました。これにはいくつかのGoogleをした後、私は

app.UseMvc(routes => { 
    var dataTokens = new RouteValueDictionary { 
     { 
      "Namespaces", new[] {"ProjectA.SomeNamespace.Controllers"} 
     } 
    }; 

    routes.MapRoute(
     name: "default", 
     template: "{controller=Home}/{action=Index}/{id?}", 
     defaults: null, 
     constraints: null, 
     dataTokens: dataTokens 
    ); 
}); 

のようなもので遊んでみましたが、私がやりたいようには見えないASP.NET MVC 6に欠けています。ルーティングエンジンを特定の名前空間に制限する方法はありますか?

更新

私はちょうどそれは私が個々のコントローラ上のルーティング属性を使用しているという事実と何かをする必要があります実現?属性ルーティングはapp.UseMvc()で定義されたルートをファンクしますか?

アップデート2

詳細:

私は2つの完全に独立したWeb APIプロジェクトをしました。ちなみに、いくつかのルートは両方で同じです(つまり、~/api/ping)。これらのプロジェクトはProductionでは独立しています。一方はユーザーのエンドポイントであり、もう一方は管理者のエンドポイントです。

私もMicrosoft.AspNet.TestHostを使用して、ユニットテストを持っています。これらのユニットテストのいくつかは、これらのWeb APIプロジェクトの両方の機能を必要とします(つまり、 "user"のテストケースを完全にセットアップするための "admin"エンドポイントが必要です)。私は両方のAPIプロジェクトを参照する場合でも、TestHostがあるため、同一ルートの混乱、それは「複数のマッチングルート」文句を言う:

Microsoft.AspNet.Diagnostics.DeveloperExceptionPageMiddleware: Error: An unhandled exception has occurred while executing the request 
Microsoft.AspNet.Mvc.Infrastructure.AmbiguousActionException: Multiple actions matched. The following actions matched route data and had all constraints satisfied: 
    ProjectA.SomeNamespace.Controllers.PingController.Ping 
    ProjectB.SomeNamespace.Controllers.PingController.Ping 
at Microsoft.AspNet.Mvc.Infrastructure.DefaultActionSelector.SelectAsync(RouteContext context) 
at Microsoft.AspNet.Mvc.Infrastructure.MvcRouteHandler.<RouteAsync>d__6.MoveNext() 
+0

"複数の一致するルート" - ここでスタックトレースに完全なエラーを付けることはできますか? –

+0

確かに、更新された質問をご覧ください。 –

答えて

13

アップデート:私はActionConstraintを使用して解決策を見つけた

。重複するアクションについては、カスタムAction Constraint属性を追加する必要があります。重複インデックスメソッドと

例。

まずにHomeController

namespace WebApplication.Controllers 
{ 
    public class HomeController : Controller 
    { 
     [NamespaceConstraint] 
     public IActionResult Index() 
     { 
      return View(); 
     } 
    } 
} 

第二にHomeController

namespace WebApplication 
{ 
    public class HomeController : Controller 
    { 
     [NamespaceConstraint] 
     public IActionResult Index() 
     { 
      return View(); 
     } 
    } 
} 

設定ルーティング

app.UseMvc(cR => 
    cR.MapRoute("default", "{controller}/{action}", null, null, 
    new { Namespace = "WebApplication.Controllers.HomeController" })); 

アクション制約

namespace WebApplication 
{ 
    public class NamespaceConstraint : ActionMethodSelectorAttribute 
    { 
     public override bool IsValidForRequest(RouteContext routeContext, ActionDescriptor action) 
     { 
      var dataTokenNamespace = (string)routeContext.RouteData.DataTokens.FirstOrDefault(dt => dt.Key == "Namespace").Value; 
      var actionNamespace = ((ControllerActionDescriptor)action).MethodInfo.DeclaringType.FullName; 

      return dataTokenNamespace == actionNamespace; 
     } 
    } 
} 

最初の答え:

がapp.UseMvcによって定義されたルート()までファンクをルーティング属性していますか?

属性ルーティングとConvention-basedルーティング(routes.MapRoute(...)は、独立して動作します。アトリビュートルートはコンベンションルートよりも利点があります。

しかし、私がしたいとは思わない。ルーティングエンジンを特定の名前空間に制限する方法はありますか?

Answer from developers

代わりのグループに私たちは地域の使用をお勧めしますあなたのコントローラを名前空間のリストを使用して。コントローラは、特定のエリアでコントローラをアトリビュートすることができます(そのアセンブリがどのアセンブリに属しているかに関係なく)。そのエリアのルートを作成します。

ここでは、MVC 6の領域を使用する例を示したテストウェブサイトが表示されます:https://github.com/aspnet/Mvc/tree/dev/test/WebSites/RoutingWebSite

//Reached through /admin/users 
//have to be located into: project_root/Areas/Admin/ 
[Area("Admin")] 
public class UsersController : Controller 
{ 

} 

設定規則ベースのルーティング:

app.UseMvc(routes => 
{ 
     routes.MapRoute(
     "areaRoute", 
     "{area:exists}/{controller}/{action}", 
     new { controller = "Home", action = "Index" }); 
} 

例属性ベースの領域を使用して、規則ベース

コントローラルーティングエリアを使用

例ルーティング

//Reached through /admin/users 
//have to be located into: project_root/Areas/Admin/ 
[Area("Admin")] 
[Route("[area]/[controller]/[action]", Name = "[area]_[controller]_[action]")] 
public class UsersController : Controller 
{ 

} 
+0

あなたの素晴らしい答えをありがとう。これは確かにほとんどの場合有効ですが、私はそれが私の特別なケースでは最適ではないと思います。私は詳細を提供する必要がありました。私は直ちにそれを修正します)。 私は完全に独立した2つのWeb APIプロジェクトを持っています。ちなみに、いくつかのルートは同じです(つまり '〜/ api/ping')。私は 'Microsoft.AspNet.TestHost'を使ってユニットテストをしています。これらの単体テストのいくつかは、これらのWeb APIプロジェクトの両方の機能を必要とします(例えば、テストケースを完全にセットアップする場合など)。しかし、私が両方のAPIプロジェクトを参照するとき、 'TestHost'は同じルートのため混乱します。 –

+0

@saxx私は答えを更新しました。 –

+0

ルーティングの制約を使ってお時間をいただき、ありがとうございます。私はあなたの答えをソリューションとしてマークします。 'dataTokens'は属性ルーティングでは動作しません。 –

関連する問題