2

我有一個僱員包含功能列表的模型。員工至少應該有一個功能。如何在MVC中的對象的必需列表<>上獲得不顯眼的客戶端驗證?

public class Employee 
{ 
    [Required(ErrorMessage = "Name is Required")] 
    public string Name { get; set; } 

    [Required(ErrorMessage = "Email is Required")] 
    [RegularExpression(@"^([a-zA-Z0-9_\-\.]+)@((\[[0-9]{1,3}" + 
         @"\.[0-9]{1,3}\.[0-9]{1,3}\.)|(([a-zA-Z0-9\-]+\" + 
         @".)+))([a-zA-Z]{2,4}|[0-9]{1,3})(\]?)$", 
     ErrorMessage = "Email is not valid")] 
    public string Email { get; set; } 

    [Required(ErrorMessage = "At least one function is required")] 
    public List<Function> Functions { get; set; } 
} 

public class Function 
{ 
    [Required(ErrorMessage = "Name is Required")] 
    public string Name { get; set; } 
} 

我創建了一個EditorTemplate的功能

@model MvcClientSideValidation.Models.Function 

    <fieldset> 
     <legend>Functie</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> 

    </fieldset> 

索引視圖使用EditorFor和ValidationMessageFor。

@Html.EditorFor(m => m.Functions) 
@Html.ValidationMessageFor(m => m.Functions) 

視圖還包含添加或刪除函數的代碼。

提交視圖時,客戶端驗證不會檢查函數是否存在。服務器端驗證確實。問題是當列表爲空時,沒有爲Function屬性呈現輸入元素,因此沒有可以添加驗證標籤的標籤。

因此,我正在尋找一種簡單的方法來對List[Required]屬性進行不顯眼的客戶端驗證。

編輯:我剛剛意識到[必需的]屬性可能只會驗證Function不是null。它不會檢查它是否包含任何項目。這對我來說很好,因爲該屬性將在回發時自動變爲null。

回答

0

我認爲你的問題是你讓列表爲空。如果它確實需要一個函數存在,那麼從列表中的1個項目開始,沒有選擇任何項目。不要讓您的代碼添加或刪除項目以刪除最後一個項目,因此總是會有至少一個項目,並且驗證應該可以工作。

+0

也許我過分簡化了我的問題。在真正的解決方案中,上傳文件列表的模型以及至少一個文件應該被上傳。我真的在尋找一種解決方案來進行服務器端同樣的驗證。 – comecme

+0

@comecme - 是的,我所概述的會發生在客戶端。我不明白你的澄清。你總是至少有文本框1(空或不)。我假設您有某種添加項目功能可以增加您上傳的文件數量,以及從列表中刪除項目的刪除項目功能。只是不要讓最後一項被刪除,所以你總是至少有一組表單域來驗證。 –

+0

這意味着如果文件名爲空,我必須確保我不呈現任何內容。另外,上傳文件時,如果列表只包含一個空文件名,我應該使用該條目。對於第二個文件,我必須將新條目添加到列表中。沒有我想要的那麼簡單。 – comecme

1

嘗試這種情況:

[RequiredEnumerable(ErrorMessage = "At least one function is required")] 
[UIHint("FunctionCollection")] // -> EditorTemplate partial view, it ensures that the input is generated. 
public List<Function> Functions { get; set; } 

RequiredEnumerable類:

public class RequiredEnumerableAttribute : ValidationAttribute, IClientValidatable 
{ 
    public override bool IsValid(object value) 
    { 
     var enumerable = value as IEnumerable; 
     if (enumerable == null) return false; 

     IEnumerator enumerator = enumerable.GetEnumerator(); 
     if (enumerator.MoveNext()) 
      return true; 
     return false; 
    } 

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

FunctionCollection局部視圖(/Views/Shared/EditorTemplates/FunctionCollection.cshtml):

@model IEnumerable<Function> 
@{ 
    Function[] models = Model != null ? Model as Function[] ?? Model.ToArray() : new Function[0]; 
    string value = Newtonsoft.Json.JsonConvert.SerializeObject(models.Select(x => x.Name)); 
} 
@Html.Hidden(String.Empty, value) 
@Html.ValidationMessage(String.Empty) 
@if (models.Any()) 
{ 
    <ul> 
     @foreach (Function f in models) 
     { 
      <li>@f.Name</li> 
     } 
    </ul> 
} 
@Ajax.ActionLink("Edit functions", "Index", "Function", new { selectedFunctions = value }, new AjaxOptions { }) 
在JavaScript

<script> 
    // create and append method 'requiredenumerable' to $.validator (before $.ready) 
    $.validator.addMethod("requiredenumerable", function (value) { 
     value = $.trim(value); 
     if (!value.length) return false; 

     //assumes that value is either a json array or a string of comma separated values​​ 
     var arr = value.indexOf("[") === 0 ? $.parseJSON(value) : value.split(","); 
     return arr && arr.length > 0; 
    }); 
    $.validator.unobtrusive.adapters.addBool("requiredenumerable"); 

    // as #Functions input is hidden so we need adapt the validator object (inside $.ready) 
    $(document).ready(function() { 
     var elemSelector = "#Functions"; 
     var validator = $(elemSelector).closest("form").data("validator"); 
     if (validator) { 
      validator.settings.ignore = ":hidden:not(" + elemSelector + ")"; 
     } 
    }); 
</script> 
+0

什麼是正在生成的HTML?因爲根據[Brad Wilson](http://forums.asp.net/post/4352873。aspx)使用這種方式不支持使用EditorTemplates的不顯眼的驗證... – janv8000

+0

您能顯示FuctionCollection編輯器模板的內容嗎? – janv8000

+0

@ janv8000,我修改了我的答案,使其更清晰。我目前正在使用它,它工作正常。 – Charlie

相關問題