0

私のアプリケーションでは、エリア(XYZ)にコントローラー(XYZController)があり、エリア内に他のコントローラーがたくさんあります。XYZControllerには、インデックス、表示、作成、編集などの一般的なアクションがあります。特定の機能に関連するより具体的なアクションは、対応するコントローラーに適宜配置されます。

app / XYZ(area)/ XYZ(Controller)/ Createのような構造のURLを避けるために、エリアルートレジスタファイルに次のようにルーティングを追加しました。

context.MapRoute(
                  "XYZ_AreaDefaultControllerActions",
                  "XYZ/{action}/{id}",
                  new { controller = "XYZ", id = UrlParameter.Optional },
                  new { controller = "XYZ" },
                  new string[] { "App.Web.Areas.XYZ.Controllers.*" } 
              );

context.MapRoute(
                "XYZ_default",
                "XYZ/{controller}/{action}/{id}",
                new { controller = "XYZ", action = "Index", id = UrlParameter.Optional}
        );

このマッピングは、次のURLをルーティングします:app / XYZ / Create to area = XYZ、Controller = XYZ and Action = Createこれは正しく、私がやりたいことですが、他のいくつかのPostアクションのルーティングを台無しにします。

これを考慮して、いくつかのPostアクションを持つNotesコントローラーと呼ばれる別のコントローラーがあります。

リクエストがHTTPGetであり、ルートデバッガーからの出力が、2番目のルート定義が一致し、最初のルート定義が一致しないことを示している場合、URLが/ app / XYZ / Notes / List/idであるアクションは正しくルーティングされます。

url / App / XYZ / Notes / AddNoteを使用してアクションAddNoteを使用して同じコントローラーに投稿すると、ルートデバッガーに従って最初のルート定義が一致し、その結果、Controller = XYZ、Actionを実行するため、アクションが見つかりません。 =メモ、Id=AddNote。ルートデバッガーからの出力は次のとおりです。

一致| URL | デフォルト| 制約

  1. 真| XYZ/{アクション}/{id} | コントローラ=XYZ、id = | コントローラー=XYZ

  2. 真| XYZ/{コントローラー}/{アクション}/{id} | コントローラ=XYZ、アクション=インデックス、id = |(null)

問題は、最初のルートの制約が、[取得]で制約を適用しているときに、Postの場合にそれを十分に制限していないように見えることです。

ここで何が問題になっているのか、何か提案はありますか?

4

1 に答える 1

0

XYZControllerにPOSTアクションがない場合は、次のような制約を追加して、POST要求が最初のルートと一致しないようにすることができます。

context.MapRoute("XYZ_AreaDefaultControllerActions",
    "XYZ/{action}/{id}",
    new { controller = "XYZ", id = UrlParameter.Optional },
    new { controller = "XYZ", httpMethod = new HttpMethodConstraint("GET") },
    new string[] { "App.Web.Areas.XYZ.Controllers.*" }
);

アップデート

前述のように、XYZControllerに投稿アクションがあるため、上記のルート制約は機能しません。

ここでの問題は、お住まいの地域と同じ名前のコントローラーがあることです。これが、MVCが最初のルートをNotes Controller POSTアクションに一致させている理由です。これは、受信URLに基​​づいてトークンを一致させようとしているだけだからです。

  • /XYZ-これは文字通り最初のルートの最初のセグメントと一致します
  • /メモ-これは{アクション}セグメントに入力されます
  • /AddNote-これは{id}セグメントに入力されます

最初のルートを考えると、{ controller = "XYZ" }MVCはインバウンドURLをコントローラー+アクション+引数にルーティングしようとしているため、制約は何の違いもありません。MVCは、どのコントローラーから来ているのかわかりません。どのコントローラーとアクションがURL要求を処理するかを一致させようとしています。

1つの解決策は、最初のルートにアクション制約を追加することですが、これは、XYZControllerのアクション名がNotesコントローラーのPOSTアクション名のいずれとも一致しない場合にのみ機能します。

new { controller = "XYZ", action = "XYZAction1|XYZAction2|XYZActionN" },

着信ルートの場合、これは、アクションが制約内のパイプで区切られた名前の1つである場合にのみ、最初のルートと一致します。

もう1つのオプションは、正規表現を使用して{id}ルートセグメントを制約することです。IDが文字列の場合、これはオプションではない可能性があります。ただし、IDが常に数字である場合は、最初のルートを制約して、ルートセグメントが数字の場合にのみルートセグメントを{id}トークンに一致させることができます。このように、「AddNote」は数値ではないため、最初のルートの{id}セグメントと一致しません。

new { controller = "XYZ", id = @"\d+" },

2番目のコメントに答えるために、これがGETで機能する理由は、2番目のルートに追加のルートセグメントがあるためです。IDを持つGETSは、3つではなく4つのトークンを持っているため、最初のルートと一致しません。

于 2012-07-30T13:03:10.903 に答える