FileExtension使用自定义validation进行validation会创建重复且无效的data- *属性
在我从前一个问题中提到的答案中尝试过之后,这个问题就出现了。 我完全按照本文的方式对image files
validation,而不是文章中提到的doc files
。
说明:我有一个type=file
的input
控件,用于上传图像文件,这存在于其中一个部分partialview
。 click
partialview
会在click
button
时加载。 要应用model
提到的validations
,请明确unobtrusive
向form
添加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-*
属性,这正是你的代码生成的。 您生成一个名为fileextensions
的ClientValidationRule
( ValidationType = "fileextensions";
代码),然后添加一个名为fileextensions
的属性( ValidationParameters.Add("fileextensions", ..)
代码,该代码生成data-val-fileextensions-fileextensions="png,jpg,jpeg"
。至于data-val-fileextensions=""
,它是为了存储错误信息而生成的,但是你没有生成错误信息,所以它是一个空字符串。
我建议您对代码进行一些更改。
- 将其重命名为
FileTypeAttribute
以便您可以灵活地添加其他文件validation属性,例如FileSizeAttribute
以validation最大大小。 - 在构造函数中,生成一个默认的错误消息,例如add
private const string _DefaultErrorMessage = "Only the following file types are allowed: {0}";
并且在构造函数的最后一行包括ErrorMessage = string.Format(_DefaultErrorMessage, string.Join(" or ", ValidExtensions));
- 将
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; }