4

私はまだMVCに非常に慣れていないので、この問題を回避する最善の方法を見つけるのに苦労しています。

"Create" (GET)オプションのパラメーター(ドロップダウンリストのデフォルト値)をとる自動足場アクションの修正バージョンがあります。"Create" (HTTPPost)次に、そのフォームをアクションに送信します。

public ActionResult Create(string id = null)
{ 
    //use id to pick a default item in a drop down list.
}

[HttpPost]
public ActionResult Create(Registration registration)
{ 
    //this method doesn't care one iota what was passed to the GET method
    // but registration.id is invalid because it's trying to set it to the value that was passed to the get method.  If id in the get method is not passed, then everything is fine
}

問題は、値がGET createアクションに渡された場合、GETアクションに渡された値をPOSTアクションのモデルの主キー(Id)フィールドに詰め込もうとしているためModelState.isValid、アクションでfalseになることです。 POST create(自動生成されるため、省略してください。

主キーの列名をId以外に変更できることはわかっていますが、データベースを制御できず、この問題に対する別の解決策を見つけようとしています。

GETアクションのパラメーターの名前を「id」から別の名前に変更しようとすると、リンクをからに変更する必要がありますが、変更し CREATE/paramValue たくCREATE/?paramName=paramValueありません。(それが唯一の簡単な方法であるなら私はそうしますが)。

POSTアクションがGETアクションに渡された値を無視するようにする方法はありますか?

4

2 に答える 2

3

あなたがやろうとしているのは、コントローラーのCreateメソッドを、作成するオブジェクトのタイプのIDでパラメーター化することだと思います。

ASP.NET MVCのパラメーター名には厳格な規則はありませんが、ほとんどの人は、呼び出されたパラメーターがid、その属性ではなく、処理されているオブジェクトを参照することを期待していると思います。

これを念頭に置いて、あなたへの私の提案は次のことをすることです:

  1. CreateメソッドのGETバージョンのパラメーターの名前をtypeIdなどの適切な名前に変更すると、署名は次のようになります。public ActionResult Create(string typeId = null)

  2. にカスタムルートを追加します。これにより、強制的にではなくMvcApplication、適切にフォーマットされたルートを使用できるようになります。/Create/typeId/Create?typeId=value

これを行うには、デフォルトルートの前に次のコード行を追加します。

routes.MapRoute
(
    name: "CreateGet",
    url: "Controller/Create/{typeId}",
    defaults: new
    {
        controller = "Controller",
        action = "Create",
        typeId = UrlParameter.Optional
    }
);

デフォルトルートは次のようになります。

routes.MapRoute
(
    name: "Default",
    url: "{controller}/{action}/{id}",
    defaults: new
    {
        controller = "Site",
        action = "Index",
        id = UrlParameter.Optional
    }
);

私が提案しているカスタムルートがデフォルトルートの前に来るようにしてくださいが、これで問題は解決すると思います。

アップデート:

GetメソッドとPostメソッドがあります。

Getメソッドは(おそらく)ビューモデルオブジェクトを作成し、それをビューに送信してレンダリングします。または、ビューにさまざまな入力をHTMLにハードコーディングするか、AJAX呼び出しを介して挿入することもできます。それらがどのようにそこに到達したかに関係なく、Webブラウザに出力されるレンダリングされたビューは次のようになります。

<html>
<head />
<body>
<form>
<input id="Input1" ... />
<select id="Select1" ... />
</form>
</body>
</html>

上記は、出力されるHTMLの非常に単純化された構造です。

入力のIDは、このページがポストバックされたときに作成されるビューモデルオブジェクト内のプロパティの名前、つまりRegistrationクラスのインスタンスと一致します。

(Postメソッドに)戻る途中で、モデルバインダーはリクエストから値(クエリ文字列パラメーター、フォーム値など)を取得し、Postメソッドに与えられたモデルオブジェクトにバインドします。

あなたの場合、おそらく起こっていたidのは、Getメソッド(およびレンダリングされたビュー)でidの意味RegistrationとPostメソッドに与えられたオブジェクトでの意味との間に不一致があったことでした。

不一致の理由は、Registration.Idプロパティ名がデータベースCreate(string id)によって指定され、デフォルトルートによって指定されていたためですが、実際には異なるものであるため、別の名前を付ける必要があります。

そのため、/ Create / idフォームのクリーンなURLが必要になりました。これは、カスタムルートで簡単に実行できます。

ここで、モデルバインディングロジックからパラメーターを本当に除外したい場合はRegistration、Postメソッドのパラメーターの属性を使用しDefaultModelBinderて、そのパラメーターをバインディングロジックから除外するように明示的に指示する別の回答を使用します。

これを実行すると、バインドされたプロパティは、インスタンス化してコンストラクターを実行した後、CLRによって指定されたデフォルト値を保持します。

ASP.NET MVCは、必要に応じてモデルバインディングロジックを大幅に変更できるカスタムモデルバインダーもサポートしていますが、それはあなたの場合には当てはまりません。

于 2013-01-22T21:44:07.160 に答える
2

使用してみてくださいBindAttribute

[HttpPost]
public ActionResult Create([Bind(Exclude = "RegistrationId")]Registration registration)
{ 

}

RegistrationIdモデルにバインドするときに、POSTedwithフォームを省略します。

于 2013-01-22T21:21:26.543 に答える