代码之家  ›  专栏  ›  技术社区  ›  Renato Sanhueza

IClientValidator是否支持输入文件?

  •  -1
  • Renato Sanhueza  · 技术社区  · 6 年前

    编辑

    我发现问题是视图组件不能有@section( see ViewComponent and @Section #2910 )因此,使用不显眼的库添加自定义客户端验证似乎是不可能的(或者非常复杂)。此外,无法将所需的javascript包含到视图组件中,这让我后悔当初采用这种方法来模块化我的应用程序。。。


    模型的类

    public class UploadPanelModel
    {
        public int? ID { get; set; }
        public string Title { get; set; }
        public string Description { get; set; } //Raw HTML with the panel description
        [FileType(type:  "application/pdf")]
        [FileSize(maxSize: 5000000)]
        public IFormFile File { get; set; }
        public byte[] FileBytes { get; set; }
        public ModalModel Modal { get; set; } //Only used if the Upload panel uses a modal.
    

    public class FileSizeAttribute : ValidationAttribute, IClientModelValidator
    {
        private long _MaxSize { get; set; }
        public FileSizeAttribute (long maxSize)
        {
            _MaxSize = maxSize;
        }
        protected override ValidationResult IsValid(object value, ValidationContext validationContext)
        {
            UploadPanelModel panel = (UploadPanelModel)validationContext.ObjectInstance;
            return (panel.File==null || panel.File.Length <= _MaxSize) ?  ValidationResult.Success : new ValidationResult(GetFileSizeErrorMessage(_MaxSize));
        }
        private string GetFileSizeErrorMessage(long maxSize)
        {
            double megabytes = maxSize / 1000000.0;
            return $"El archivo debe pesar menos de {megabytes}MB";
        }
        public void AddValidation(ClientModelValidationContext context)
        {
            if(context == null)
            {
                throw new ArgumentNullException(nameof(context));
            }
            MergeAttribute(context.Attributes, "data-val", "true");
            MergeAttribute(context.Attributes, "data-val-filesize", GetFileSizeErrorMessage(_MaxSize));
            var maxSize = _MaxSize.ToString();
            MergeAttribute(context.Attributes, "data-val-filesize-maxsize", maxSize);         
        }
        private bool MergeAttribute(IDictionary<string, string> attributes, string key, string value)
        {
            if (attributes.ContainsKey(key))
            {
                return false;
            }
            attributes.Add(key, value);
            return true;
        }
    }
    

    Razor视图中的javascript

    @section Scripts{
    @{await Html.RenderPartialAsync("_ValidationScriptsPartial");}
    
    
    <script type="text/javascript">
        $.validator.addMethod('filesize',
            function (value, element, params) {
                var size = $((params[0]).val()).size(),
                    maxSize = params[1];
                if (size < maxSize) {
                    return false;
                }
                else {
                    return false;
                }
            }
        );
        $.validator.unobtrusive.adapters.add('filesize',
            ['maxSize'],
            function (options) {
                var element = $(options.form).find('input#File')[0];
                options.rules['filesize'] = [element, options.params['maxSize']];
                options.messages['filesize'] = options.message;
            }
        );
    </script>
    

    我总是在javascript方法中返回false,以强制应用程序显示验证错误,而不管选择的文件是什么,但它仍然不起作用。

    1 回复  |  直到 6 年前
        1
  •  1
  •   user3559349 user3559349    6 年前

    你的 addMethod() 函数将引发错误,因为 params[0] .val() $ 在错误的地方)。你需要使用

    var size = params[0].files[0].size;
    

    $.validator.unobtrusive.adapters.add('filesize', ['maxsize'], function (options) {
        options.rules['filesize'] = { maxsize: options.params.maxsize };
        if (options.message) {
            options.messages['filesize'] = options.message;
        }
    });
    
    $.validator.addMethod("filesize", function (value, element, param) {
        if (value === "") {
            return true;
        }
        var maxsize = parseInt(param.maxsize);
        if (element.files != undefined && element.files[0] != undefined && element.files[0].size != undefined) {
            var filesize = parseInt(element.files[0].size);
            return filesize <= maxsize ;
        }
        return true; // in case browser does not support HTML5 file API
    });