FileExtension使用自定义validation进行validation会创建重复且无效的data- *属性

我从前一个问题中提到的答案中尝试过之后,这个问题就出现了。 我完全按照本文的方式对image filesvalidation,而不是文章中提到的doc files

说明:我有一个type=fileinput控件,用于上传图像文件,这存在于其中一个部分partialviewclick partialview会在click button时加载。 要应用model提到的validations ,请明确unobtrusiveform添加unobtrusive的内容。 但是在按照上述文章中提到的所有设置后,我无法validationsubmit的文件,而且通过unobtrusive validation创建的data-*非常可疑或更好地说无效。 下面是显示我的设置是什么样的代码,这里是通过使用无效data-*属性进行不显眼validation而创建的html ,可能是因为validation未能发生。

  

加载部分视图Js

 $('.getpartial').on('click', function () { $('.loadPartial').empty().load('/Home/GetView',function () { var form = $('form#frmUploadImages'); form.data('validator', null); $.validator.unobtrusive.parse(form); $(function () { jQuery.validator.unobtrusive.adapters.add('fileextensions', ['fileextensions'], function (options) { var params = { fileextensions: options.params.fileextensions.split(',') }; options.rules['fileextensions'] = params; if (options.message) { options.messages['fileextensions'] = options.message; } }); jQuery.validator.addMethod("fileextensions", function (value, element, param) { var extension = getFileExtension(value); var validExtension = $.inArray(extension, param.fileextensions) !== -1; return validExtension; }); function getFileExtension(fileName) { var extension = (/[.]/.exec(fileName)) ? /[^.]+$/.exec(fileName) : undefined; if (extension != undefined) { return extension[0]; } return extension; }; }(jQuery)); }) }) 

ModelClass

 public class ImageUploadModel { [FileValidation("png|jpg|jpeg")] public HttpPostedFileBase File { get; set; } } 

视图

 @model ProjectName.Models.ImageUploadModel @using (Html.BeginForm("UploadImages", "Admin", FormMethod.Post, htmlAttributes: new { id = "frmUploadImages", novalidate = "novalidate", autocomplete = "off", enctype = "multipart/form-data" })) { 
Browse @Html.TextBoxFor(m => m.File, new { type = "file", multiple = "multiple", data_charset = "file" })   No files selected @Html.ValidationMessageFor(m => m.File, null, htmlAttributes: new { @class = "invalid" })
}

最后是我的CustomFileValidation

 [AttributeUsage(AttributeTargets.Field | AttributeTargets.Property, AllowMultiple = false, Inherited = true)] public class FileValidationAttribute : ValidationAttribute, IClientValidatable { private List ValidExtensions { get; set; } public FileValidationAttribute(string fileExtensions) { ValidExtensions = fileExtensions.Split('|').ToList(); } public override bool IsValid(object value) { HttpPostedFileBase file = value as HttpPostedFileBase; if (file != null) { var fileName = file.FileName; var isValidExtension = ValidExtensions.Any(y => fileName.EndsWith(y)); return isValidExtension; } return true; } public IEnumerable GetClientValidationRules(ModelMetadata metadata, ControllerContext context) { var rule = new ModelClientFileExtensionValidationRule(ErrorMessage, ValidExtensions); yield return rule; } } public class ModelClientFileExtensionValidationRule : ModelClientValidationRule { public ModelClientFileExtensionValidationRule(string errorMessage, List fileExtensions) { ErrorMessage = errorMessage; ValidationType = "fileextensions"; ValidationParameters.Add("fileextensions", string.Join(",", fileExtensions)); } } 

您需要移动块代码

 $(function () { .... }(jQuery)); 

$('.getpartial').on(..)函数内部到它之前就是它

  

目前你加载内容,重新解析validation器,然后添加方法添加到jqueryvalidation但是它已经很晚了(validation器已被解析)

旁注:你不需要在$(function () {包装validation函数。它可以被删除,只需使用$.validator...而不是jQuery.validator....就像你在代码中的其他地方一样。

至于’fishy’ data-val-*属性,这正是你的代码生成的。 您生成一个名为fileextensionsClientValidationRuleValidationType = "fileextensions";代码),然后添加一个名为fileextensions的属性( ValidationParameters.Add("fileextensions", ..)代码,该代码生成data-val-fileextensions-fileextensions="png,jpg,jpeg" 。至于data-val-fileextensions="" ,它是为了存储错误信息而生成的,但是你没有生成错误信息,所以它是一个空字符串。

我建议您对代码进行一些更改。

  1. 将其重命名为FileTypeAttribute以便您可以灵活地添加其他文件validation属性,例如FileSizeAttribute以validation最大大小。
  2. 在构造函数中,生成一个默认的错误消息,例如add private const string _DefaultErrorMessage = "Only the following file types are allowed: {0}"; 并且在构造函数的最后一行包括ErrorMessage = string.Format(_DefaultErrorMessage, string.Join(" or ", ValidExtensions));
  3. ValidationParameters.Add("fileextensions", ...)更改为(例如) ValidationParameters.Add("validtypes", ...)以便生成data-val-fileextensions-validtypes="png,jpg,jpeg" ,这是一个更有意义(请注意,您需要将脚本更改为...add('fileextensions', ['validtypes'], function() ....

编辑

你的代码不适用于为了做到这一点,你的属性需要是IEnumerable (注意你的代码稍作修改)

 [FileType("png, jpg, jpeg")] public IEnumerable Files { get; set; } 

然后validation属性需要检查集合中的每个文件

 [AttributeUsage(AttributeTargets.Property, AllowMultiple = false, Inherited = true)] public class FileTypeAttribute : ValidationAttribute, IClientValidatable { private const string _DefaultErrorMessage = "Only the following file types are allowed: {0}"; private IEnumerable _ValidTypes { get; set; } public FileTypeAttribute(string validTypes) { _ValidTypes = validTypes.Split(',').Select(s => s.Trim().ToLower()); ErrorMessage = string.Format(_DefaultErrorMessage, string.Join(" or ", _ValidTypes)); } protected override ValidationResult IsValid(object value, ValidationContext validationContext) { IEnumerable files = value as IEnumerable; if (files != null) { foreach(HttpPostedFileBase file in files) { if (file != null && !_ValidTypes.Any(e => file.FileName.EndsWith(e))) { return new ValidationResult(ErrorMessageString); } } } return ValidationResult.Success; } public IEnumerable GetClientValidationRules(ModelMetadata metadata, ControllerContext context) { var rule = new ModelClientValidationRule { ValidationType = "filetype", ErrorMessage = ErrorMessageString }; rule.ValidationParameters.Add("validtypes", string.Join(",", _ValidTypes)); yield return rule; } } 

最后脚本需要检查每个文件

 $.validator.unobtrusive.adapters.add('filetype', ['validtypes'], function (options) { options.rules['filetype'] = { validtypes: options.params.validtypes.split(',') }; options.messages['filetype'] = options.message; }); $.validator.addMethod("filetype", function (value, element, param) { for (var i = 0; i < element.files.length; i++) { var extension = getFileExtension(element.files[0].name); if ($.inArray(extension, param.validtypes) === -1) { return false; } } return true; }); function getFileExtension(fileName) { if (/[.]/.exec(fileName)) { return /[^.]+$/.exec(fileName)[0].toLowerCase(); } return null; }