2

由於我處理的是一個非常複雜的模型和表單,因此我會通過一個更容易理解的示例來減少問題(請原諒是否有任何錯字)。嵌套集合的不顯眼驗證

首先,我將展示場景:

模型...

public class Foo 
{ 
    [Required] 
    public int fooId {get; set;} 
    public string fooName {get; set;} 

    public List<Bar> barList {get; set;} 
} 


public class Bar 
{ 
    [Required] 
    public int barId {get; set;} 
    public string barName {get; set;} 
} 

的觀點...

@model Foo 

@using (Html.BeginForm("Save", "form", FormMethod.Post)) 
{ 

    <div class="control-group"> 
     <div class="controls"> 
      @Html.TextBoxFor(model => Model.fooId) 
     </div> 
    </div> 

    <div class="control-group"> 
     <div class="controls"> 
      @Html.TextBoxFor(model => Model.fooName) 
     </div> 
    </div> 

    @for (int i = 0; i < Model.barList.Count(); i++) 
    { 
     @Html.EditorFor(m => m.barList[i]) 
    } 

} 

的 「欄中的」 編輯模板...

@model Bar 

<div class="control-group"> 
    <div class="controls"> 
     @Html.TextBoxFor(m => m.barId) 
    </div> 
</div> 
<div class="control-group"> 
    <div class="controls"> 
     @Html.TextBoxFor(m => m.barName) 
    </div> 
</div> 

這個問題, m在客戶端驗證嵌套集合中的輸入時,在這種情況下,我無法驗證「barId」輸入字段。它只是忽略它... 在fooId字段的情況下,它的確認無誤。

如果深究下去,連2「欄」項「foo」的對象會產生這樣的:

<div class="control-group"> 
    <div class="controls"> 
     <input class="input-validation-error" id="fooId" name="fooId" type="text" value=""> 
    </div> 
</div> 
<div class="control-group"> 
    <div class="controls"> 
     <input id="fooName" name="fooName" type="text" value=""> 
    </div> 
</div> 

<div class="control-group"> 
    <div class="controls"> 
     <input id="barList_0__barId" name="barList[0].barId" type="text" value=""> 
    </div> 
</div> 
<div class="control-group"> 
    <div class="controls"> 
     <input id="barList_0__barName" name="barList[0].barName" type="text" value=""> 
    </div> 
</div> 

<div class="control-group"> 
    <div class="controls"> 
     <input id="barList_1__barId" name="barList[1].barId" type="text" value=""> 
    </div> 
</div> 
<div class="control-group"> 
    <div class="controls"> 
     <input id="barList_1__barName" name="barList[1].barName" type="text" value=""> 
    </div> 
</div> 

正如你所看到的,「酒吧」集合內的項目均獲得了不同ID和名稱。這是渲染集合的正常行爲。

但它似乎是客戶端驗證不適用於這些ID和名稱。只有當我將ID &名稱更改爲「barId」,刪除收集索引時,驗證纔有效。

經過數小時的調查,我發現了一些有關這類問題的文章和帖子,但沒有具體的和我仍然無法解決這個問題。

IValidatableObject in MVC3 - client side validation

mvc clientside validation for nested (collection) properties

+0

您發佈似乎並不符合您的觀點和編輯模板的輸出,不應該前兩個是Foo控件,每個Bar都有Id和Name控件? – christofr

+0

是的,對不起。現在它已更正 – Javier

+0

如果您使用JavaScript添加收藏品,您是否刷新了驗證?例如,'var form = $(「#editItem」);''form.removeData('validator');''form.removeData('unobtrusiveValidation');''。$ .validator.unobtrusive.parse(form); '是我爲集合項添加我的add方法後調用的。 –

回答

0

我沒有找到一個解決方案,但我沒有找到一個解決辦法。

功能說明:該模型被稱爲「InsuranceLine」,它有一個集合「InsuranceLine.Letters」。每封信都有一個可空布爾屬性「Letter.IsDeficient」。如果「IsDeficient」從False更改爲True,則字符串字段「Letter.ReasonCode」是必需的。 「IsDeficient」呈現爲複選框,「ReasonCode」呈現爲兩個單選按鈕「已更正」和「已放棄」。

這是自定義屬性:

public class ReasonCodeAttribute : ValidationAttribute, IClientValidatable 
    { 
     private const string errorMessage = "When 'Deficient' is changed from True to False you must select a Reason."; 

     public IEnumerable<ModelClientValidationRule> GetClientValidationRules(ModelMetadata metadata, ControllerContext context) 
     { 
      yield return new ModelClientValidationRule 
      { 
       ErrorMessage = errorMessage, 
       ValidationType = "reasoncoderequired" 
      }; 
     } 

     protected override ValidationResult IsValid(object value, ValidationContext validationContext) 
     { 
      Letter letter = validationContext.ObjectInstance as Letter; 
      if(!letter.IsDeficient.GetValueOrDefault() 
       && letter.IsDeficient_OriginalState.GetValueOrDefault() 
       && (value == null || string.IsNullOrEmpty(value.ToString()))) 
      { 
       return new ValidationResult(errorMessage); 
      } 
      else 
      { 
       return null; 
      } 
     } 
    } 

我裝點Letter.ReasonCode與自定義屬性:

[ReasonCodeAttribute] 
public string ReasonCode { get; set; } 

我渲染嵌套字母集合中的* .cshtml頁:

@for (int i = 0; i < Model.Letters.Count; i++) 
{ 
@Html.EditorFor(m => m.Letters[i].IsDeficient, "MyCustomTemplate", new { htmlAttributes = new { @class="cb-is-deficient" } }) 
<div class="rb-reason-code"> 
    <label>@Html.RadioButtonFor(m => m.Letters[i].ReasonCode, myVar == "C", new { id = id + "C", @class ="rb-reason-code" }) Corrected</label> 
    &nbsp;&nbsp; 
    <label>@Html.RadioButtonFor(m => m.Letters[i].ReasonCode, myVar == "W", new { id = id + "W", @class = "rb-reason-code" }) Waived</label> 
</div> 
} 

ReasonCode屬性的GetClientValidationRules()方法會導致asp。淨運行時生成以下屬性時它呈現ReasonCode到HTML單選按鈕:

data-val-reasoncoderequired="When 'Deficient' is changed from True to False you must select a Reason.". 

在JavaScript我添加「reasoncoderequired」的方法來驗證,像這樣在文檔準備方法。由於我的解決辦法的一部分,我需要的類「錯誤」手動添加到我的顯示器,使用戶獲得了該模型的無效狀態的視覺提示:

$.validator.addMethod('reasoncoderequired', function (value, element) { 
     var $parent = $(element).closest('div.parent'); 
     var $cb = $parent.find('input[type="checkbox"].cb-is-deficient'); 
     if ($cb.prop('defaultChecked')) { 
      var $selectedRadioButton = $parent.find('div.rb-reason-code').find('input[type="radio"]:checked'); 
      if ($selectedRadioButton.length == 0) { 
       $parent.addClass('error'); 
       return false; 
      } 
     } 
     $parent.removeClass('error'); 
     return true; 
    }); 

最後,我想補充reasoncoderequired規則,每個ReasonCode單選按鈕就像這樣,也是在文檔準備好的方法中。 「消息」簡單地從每個輸入呈現的數據-VAL-reasoncoderequired屬性讀取顯示錯誤消息:

 $form.find('input[type="radio"].rb-reason-code').each(function() { 
     $(this).rules('add', 
      { 
       reasoncoderequired: true, 
       messages: { reasoncoderequired: $(this).attr('data-val-reasoncoderequired') } 
      }); 
    })