1

私は最初の ASP.NET MVC (バージョン 3 のベータ版) アプリケーション (EF4 を使用) に取り組んでおり、新しいレコードの保存と既存のレコードの更新に関するいくつかの規則に少し苦労しています。標準のルート マッピングを使用しています。

ユーザーがページ /session/Evaluate に移動すると、新しいレコードを入力して保存できます。次のように定義されたアクションがあります。

[ActionName("Evaluate")]
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult EvaluateSave(EvaluteSessionViewModel evaluatedSession)
{
}

保存するときは、ビュー モデルからエンティティを取得し、コンテキストにアタッチして保存します。ここまでは順調ですね。ここで、ユーザーが URL /session/Evaluate/1 (「1」はレコード ID) を介してこのレコードを編集できるようにします。

編集: EF エンティティをプロパティとしてビュー モデルに添付しています。

このように、オーバーロードされたメソッドを追加すると ('1' の部分を自動的に取得できるようになります)。

[ActionName("Evaluate")]
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult EvaluateSave(ID, EvaluteSessionViewModel evaluatedSession)
{
}

「コントローラ タイプ 'SessionsController' に対するアクション 'Evaluate' の現在のリクエストは、次のアクションの間であいまいです」というエラーが表示されます。私には独特に見えるので、なぜ曖昧なのかわかりません。

今のところ、この問題を飛ばして、既存のレコードを更新できるかどうかを確認することにしたので、ID パラメーターを持たない EvaluateSave をコメントアウトしました。

私がやりたいことはこれです:

// Load the original entity from EF
// Rebind the postback so that the values posted update the entity
// Save the result

エンティティがパラメーター (evaluatedSession) として設定されているため、再バインドが早すぎます。しかし、私が採用したいアプローチを見ると、コードがハッキングされる可能性があることに気付きました (ユーザーが投稿されたバックページにフィールドを追加し、エンティティに設定した値を上書きする可能性があるため)。

そのため、各フィールドを手動でチェックして、変更されているかどうかを確認し、変更されている場合は更新する必要があるようです。このようなもの:

if (evaluatedSession.MyEntity.myField <> savedSession.myField)
   savedSession.myField = evaluatedSession.MyEntity.myField;

または、エンティティのコピーを保存し、ユーザーが編集できないものが変更されていないことを確認します。うん。

2つの質問:

最初: オーバーロードされたメソッドを明確にするにはどうすればよいですか?

2 番目: 以前に保存したレコードの更新を処理するより良い方法はありますか?

編集:Automapperのようなものを使用できると思います...

2010 年 9 月 22 日編集 - OK、これは 2 つの項目の組み合わせで動作するように見えます: [Bind(Exclude="field1,field2" )] クラス レベルの属性、または保存を行うメソッドの一部としての属性。

public ActionResult EvaluateSave([Bind(Exclude="field1")] EvaluateSessionViewModel evaluatedSession)

EF 側からは、コンテキストから ApplyCurrentValues() メソッドを使用できるはずです。

context.ApplyCurrentValues(savedEval.EntityKey.EntitySetName, evaluatedSession);

もちろん、それは私にはうまくいかないようです。「提供されたオブジェクトのキーと一致するキーを持つオブジェクトが ObjectStateManager で見つかりませんでした。提供されたオブジェクトのキー値が、変更を適用する必要があるオブジェクトのキー値と一致することを確認してください。」

何らかの理由で (ApplyCurrentValues の前に) コンテキストにアタッチされていない場合に備えて、ロードしたばかりの元のエンティティをアタッチしようとしました。

context.AttachTo(savedEval.EntityKey.EntitySetName, savedEval);

それでも失敗します。私は、MVC が作成する EF エンティティ オブジェクトの型と関係があると推測しています (おそらく、EF4 が何かを行うには十分に入力されていませんか?)。.NET フレームワークのステップ実行を有効にして、それが何をしようとしているのかを確認できるようにしたかったのですが、EF4 は契約の一部ではないようです。Reflector で見ましたが、何が起こっているのかを視覚化するのは少し難しいです。

4

1 に答える 1

1

それが機能する方法は、httpverbごとに1つのメソッド名しか持てないということです。したがって、最も簡単な方法は、新しいアクション名を作成することです。新しいレコードの場合は「作成」、既存のレコードの場合は「編集」など。

AntiForgeryToken(http://msdn.microsoft.com/en-us/library/dd492767.aspx)を使用してデータを検証できます。ハッキングのすべての試みを止めるわけではありませんが、追加の利点があります。

追加

httpverbごとに1つのアクション名しか持てない理由は、モデルバインダーがモデルバインドを試みるだけであり、実際にはタイプ固有ではないためです。同じアクション名と2つの異なるタイプのパラメーターを持つ2つのメソッドがある場合、プログラムはある種の最適な一致しか認識しないのに、意図は明らかに1つのものである可能性があるため、最適な一致を見つけることはできません。たとえば、パラメータIdとプロパティIdを含むモデルがあり、どちらを使用するのかわからない場合があります。

于 2010-09-20T15:40:18.787 に答える