MVC 2 AreaRegistrationルートの順序
-
08-07-2019 - |
質問
MVC 2 Preview 2では、AreaRegistrationが各エリアのルートを任意の順序でロードしていることに気付きました。あるものを先に得る良い方法はありますか?
たとえば、「サイト」という2つの領域があります。および「管理者」。両方とも「ブログ」を持っています;コントローラ。
次のものが欲しい:
/admin/ --> go to Admin's Blog controller
/ --> go to Site's Blog controller.
問題は、最初にサイトのルートをロードしているため、 admin / {controller} / {actionではなく、
のURL" / admin /"にアクセスすると。 「サイト」に管理コントローラーがないため、404が表示されます。エリア。 {controller} / {action} / {id}
と一致することです。 } / {id}
両方の領域のデフォルトは「ブログ」です。コントローラ。 URLとして site / {controller} / ...
を単純に配置できることを理解していますが、可能であればルートに配置したいです。また、グローバルRegisterRoutes関数でデフォルトルートを維持しようとしましたが、「サイト」に送信されません。エリア。
事前に感謝します!
解決
現在、エリアを注文することはできません。ただし、各エリアを可能な限り他のエリアから独立させて、順序が問題にならないようにすることは理にかなっていると思います。
たとえば、デフォルトの{controller} / {action} / {id}ルートを使用する代わりに、各コントローラーの特定のルートに置き換えることができます。または、そのデフォルトルートに制約を追加します。
注文を許可するためにオプションを検討していますが、機能を過度に複雑にしたくありません。
他のヒント
Haackedの発言は別として、エリア登録(およびそのルート)を注文することは非常に可能です。あなたがしなければならないのは、あなたが望むどんな順番ででも、手動で各エリアを登録することです。 RegisterAllAreas()を呼び出すほどスマートではありませんが、間違いなく実行可能です。
protected void Application_Start() {
var area1reg = new Area1AreaRegistration();
var area1context = new AreaRegistrationContext(area1reg.AreaName, RouteTable.Routes);
area1reg.RegisterArea(area1context);
var area2reg = new Area2AreaRegistration();
var area2context = new AreaRegistrationContext(area2reg.AreaName, RouteTable.Routes);
area2reg.RegisterArea(area2context);
var area3reg = new Area3AreaRegistration();
var area3context = new AreaRegistrationContext(area3reg.AreaName, RouteTable.Routes);
area3reg.RegisterArea(area3context);
}
もう1つのオプションは、RegisterAllAreas()のコードを取得して独自のアプリにコピーし、順序を決定する独自のメカニズムを構築することです。組み込みメソッドが行うすべての派手なキャッシングロジックが必要な場合、コピーするのはかなりのコードですが、アプリでは必要ないかもしれません。
このソリューションを作成します:
AreaUtils.cs
using System;
using System.Web.Mvc;
using System.Web.Routing;
namespace SledgeHammer.Mvc.Site
{
public static class Utils
{
public static void RegisterArea<T>(RouteCollection routes,
object state) where T : AreaRegistration
{
AreaRegistration registration =
(AreaRegistration)Activator.CreateInstance(typeof(T));
AreaRegistrationContext context =
new AreaRegistrationContext(registration.AreaName, routes, state);
string tNamespace = registration.GetType().Namespace;
if (tNamespace != null)
{
context.Namespaces.Add(tNamespace + ".*");
}
registration.RegisterArea(context);
}
}
}
global.asaxの場合:
Utils.RegisterArea<SystemAreaRegistration>(RouteTable.Routes, null);
Utils.RegisterArea<ClientSitesAreaRegistration>(RouteTable.Routes, null);
//AreaRegistration.RegisterAllAreas(); do not dublicate register areas
生成されたエリア登録コードに必要な変更はありません。 また、ルートでカスタムconstrantを使用して、リクエスト内のドメインのタイプ(システムドメインまたはユーザーサイト)でルートをフィルタリングします。
これは例としての私のエリア登録です:
namespace SledgeHammer.MVC.Site.Areas.System
{
public class SystemAreaRegistration : AreaRegistration
{
public override string AreaName
{
get { return "System"; }
}
public override void RegisterArea(AreaRegistrationContext context)
{
context.MapRoute(
"System_Feedback",
"Feedback",
new { controller = "Feedback", action = "Index" }
);
context.MapRoute(
"System_Information",
"Information/{action}/{id}",
new { controller = "Information", action = "Index", id = UrlParameter.Optional }
);
}
}
}
namespace SledgeHammer.MVC.Site.Areas.ClientSites
{
public class ClientSitesAreaRegistration : AreaRegistration
{
public override string AreaName
{
get { return "ClientSites"; }
}
public override void RegisterArea(AreaRegistrationContext context)
{
context.MapRoute(
"ClientSites_default",
"{controller}/{action}/{id}",
new { controller = "Site", action = "Index", id = UrlParameter.Optional },
new { Host = new SiteInGroups("clients") }
);
}
}
}
参考のために、
MVC3(MVC2については知らない)では、ルートを特定のエリア/コントローラーにマップするだけの場合は、単にグローバルルートを使用できます。 名前空間/エリアを指定することを忘れないでください。
routes.MapRoute(
"CatchRoot", "",
new { controller = "SITEBLOG-CONTROLLER-NAME", action = "Index"}
).DataTokens.Add("area", "SITE-AREA-NAME");