10

I am trying to upload a file using HTML FileUpload control in MVC. I want to validate the file to accept only specific extensions. I have tried using FileExtensions attribute of DataAnnotations namespace, but its not working. See code below -

public class FileUploadModel
    {
        [Required, FileExtensions(Extensions = (".xlsx,.xls"), ErrorMessage = "Please select an Excel file.")]
        public HttpPostedFileBase File { get; set; }
    }

In the controller, I am writing the code as below -

[HttpPost]
        public ActionResult Index(FileUploadModel fileUploadModel)
        {
            if (ModelState.IsValid)
                fileUploadModel.File.SaveAs(Path.Combine(Server.MapPath("~/UploadedFiles"), Path.GetFileName(fileUploadModel.File.FileName)));

            return View();
        }

In View, I have written below code -

@using (Html.BeginForm("Index", "FileParse", FormMethod.Post, new { enctype = "multipart/form-data"} ))
{
    @Html.Label("Upload Student Excel:")
    <input type="file" name="file" id="file"/>
    <input type="submit" value="Import"/>
    @Html.ValidationMessageFor(m => m.File)
}

When i run the application and give an invalid file extension, its not showing me the error message. I am aware of solution to write custom validation attribute, but I dont want to use custom attribute. Please point out where I am going wrong.

DfrDkn
  • 1,270
  • 2
  • 16
  • 23
  • Might be helpful: http://stackoverflow.com/questions/14718425/cant-get-mvc-4-fileextensions-attribute-to-work-on-viewmodel-property – serhiyb Jul 12 '15 at 09:27
  • @serhiyb Thanks for your reply. I have gone through that solution. But I don't want to use custom attribute , I want to use attribute which is already provided by .NET. Am I doing something wrong or Is there some issue in Microsoft provided attribute? – DfrDkn Jul 12 '15 at 09:39
  • Since FileExtensions attribute works fine in MVC5 (just tested) I assume there is an issue with it in lower versions. – serhiyb Jul 12 '15 at 09:54
  • Hi, Maybe this can help you... http://stackoverflow.com/questions/8536589/asp-net-mvc-3-dataannotations-fileextensionsattribute-not-working – HectorMenchaca Jul 13 '15 at 17:42

4 Answers4

9

I had the same problem and I resolved creating a new ValidationAttribute.

Like this:

    [AttributeUsage(AttributeTargets.Field | AttributeTargets.Property, AllowMultiple = false, Inherited = true)]
    public class FileExtensionsAttribute : ValidationAttribute
    {
        private List<string> AllowedExtensions { get; set; }

        public FileExtensionsAttribute(string fileExtensions)
        {
            AllowedExtensions = fileExtensions.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries).ToList();
        }

        public override bool IsValid(object value)
        {
            HttpPostedFileBase file = value as HttpPostedFileBase;

            if (file != null)
            {
                var fileName = file.FileName;

                return AllowedExtensions.Any(y => fileName.EndsWith(y));
            }

            return true;
        }
    }

Now, just use this:

[FileExtensions("jpg,jpeg,png,gif", ErrorMessage = "Your error message.")]
public HttpPostedFileBase Imagem { get; set; }

I have helped. Hugs!

Rafael Botelho
  • 398
  • 5
  • 11
6

Like marai answered, the FileExtension Attribute only works on string properties.

In my code, i use the attribute as follows:

public class MyViewModel
{
    [Required]
    public HttpPostedFileWrapper PostedFile { get; set; }

    [FileExtensions(Extensions = "zip,pdf")]
    public string FileName
    {
        get
        {
            if (PostedFile != null)
                return PostedFile.FileName;
            else
                return "";
         }
    }
}

Then, in server side, ModelState.IsValid will be false if the postedfile doesn't have the entensions that you specify in the attribute (.zip and .pdf in my example).

Note: If you are using the HTML.ValidationMessageFor helper to render the error message after PostBack (The File Extension Attribute does not validate on client side, only server side), you need to specify another helper for the FileName property in order to display the extension error message:

@Html.ValidationMessageFor(m => m.PostedFile)
@Html.ValidationMessageFor(m => m.FileName)
Miguel Ramirez
  • 321
  • 3
  • 9
  • Thanks this works great if there's file selected. But if there's no file selected, only the Required validation should fire. In this case, both validations does. Is there remedy for this issue? – Patee Gutee Mar 21 '21 at 20:54
  • I got it working! When PostedFile is null, it should return null instead of returning "". – Patee Gutee Mar 21 '21 at 21:11
3

The FileExtensions Attribute does not know how to verify a HttpPostedFileBase. Please try below

[FileExtensions(Extensions = "xlsx|xls", ErrorMessage = "Please select an Excel file.")]
public string Attachment{ get; set; }

In your controller:

[HttpPost]
    public ActionResult Index(HttpPostedFileBase Attachment)
    {
        if (ModelState.IsValid)
        {
            if (Attachment.ContentLength > 0)
            {
                string filePath = Path.Combine(HttpContext.Server.MapPath("/Content/Upload"), Path.GetFileName(Attachment.FileName));
                Attachment.SaveAs(filePath);
            }
        }
        return RedirectToAction("Index_Ack"});
    }
marai
  • 865
  • 1
  • 11
  • 16
1

I used the code above in FileExtensions attribute of DataAnnotations not working in MVC, I just did a couple of changes to: 1)avoid namespace collisions and 2) to use IFormFile instead of the original HttpPostedFileBase. Well, maybe is usefull to someone.

My code:

[AttributeUsage(AttributeTargets.Field | AttributeTargets.Property, AllowMultiple = false, Inherited = true)]
public class FileVerifyExtensionsAttribute : ValidationAttribute
{
    private List<string> AllowedExtensions { get; set; }

    public FileVerifyExtensionsAttribute(string fileExtensions)
    {
        AllowedExtensions = fileExtensions.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries).ToList();
    }

    public override bool IsValid(object value)
    {
        IFormFile file = value as IFormFile;

        if (file != null)
        {
            var fileName = file.FileName;

            return AllowedExtensions.Any(y => fileName.EndsWith(y));
        }

        return true;
    }
}
Daniel Silva
  • 817
  • 8
  • 16
  • A nice solution @DanielSilva. Works perfectly fine. But the downside is that, it's working only in **Server Side**. Is there any workaround, so that it works in **Client Side** as well? – Kash Feb 25 '21 at 12:29