- JQuery Validation: Add custom method to validate on submit
- var totalFileSize = 0;
- $("input:file").each(function () {
- var file = $(this)[0].files[0];
- if (file) totalFileSize += file.size;
- });
- return totalFileSize < maxFileSize; // I've set maxFileSize elsewhere.
- public class MyViewModel
- {
- [MaxFileSize(2 * 1024 * 1024, ErrorMessage = "The total file size should not exceed {0} bytes")]
- public IEnumerable<HttpPostedFileBase> Files { get; set; }
- }
- public class MaxFileSizeAttribute : ValidationAttribute, IClientValidatable
- {
- public MaxFileSizeAttribute(int maxTotalSize)
- {
- MaxTotalSize = maxTotalSize;
- }
- public int MaxTotalSize { get; private set; }
- public override bool IsValid(object value)
- {
- var files = value as IEnumerable<HttpPostedFileBase>;
- if (files != null)
- {
- var totalSize = files.Where(x => x != null).Sum(x => x.ContentLength);
- return totalSize < MaxTotalSize;
- }
- return true;
- }
- public override string FormatErrorMessage(string name)
- {
- return base.FormatErrorMessage(MaxTotalSize.ToString());
- }
- public IEnumerable<ModelClientValidationRule> GetClientValidationRules(ModelMetadata metadata, ControllerContext context)
- {
- var rule = new ModelClientValidationRule
- {
- ErrorMessage = FormatErrorMessage(MaxTotalSize.ToString()),
- ValidationType = "maxsize"
- };
- rule.ValidationParameters["maxsize"] = MaxTotalSize;
- yield return rule;
- }
- }
- public class HomeController : Controller
- {
- public ActionResult Index()
- {
- return View(new MyViewModel());
- }
- [HttpPost]
- public ActionResult Index(MyViewModel model)
- {
- if (!ModelState.IsValid)
- {
- // Server side validation failed => redisplay the view so
- // that the user can fix his errors
- return View(model);
- }
- // Server side validation passed => here we can process the
- // model.Files collection and do something useful with the
- // uploaded files knowing that their total size will be smaller
- // than what we have defined in the custom MaxFileSize attribute
- // used on the view model
- // ...
- return Content("Thanks for uploading all those files");
- }
- }
- @model MyViewModel
- <script src="@Url.Content("~/Scripts/jquery.validate.js")" type="text/javascript"></script>
- <script src="@Url.Content("~/Scripts/jquery.validate.unobtrusive.js")" type="text/javascript"></script>
- <script type="text/javascript">
- (function ($) {
- $.validator.unobtrusive.adapters.add('maxsize', ['maxsize'], function (options) {
- options.rules['maxsize'] = options.params;
- if (options.message) {
- options.messages['maxsize'] = options.message;
- }
- });
- $.validator.addMethod('maxsize', function (value, element, params) {
- var maxSize = params.maxsize;
- var $element = $(element);
- var files = $element.closest('form').find(':file[name=' + $element.attr('name') + ']');
- var totalFileSize = 0;
- files.each(function () {
- var file = $(this)[0].files[0];
- if (file && file.size) {
- totalFileSize += file.size;
- }
- });
- return totalFileSize < maxSize;
- }, '');
- })(jQuery);
- </script>
- @Html.ValidationMessageFor(x => x.Files)
- @using (Html.BeginForm(null, null, FormMethod.Post, new { enctype = "multipart/form-data" }))
- {
- <div>
- @foreach (var item in Enumerable.Range(1, 3))
- {
- @Html.TextBoxFor(x => x.Files, new { type = "file" })
- }
- </div>
- <button type="submit">OK</button>
- }