4

ルートが MVC 2 のコントローラーにどのように関連付けられているかを誰かが説明できますか? 現在、/Controllers/HomeController.cs にコントローラーがあり、ビューは /Home/Index.aspx です。

私のルート登録方法は次のようになります。

 public static void RegisterRoutes(RouteCollection routes)
        {
            routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
            routes.IgnoreRoute("{resource}.aspx/{*pathInfo}");
            routes.MapRoute(
               "Default",
                // Route name
               "{controller}/{action}/{id}",
                // URL with parameters
               new { controller = "Home", action = "Index", id = "" }
                // Parameter defaults
              );
        }

URL: http://localhost/Home/Indexをリクエストすると、リクエストは HomeController.Index() によって正しく処理されます。

ただし、私の人生では、URL /Home/Index がどのように HomeController を指しているのかわかりません。私が知る限り、ビュー aspx は HomeController を参照しておらず、HomeController はビューを参照しておらず、ルート テーブルは HomeController を明示的に言及していません。これは魔法のようにどのように起こっているのですか?確かに私は明らかな何かを見逃しています。

それから

4

3 に答える 3

7

これは、ASP.NETMVCの規則です。

DefaultControllerFactoryを使用する場合、この規則は内部の封印されたクラス内に埋め込まれSystem.Web.Mvc.ControllerTypeCacheます(Microsoftが内部の封印されたクラスを作成するのが一般的です)。内部には、EnsureInitialized次のようなメソッドがあります。

public void EnsureInitialized(IBuildManager buildManager)
{
    if (this._cache == null)
    {
        lock (this._lockObj)
        {
            if (this._cache == null)
            {
                this._cache = GetAllControllerTypes(buildManager).GroupBy<Type, string>(delegate (Type t) {
                    return t.Name.Substring(0, t.Name.Length - "Controller".Length);
                }, StringComparer.OrdinalIgnoreCase).ToDictionary<IGrouping<string, Type>, string, ILookup<string, Type>>(delegate (IGrouping<string, Type> g) {
                    return g.Key;
                }, delegate (IGrouping<string, Type> g) {
                    return g.ToLookup<Type, string>(t => t.Namespace ?? string.Empty, StringComparer.OrdinalIgnoreCase);
                }, StringComparer.OrdinalIgnoreCase);
            }
        }
    }
}

グループ化がどのように行われるかに注意してください。したがって、基本的にDefaultControllerFactoryは、参照されているすべてのアセンブリ内でController基本クラスを実装する型を探し、名前から「Controller」を削除します。

ASP.NET MVCのパイプラインを詳細に分析したい場合は、この優れた記事をお勧めします。

于 2009-10-20T17:11:17.420 に答える
5

ASP.NET MVC に付属する既定のビュー エンジンは、次の規則に従って動作します。

次のようなフォルダ構造があります。

- Controllers\
|-  HomeController.cs
- Views\
|- Home\
|-- Index.aspx
|- Shared\

リクエストが到着し、RegisterRoutes メソッドで定義されたルートと一致すると (詳細については、URL ルーティングなどを参照してください)、一致するコントローラーが呼び出されます。

routes.MapRoute(
  "Default", // Route name, allows you to call this route elsewhere
  "{controller}/{action}/{id}", // URL with parameters
  new { controller = "Home", action = "Index", id = "" } // Parameter defaults
  );

デフォルト ルートでは、デフォルト コントローラ(「Controller」サフィックスなし)も指定しています。ルーティング エンジンはController、コントローラ名に自動的に追加します。デフォルト アクションも指定します。

コントローラーで、単純なメソッドを呼び出します。

public ActionResult Index(){
  return View();
}

次に、既定のビュー エンジンは、"Views" フォルダー (規則) 内の "Home" というフォルダー (コントローラーと同じ) で、Index という名前の aspx ファイル (アクションと同じ) を探します。

見つからない場合は、Shared フォルダー内のインデックス ページも探します。

ASP.NET MVC Nerd Dinner サンプルの章から

ASP.NET MVC アプリケーションは、既定で、ビュー テンプレートを解決するときに、規則に基づくディレクトリの名前付け構造を使用します。これにより、開発者は Controller クラス内からビューを参照するときにロケーション パスを完全修飾する必要がなくなります。既定では、ASP.NET MVC は\Views\[ControllerName]\、アプリケーションの下のディレクトリ内でビュー テンプレート ファイルを探します。

サブディレクトリは、アプリケーション内の\Views\Shared複数のコントローラーで再利用されるビュー テンプレートを格納する方法を提供します。ASP.NET MVC がビュー テンプレートを解決しようとすると、最初に\Views\[Controller]特定のディレクトリ内がチェックされ、そこにビュー テンプレートが見つからない場合は\Views\Sharedディレクトリ内が検索されます。

個々のビュー テンプレートに名前を付ける場合は、レンダリングの原因となったアクション メソッドと同じ名前をビュー テンプレートに持たせることをお勧めします。たとえば、上記の「インデックス」アクション メソッドは「インデックス」ビューを使用してビューの結果をレンダリングし、「詳細」アクション メソッドは「詳細」ビューを使用してその結果をレンダリングしています。これにより、各アクションに関連付けられているテンプレートをすばやく簡単に確認できます。

ビュー テンプレートがコントローラーで呼び出されるアクション メソッドと同じ名前を持つ場合、開発者はビュー テンプレート名を明示的に指定する必要はありません。代わりに、(ビュー名を指定せずに) モデル オブジェクトをヘルパー メソッドに渡すだけで、ASP.NET MVC はディスク上View()のビュー テンプレートを使用してレンダリングすることを自動的に推測します。\Views\[ControllerName]\[ActionName]


編集して追加:

コントローラーを明示的に設定する、私が設定したルートの例は次のとおりです。

routes.MapRoute(
  "PhotoDetailsSlug",
  "Albums/{albumId}/{photoId}/{slug}",
  new {controller = "Albums", action = "PhotoDetails"},
  new {albumId = @"\d{1,4}", photoId = @"\d{1,8}"}
  );

ここでは、Albums コントローラーとその PhotoDetails アクションを使用し、さまざまな ID などをそのアクションに渡していることを明示的に述べています。

于 2009-10-20T17:32:32.953 に答える
2

アクションインデックス内にステートメントがありreturn View()ます。空白のビューが返されると、DefaultViewEngineはいくつかのデフォルトフォルダーでControllerメソッドの名前を検索します(具体的にはFindViewメソッド内)。Homeはコントローラーの名前であるため、そのうちの1つはViews/Homeディレクトリーです。そこでインデックスファイルを見つけ、それを使用して結果を表示します。

于 2009-10-20T17:07:53.353 に答える