5

TryUpdateModel を使用して、DataAnnotations を使用して asp.NET MVC 2 RC2 のモデルに検証を追加しようとしています。

        var user = UserManager.Find(id);

        this.TryUpdateModel<IProvisioningObject>(user, form.ToValueProvider());

これによりモデルが更新されますが、検証は呼び出されません。フォーム値プロバイダーを使用せずに、(検証メタデータを持つ) ProvisioningObject を直接使用して、TryUpdateModel (ユーザーの直接型) も使用してみましたが、役に立ちませんでした。

例をグーグルで検索すると、パラメーターを介してバインドすることで DataAnnotations を使用する方法しか得られません

public ActionResult Update(User user)

更新シナリオが嫌いです。

ヒントや解決策はありますか?

編集 私のオブジェクトは、WCF サービスから自動生成されたオブジェクトです。

DataAnnotations を追加できるようにパーシャルを作成しました。どうやら継承をサポートしていないため、TryUpdateModel を 3 回呼び出します。これは、DataAnnotations の問題でもあると思います。ProvisioningObject の検証属性を指定すると、バインディングはそのような継承されたものを探しません。

[MetadataType(typeof(ProvisioningObjectMetadata))]
public partial class ProvisioningObject : IProvisioningObject
{
    public string DisplayNameInvariant { get { return string.IsNullOrEmpty(this.DisplayName) ? this.Name : this.DisplayName; } }
}


[MetadataType(typeof(UserMetadata))]
public partial class User : IUser
{
}


public class ProvisioningObjectMetadata
{
    [DisplayName("Country")]
    public string CountryIsoCode { get; set; }

    [Required(ErrorMessageResourceType = typeof(Properties.Validation), ErrorMessageResourceName = "DisplayNameIsRequired")]
    [TempValidator]
    public string DisplayName { get; set; }
}


public class UserMetadata
{
    [DisplayName("Username")]
    public string Name { get; set; }
}


// Controller action
    public ActionResult Update(string id, FormCollection form)
    {
        var user = UserManager.Find(id);

        this.TryUpdateModel<IUser>(user.User, form.ToValueProvider());
        this.TryUpdateModel<IPerson>(user.User, form.ToValueProvider());
        this.TryUpdateModel<IProvisioningObject>(user.User, form.ToValueProvider());

        if (ModelState.IsValid) // always true
        {
            return Redirect;
        }
        else
        {
            return View();
        }
    }

UserMetadata に DisplayName のメタデータを追加すると、期待どおりに動作しますが、それは非常に冗長に思えます。また、TryUpdateModel が適切に動作するように、継承したすべてのインターフェイスをコピーして貼り付ける必要があることも意味します。

検証属性をコピーして継承されたクラスに貼り付ける必要のない方法を探していると思います。

4

3 に答える 3

1

新しい答え:

「私のオブジェクトは、WCF サービスから自動生成されたオブジェクトです。」

自動生成されたオブジェクトには属性がありません。サーバー側またはクライアント側でオブジェクトとその属性を定義していますか?

古い回答: メタデータが IProvisioningObject にない場合、検証は呼び出されません。MVC2 の既定のモデル バインダーは、"追加の" [MetadataType(buddyClass)] 検証情報を見つける方法しか知りません。

更新シナリオでは、DTO に対してバインドしてから、IsValid() の場合は DTO をメイン モデル クラスにマップします。

于 2010-02-08T17:50:35.167 に答える
1

部分クラスにインターフェイスを実装IDataErrorInfoします 各フィールドのカスタム検証を記述する必要があります (データ注釈クラスを使用して必要な各プロパティを検証できます)

コード例が必要な場合は、お知らせください。私はあなたのためにそれを書きます!

ソース: http://www.asp.net/(S(pdfrohu0ajmwt445fanvj2r3))/learn/mvc/tutorial-37-cs.aspx

于 2010-02-12T13:45:00.937 に答える
0

検証が呼び出されていないことをどのように知ることができますか? 更新コントローラーで ModelState.IsValid をチェックしていて、誤って true に戻っていることがわかりましたか?

一般的な更新パターンは次のとおりです。

UpdateModel(model);
if(!ModelState.IsValid) return View(model);
return RedirectToAction("Index");

モデルの「IsValid」が自動的に呼び出されることを期待している場合、それは起こりません。データ注釈は、Controller 基本クラスの ModelState ディクショナリを使用して、舞台裏で機能します。

于 2010-02-08T19:29:50.567 に答える