0

I have a contact form in a page that looks like this:

@model LessonsLearned.Domain.Common.ViewModels.ContactFormViewModel

@using (Html.BeginForm("SubmitForm", "Help", FormMethod.Post, new { enctype = "multipart/form-data" }))
{
<p>@LLResources.GetResourceText("Question")</p>
<br />
<div class="row form-group">
   <div class="col-12">
      <b>@LLResources.GetResourceText("Admin_Email")</b>
   </div>
   <div class="col-12">
      @Html.EditorFor(model => model.Email, new { htmlAttributes = new { @class = "form-control", autocomplete = "off" } })
   </div>
</div>
<div class="row form-group">
   <div class="col-12">
      <b>@LLResources.GetResourceText("General_Name")</b>
   </div>
   <div class="col-12">
      @Html.EditorFor(model => model.Name, new { htmlAttributes = new { @class = "form-control", autocomplete = "off" } })
   </div>
</div>
<div class="row form-group">
   <div class="col-12">
      <b>@LLResources.GetResourceText("Admin_SchoolName")</b>
   </div>
   <div class="col-12">
      @Html.EditorFor(model => model.SchoolName, new { htmlAttributes = new { @class = "form-control", autocomplete = "off" } })
   </div>
</div>
<div class="row form-group">
   <div class="col-12">
      <b>@LLResources.GetResourceText("Message")</b>
   </div>
   <div class="col-12">
      @Html.EditorFor(model => model.Message, new { htmlAttributes = new { @class = "form-control", autocomplete = "off" } })
   </div>
</div>
<div class="row form-group">
   <div class="col-12">
      <b>@LLResources.GetResourceText("Observation_Attachments")</b>
   </div>
   <div class="col-12">
      @Html.TextBoxFor(m => m.File, new { type = "file" })
      @Html.ValidationMessageFor(m => m.File)
   </div>
</div>
<div class="row">
   <div class="col-12">
      <input type="submit" value="Submit" class="btn btn-success float-md-right mr-md-2" />
   </div>
</div>
}

The model behind the page looks like this:

public class ContactFormViewModel
    {
        [Required(ErrorMessage = "Email address is required.")]
        [EmailAddress(ErrorMessage = "Must be a valid email address.")]
        public string Email { get; set; }
        [Required(ErrorMessage = "Name is required.")]
        public string Name { get; set; }
        [Required(ErrorMessage = "School name is required.")]
        public string SchoolName { get; set; }
        [Required(ErrorMessage = "Message is required.")]
        [DataType(DataType.MultilineText)]
        public string Message { get; set; }
        [FileExtensions(Extensions = "jpg, jpeg, png")]
        public HttpPostedFileBase File { get; set; }

    }

And then finally in my controller I have:

[HttpPost]
        public ActionResult SubmitForm(ContactFormViewModel contactFormViewModel)
        {
            if (ModelState.IsValid)
            {
                //Do stuff
                ViewBag.result = "Form submitted successfully!";
                return View("Index", new ContactFormViewModel());
            }
            else
            {
                //Don't do stuff
                ViewBag.result = "Form was not submitted, please fix errors.";
                return View("Index", contactFormViewModel);
            }

            return RedirectToAction("Index");
        }

For some reason when I upload a jpg on png to the form and try and submit, ModelState keeps telling me that there is an error - "The File field only accepts files with the following extensions: .jpg, .jpeg, .png". It's definitely a jpg or png I'm uploading. Why does it not recognise that?

Hannah Hayes
  • 161
  • 17
  • Are the missing open quotes only a typo in copying the code here `, new { enctype = multipart/form-data" }))`? – Josh Mein Feb 21 '23 at 14:40
  • Yes a typo in copying code here, apologies I will sort. – Hannah Hayes Feb 21 '23 at 14:42
  • Per the following answer, the extensions cannot have spaces between them for the FileExtensions data annotation attribute: https://stackoverflow.com/a/33257613/2486. – Josh Mein Feb 21 '23 at 14:52
  • Does this answer your question? [How to use multiple file extensions using DataAnnotations?](https://stackoverflow.com/questions/33257347/how-to-use-multiple-file-extensions-using-dataannotations) – Josh Mein Feb 21 '23 at 14:55
  • @JoshMein you're correct and I've changed it to `[FileExtensions(Extensions = "jpg,jpeg,png")]` but unfortunately same issue - ModelState is still recognising it as invalid. – Hannah Hayes Feb 21 '23 at 15:00
  • Have you debugged the code to verify that the file and filename are being posted to the controller? – Josh Mein Feb 21 '23 at 15:09
  • To be honest I'm not entirely sure how to do that. Does using HttpPostedFileBase not guarantee that? – Hannah Hayes Feb 21 '23 at 15:12
  • @JoshMein if I look at what's being passed via the model I can see that File has a ContentType of "image/jpeg". – Hannah Hayes Feb 21 '23 at 15:14
  • I was asking because you dont have the File field as required so there could be something I am not noticing, and the file wasnt being posted to the controller at all. – Josh Mein Feb 21 '23 at 15:16
  • I have just noticed that it appears in the model as part of the parameter passed to the method, but when I look at the value for File in ModelState it appears to be null? – Hannah Hayes Feb 21 '23 at 15:21
  • @HannahHayes try to rename the Property 'File' in your ContactFormViewModel to Something else, like 'FileUpload'. This'll probably fix it and you'll see the object. This is because when MVC tries to convert this object, it thinks it's a System.IO.File and not a file upload. If you call properties the same name as .NET classes in this POST it silently breaks during the conversion to the c# world, but doesn't tell you. I've lost countless hours to this little gotcha. – Tom Ruyter Feb 21 '23 at 16:22
  • @TomRuyter I really though that was going to be the answer but it's still erroring! This is driving me nuts! – Hannah Hayes Feb 21 '23 at 17:39
  • @HannahHayes I've mocked this up and it's the [FileExtensions] Attribute applied to the File property of the Model. From my research The FileExtensions Attribute in MVC doesn't know how to parse the file name of the uploaded file so it's always in an invalid state when you apply this attribute. See the answer to [This post](https://stackoverflow.com/questions/8536589/asp-net-mvc-3-dataannotations-fileextensionsattribute-not-working/13650754#13650754) if that makes sense. if you remove the attribute it'll work as expected and you can do your own file name validation from the posted file. – Tom Ruyter Feb 22 '23 at 09:17
  • @TomRuyter Thanks Tom, I went ahead and did as you suggested and I've got a working solution. – Hannah Hayes Feb 22 '23 at 10:10

0 Answers0