3.15.2013

Client-Side Validation for a Custom DataAnnonation in MVC 4

This is a continuation of my previous post. This is based from this excellent tutorial.

First step is to implement IClientValidatable interface in the FileTypesAttribute class:
public class FileTypesAttribute : ValidationAttribute, IClientValidatable {
        private readonly List _types;
        private readonly string specifiedTypes;

        public FileTypesAttribute(string types) {
            _types = types.Split(',').ToList();
            specifiedTypes = types;
        }

        public override bool IsValid(object value) {
            if (value == null) return true;
            var postedFile = value as HttpPostedFileBase;
            var fileExt = System.IO.Path.GetExtension(postedFile.FileName).Substring(1);
            return _types.Contains(fileExt, StringComparer.OrdinalIgnoreCase);
        }

        public override string FormatErrorMessage(string name) {
            return string.Format("Invalid file type. Only {0} are supported.", String.Join(", ", _types));
        }

        public IEnumerable GetClientValidationRules(ModelMetadata metadata, ControllerContext context) {
            var rule = new ModelClientValidationRule();
            rule.ErrorMessage = FormatErrorMessage(metadata.GetDisplayName());
            rule.ValidationType = "filetypes";
            rule.ValidationParameters.Add("types", specifiedTypes);
            yield return rule;
        }
    }
Things to note here are the validationtype="filetypes" and the added parameter="types", which can be observed in the emitted html below:
<input data-val="true" data-val-filetypes="Invalid file type. Only xls, xlsx are supported."
data-val-filetypes-types="xls,xlsx" data-val-required="The AttachmentTrace field is required."
id="AttachmentTrace" name="AttachmentTrace" type="file" value="" />
The added parameter called types has a value of "xls,xlsx". This parameter and validationtype are significant because it will be used for the jquery validator and adapter as follows:
$(function () {
    // custom validation method
    $.validator.addMethod("filetypes",
        function (value, element, params) {
            if (value == null) return true;
            var fileExtension = value.split('.').pop().toLowerCase();
            var types = params.toLowerCase();
            return types.indexOf(fileExtension) !== -1;
        }
    );
    // add to unobtrusive adapters
    $.validator.unobtrusive.adapters.addSingleVal("filetypes", "types");
} (jQuery));
The value has the contents of the input element, while params has the parameter value of "xls,xlsx" from the data annotation.

No comments:

Post a Comment