0

我似乎無法弄清楚如何驗證的局部視圖的片爲具有局部視圖模型爲子對象的視圖模型。這裏是我的最低水平件,這將永遠是消耗其他形式的標籤內的局部視圖:如何使用IValidatableObject偏查看

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" }); 
     } 
    } 
} 

而這裏的「主」視圖模型,包括它:

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> 

我的問題是,我無法使'Payment'viewmodel上的Validation工作。任何人都可以在ViewModels上使用IValidatableObject,並將其渲染爲部分視圖,並給我一個有效的驗證模式?如果必須,我可以在沒有JavaScript驗證的情況下生活。

+0

滾動自定義驗證器的人 – CrazyCoderz

+0

我並不是說這聽起來很諷刺,但是它從你發佈的代碼中看起來似乎只對int(Age)和decimal(量)。這完全在數據註釋的能力範圍內。你爲什麼要編寫你自己的,而不是使用框架內建的東西? –

+0

示例代碼被簡化。實際驗證呼叫將與數據源等進行交談。 – Graham

回答

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; 
    } 
} 
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); 
    } 
} 

注:不知道上面的編譯。

1

這些答案都有一些偉大的信息,但我的眼前問題,通過採用該解決:

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

取而代之的是:

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

我感到驚訝的是這個工作,但它確實。 EditorFor幫助程序像Html.Partial一樣渲染局部視圖,並自動在驗證中進行連線。出於某種原因,它確實在子模型上調用驗證兩次(在我的示例中爲Payment),這似乎是其他人(http://mvcextensions.codeplex.com/workitem/10)報告的問題,所以我必須在每個模型中包含一個'HasBeenValidated'的布爾值,並在驗證調用開始時檢查它。

更新:您必須將視圖移動到/ Views/Shared /下的EditorTemplates文件夾,以便EditorFor使用該視圖。否則,EditorFor會爲您提供這些類型的默認編輯字段。

+0

我不知道EditorFor會這麼做。很高興知道,因爲這是一種非常常見的情況。 –