0

I am trying to send a bunch of form data from my view and map it to a ViewModel parameter in my controller. In addition, I am trying to send a file with this request which will map to a separate parameter.

When formData is sent through to the controller, it correctly maps the file upload to the file parameter, however, the model parameter properties are all null/defaults.

In summary, my question is this: how do I map my form element values to to MyViewModel paramter in my controller whilst sending a file too?

Model:

public class MyViewModel
{
    public int AsssumptionSetId { get; set; }
    public int BuildingBlockId { get; set; }
    public string ReplacementCode { get; set; }
    public decimal Rounding { get; set; }
    public string DataSource { get; set; }
    public bool AER { get; set; }
    public int Term { get; set; }
}

View:

This view is strongly typed to the MyViewModel:

<form id="buildingBlockForm">

    @Html.HiddenFor(model => model.AsssumptionSetId)
    @Html.HiddenFor(model => model.BuildingBlockId)

    @Html.TextBoxFor(m => m.ReplacementCode)

    @Html.TextBoxFor(m => m.Rounding)

    @Html.DropDownListFor(m => m.DataSource, (SelectList)ViewBag.DataSources)

    @Html.DropDownListFor(m => m.Term, (SelectList)ViewBag.Terms)

    @Html.CheckBoxFor(m => m.AER)

    <input type="file" id="file" name="file" />

    <input class="button green-button" type="submit" value="Create" />

</form>

Controller:

  public ActionResult CreateBuildingBlock(MyViewModel model, HttpPostedFileBase file)
        {
            // all of the 'model' properties = null instead of the form values
            // file = the file I chose to upload and works as expected
        }

JS:

var formData = new FormData($('#buildingBlockForm'));

// Get file and append to form data (Should only be 1)
$.each(Files["csv"], function (key, value) {
    formData .append("file", value);
});

// Send file
$.ajax({
    url: '/Assumptions/CreateBuildingBlock',
    type: 'POST',
    data: formData,
    cache: false,
    dataType: "json",
    contentType: false,
    processData: false,

    success: function (response) {
        // Handle success
    },
    error: function (xhr, status, errorThrown) {
        // Handle errors
    }
});
Tomuke
  • 869
  • 2
  • 8
  • 26
  • will this method still send the file? – Tomuke May 12 '15 at 15:57
  • 1
    did you try new FormData($('#buildingBlockForm')[0]); – Dennis C May 12 '15 at 16:05
  • `new FormData($('#buildingBlockForm')[0]);` was it! thank-you! Can you explain how/why this is needed? Post the answer @DennisCheung and I will accept. – Tomuke May 12 '15 at 16:07
  • possible duplicate of [how to append whole set of model to formdata and obtain it in MVC](http://stackoverflow.com/questions/29293637/how-to-append-whole-set-of-model-to-formdata-and-obtain-it-in-mvc) –  May 12 '15 at 23:29

2 Answers2

1

Turns out I was missing an index when grabbing the form that needs serializing.

new FormData($('#buildingBlockForm')[0]);

This solved my issue.

Tomuke
  • 869
  • 2
  • 8
  • 26
0

since your form contains a file-input type, you need your form to handle this submission (enctype).

<form id="buildingBlockForm" enctype="multipart/form-data"> 

Also, if you want to stick with MVC's form helper, it would alleviate the issues you may have with a script-based ajax post.

@using (Ajax.BeginForm("CreateBuildingBlock", "Assumptions", null, new AjaxOptions { HttpMethod = "POST", OnSuccess = "postSuccess", OnFailure = "postFailed" }, new { enctype = "multipart/form-data" }))
{
  // your form fields here
}

<script>
  function postSuccess() {
    // handle success here
  }

  function postfailed() {
    // handle failed post here
  }
</script>
Eckert
  • 690
  • 4
  • 9
  • Unfortunately the issue is not with the file posting and mapping to its parameter, as this works fine. The issue is with the remaining form values not mapping to the ViewModel object parameter. – Tomuke May 12 '15 at 16:04
  • did you try it with the form's type as suggested? I know you had a successful post with @Dennis suggestion, but that doesn't make sense to me on why adding [0] resolved your issue. – Eckert May 12 '15 at 16:12
  • Yes, the suggested solution works fine with and without the form type. – Tomuke May 12 '15 at 16:15