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

相关问题