0

子オブジェクトとして部分的なViewModelを持つViewModelの部分的なビューの一部を検証する方法を理解できないようです。これが私の最低レベルの部分です。これは常に他のフォームタグ内の部分的なビューとして消費されます。

namespace MVC3App.ViewModels
{
    public class Payment : IValidatableObject
    {
        public decimal Amount { get; set; }
        public int CreditCardNumber { get; set; }

        public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
        {
            if (Amount < 20)
                yield return new ValidationResult("Please pay more than $20", new string[] { "Amount" });
        }
    }
}

そして、これがそれを含む「メイン」ViewModelです:

namespace MVC3App.ViewModels
{
    public class NewCustomerWithPayment :IValidatableObject
    {
        public string Name { get; set; }
        public int Age { get; set; }
        public ViewModels.Payment PaymentInfo { get; set; }

        public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
        {
            if (Age < 18)
                yield return new ValidationResult("Too young.", new string[] { "Age" });
        }
    }
}

NewCustomerWithPaymentのビューについては、次のようになります。

@model MVC3App.ViewModels.NewCustomerWithPayment
@using (Html.BeginForm()) {
    @Html.ValidationSummary(true)
    <fieldset>
        <legend>NewCustomerWithPayment</legend>

        <div class="editor-label">
            @Html.LabelFor(model => model.Name)
        </div>
        <div class="editor-field">
            @Html.EditorFor(model => model.Name)
            @Html.ValidationMessageFor(model => model.Name)
        </div>

        <div class="editor-label">
            @Html.LabelFor(model => model.Age)
        </div>
        <div class="editor-field">
            @Html.EditorFor(model => model.Age)
            @Html.ValidationMessageFor(model => model.Age)
        </div>
    </fieldset>
    @Html.Partial("Payment")
    <p><input type="submit" value="Create" /></p>
}

また、部分ビューの「支払い」は常に別のHtml.Beginformタグ内にレンダリングされ、次のようになります。

@model MVC3App.ViewModels.Payment
<h2>Payment</h2>
<fieldset>
    <legend>Payment</legend>

    <div class="editor-label">
        @Html.LabelFor(model => model.Amount)
    </div>
    <div class="editor-field">
        @Html.EditorFor(model => model.Amount)
        @Html.ValidationMessageFor(model => model.Amount)
    </div>

    <div class="editor-label">
        @Html.LabelFor(model => model.CreditCardNumber)
    </div>
    <div class="editor-field">
        @Html.EditorFor(model => model.CreditCardNumber)
        @Html.ValidationMessageFor(model => model.CreditCardNumber)
    </div>
</fieldset>

私の問題は、「支払い」ビューモデルの検証を機能させることができないことです。部分ビューとしてレンダリングされるViewModelsでIValidatableObjectを使用した経験のある人は、チャイムを鳴らして、機能する検証パターンを教えてくれますか?必要に応じて、JavaScriptの検証なしで生活できます。

4

3 に答える 3

1

これらの回答にはすべて素晴らしい情報がありますが、これを使用して当面の問題を解決しました:

@Html.EditorFor(model => model.PaymentInfo)

これの代わりに:

Html.Partial("Payment", Model.PaymentInfo)

これが機能することに驚きましたが、機能します。EditorFor ヘルパーは、Html.Partial と同じように部分ビューをレンダリングし、検証を自動的に配線します。何らかの理由で、子モデル (私の例では支払い) で検証を 2 回呼び出します。各モデルに「HasBeenValidated」のブール値を含め、Validate 呼び出しの開始時にそれを確認する必要があります。

更新:ビューを EditorFor ヘルパーで使用するには、ビューを /Views/Shared/ の下の EditorTemplates フォルダーに移動する必要があります。それ以外の場合、EditorFor はタイプのデフォルトの編集フィールドを提供します。

于 2012-09-17T13:37:02.047 に答える
0

チェックボックスのカスタムバリデーターの不完全な例を次に示します:)カスタムバリデーターを作成するか、正規表現を使用する可能性があります。これはあなたを正しい道に導き、より簡単にするかもしれません。

 [AttributeUsage(AttributeTargets.Property, AllowMultiple = false, Inherited = false)]
public class CheckBoxMustBeTrueAttribute : ValidationAttribute, IClientValidatable
{
    #region IClientValidatable Members

    public IEnumerable<ModelClientValidationRule> GetClientValidationRules(ModelMetadata metadata,
                                                                           ControllerContext context)
    {
        yield return new ModelClientValidationRule
                         {
                             ErrorMessage = FormatErrorMessage(metadata.GetDisplayName()),
                             ValidationType = "requiredcheckbox"
                         };
    }

    #endregion

    public override bool IsValid(object value)
    {
        if (value is bool)
        {
            return (bool) value;
        }
        return true;
    }
}
于 2012-09-14T20:06:54.063 に答える
0

ほとんどIValidatableObjectの場合、ルート モデルでのみ認識されます。ルート モデルから内部モデルValidateメソッドを呼び出すことができます。

public class NewCustomerWithPayment :IValidatableObject {
   ...
   public ViewModels.Payment PaymentInfo { get; set; }

   public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
   {
      if (Age < 18)
         yield return new ValidationResult("Too young.", new string[] { "Age" });

      if (this.PaymentInfo != null)
         yield return this.PaymentInfo.Validate(validationContext);
   }
}

注: 上記がコンパイルされるかどうかはわかりません。

于 2012-09-14T23:40:01.190 に答える