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

时间:2015-10-30 08:25:10

标签: jquery asp.net-mvc validation asp.net-mvc-3 jquery-validate

我在 my previous question 中提到的答案中尝试了这个问题。我跟着 this article 的方式完全相同,但文章中提到的image files而不是doc files的验证。

说明:我input type=file控制partialview上传图片文件,并存在partialview之一。 click加载button的{​​{1}}。要应用validations中提到的model,请明确将unobtrusive添加到form。但在按照上述文章中提到的所有设置后,我无法验证submit上的文件,data-*创建的unobtrusive validation也非常可疑或更好说无效。下面是显示我的设置的样子的代码,这里是html,它是由无效的data-*属性进行的不显眼验证创建的,可能是因为验证失败了。

<input data-charset="file" data-val="true" data-val-fileextensions="" data-val-fileextensions-fileextensions="png,jpg,jpeg" id="File" multiple="multiple" name="File" type="file" value="">

加载部分视图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" }))
{
    <div class="form-group">
        <span class="btn btn-default btn-file">
            Browse @Html.TextBoxFor(m => m.File, new { type = "file", multiple = "multiple", data_charset = "file" })
        </span>&nbsp;
        <span class="text-muted" id="filePlaceHolder">No files selected</span>
        @Html.ValidationMessageFor(m => m.File, null, htmlAttributes: new { @class = "invalid" })
    </div>
    <div class="form-group">
        <button class="btn btn-primary addImage pull-right">
            <i class="fa fa-upload"></i> Upload
        </button>
    </div>
}

最后是 CustomFileValidation

[AttributeUsage(AttributeTargets.Field | AttributeTargets.Property, AllowMultiple = false, Inherited = true)]
public class FileValidationAttribute : ValidationAttribute, IClientValidatable
{
    private List<string> 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<ModelClientValidationRule> GetClientValidationRules(ModelMetadata metadata, ControllerContext context)
    {
        var rule = new ModelClientFileExtensionValidationRule(ErrorMessage, ValidExtensions);
        yield return rule;
    }
}
public class ModelClientFileExtensionValidationRule : ModelClientValidationRule
{
    public ModelClientFileExtensionValidationRule(string errorMessage, List<string> fileExtensions)
    {
        ErrorMessage = errorMessage;
        ValidationType = "fileextensions";
        ValidationParameters.Add("fileextensions", string.Join(",", fileExtensions));
    }
}

1 个答案:

答案 0 :(得分:1)

您需要移动块代码

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

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

<script>
  $(function () {
    ....
  }(jQuery));

  $('.getpartial').on('click', function () { // or just $('.getpartial').click(function() {
    $('.loadPartial').empty().load('/Home/GetView',function () { // recommend .load('@Url.Action("GetView", "Home")', function() {
      var form = $('form#frmUploadImages');
      form.data('validator', null);
      $.validator.unobtrusive.parse(form);
    });
  });
</script>

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

旁注:您不需要在$(function () {中包装验证函数。它可以被删除,只需使用$.validator...代替jQuery.validator....,就像在代码中的其他位置一样。

至于&#39; fishy&#39; data-val-*属性,这正是您的代码生成的属性。您生成名为ClientValidationRule的{​​{1}}(fileextensions代码),然后添加名为ValidationType = "fileextensions";的{​​{1}}属性fileextensions代码生成{{ 1}}。至于ValidationParameters.Add("fileextensions", ..),它是为了存储错误信息而生成的,但你没有生成错误信息,所以它是一个空字符串。

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

  1. 将其重命名为data-val-fileextensions-fileextensions="png,jpg,jpeg",以便您具有灵活性 例如,添加其他文件验证属性 data-val-fileextensions=""验证最大大小。
  2. 例如,在构造函数中,生成默认错误消息 添加FileTypeAttribute并在构造函数的最后一行包含FileSizeAttribute
  3. 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", ...)
  4. 修改

    您的代码无法与data-val-fileextensions-validtypes="png,jpg,jpeg"一起使用为了实现此目的,您的媒体资源必须为...add('fileextensions', ['validtypes'], function() ....(请注意对您的代码进行一些细微更改)

    <input type="file" multiple="multiple" ... />

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

    IEnumerable

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

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