84

How do I pass a whole set model object through formdata and convert it to model type in the controller?

Below is what I've tried!

JavaScript part:

model = {
             EventFromDate: fromDate,
             EventToDate: toDate,
             ImageUrl: imgUrl,
             HotNewsDesc: $("#txthtDescription").val().trim(),
        };
formdata.append("model",model);

then pass it through AJAX, it will be a string, and if I check the value of Request.Form["model"] the result will be same, that is it will be received as string and value will be "[object object]"

Is there any way to pass model through formdata and receive it in the controller?

River
  • 8,585
  • 14
  • 54
  • 67
Guruprasad J Rao
  • 29,410
  • 14
  • 101
  • 200
  • Didn't I just answer this [here](http://stackoverflow.com/questions/29287311/how-to-append-datetime-value-to-formdata-and-receive-it-in-controller)? –  Mar 27 '15 at 05:05
  • I have dropped a comment @StephenMuecke. That's why I posted it here... – Guruprasad J Rao Mar 27 '15 at 05:06

4 Answers4

95

If your view is based on a model and you have generated the controls inside <form> tags, then you can serialize the model to FormData using

var formdata = new FormData($('form').get(0));

This will also include any files generated with <input type="file" name="myImage" .../>

and post it back using

$.ajax({
  url: '@Url.Action("YourActionName", "YourControllerName")',
  type: 'POST',
  data: formdata,
  processData: false,
  contentType: false,         
});

and in your controller

[HttpPost]
public ActionResult YourActionName(YourModelType model)
{
}

or (if your model does not include a property for HttpPostedFileBase)

[HttpPost]
public ActionResult YourActionName(YourModelType model, HttpPostedFileBase myImage)
{
}

If you want to add additional information that is not in the form, then you can append it using

formdata.append('someProperty', 'SomeValue');
  • 2
    @StephenMuecke Thank you very much. It is really one of the hardest issue regarding to Ajax call and with the help of you, it is solved :) I am wondering if it is also possible with `Html.BeginForm` and `Ajax.BeginForm` instead of `
    `? If so, what changes should be applied?
    – Jack Jun 20 '15 at 10:14
  • 2
    Yes, it's possible with `Html.BeginForm()` to include files with a normal submit normal. Sorry, I'm a little lost. Which question was this in reference to? –  Jun 21 '15 at 10:15
  • @StephenMuecke No, you have never lost and always help :) This question is related to [that](http://stackoverflow.com/questions/30952049/how-to-pass-kendo-dropdownlist-datatextfield-value-to-controller?noredirect=1#comment49938070_30952049) question. – Jack Jun 21 '15 at 10:42
  • I see it's possible with Html.BeginForm(). Would it be possible with Ajax.BeginForm()? – Luis Gouveia Dec 11 '15 at 10:27
  • 3
    @LuisGouveia, No its not with `Ajax.BeginForm()`. In any case the `Ajax` methods are obsolete (they are not even included in the latest version of MVC) and using `$.ajax()` (or its derivatives such as `$.get()`, `$.load()` etc give you much more flexibility. –  Dec 11 '15 at 10:33
  • @StephenMuecke, thank you for your answer. Ok, but I can use xhr.open + xhr.send right? My goal is to post asynchronously the form data (that contains a viewmodel which one of its 8 properties is a file) – Luis Gouveia Dec 11 '15 at 10:36
  • 2
    @LuisGouveia, Yes thats another option, but why not just use `FormData` as per the answer? (or are you needing this for older browsers which dont support it?) –  Dec 11 '15 at 10:39
  • @StephenMuecke, yes, that's what I'm doing. I am implementing the approved solution stated here: http://stackoverflow.com/questions/2428296/jquery-ajax-upload-file-in-asp-net-mvc/14674531#14674531 but I have one important difference: Unlike the example case, I need to post not only the file, but also other properties like strings and doubles. That's why I am so interested on this post we're on (because it plans to post the entire form and not only a file): I need the best of both worlds. – Luis Gouveia Dec 11 '15 at 10:50
  • @StephenMuecke, "or (if your model does not include a property for HttpPostedFileBase". I had tried to do a ko.toJSON(viewModel) which gives me a JSON object. I need to sent the object to controller method such that it is received as another parameter (like in your example YourModelType model). It does not happen. But if i stringify and store the value as a string in a hidden input, i can use a string parameter to capture it in my controller method. I could never map the object to a ViewModel and also send uploaded file data at a time. Link: http://stackoverflow.com/q/36643191/1379746 – zapper Apr 15 '16 at 12:38
  • @zapper, You do not need 2 separate calls as per the answer you accepted in that question (and its poor performance to do so). You ca just use `var formData = new FormData($("#photoForm")[0]);` and the append each of the name/value pairs from the `ko.toJSON()` object. –  Apr 16 '16 at 05:03
  • @StephenMuecke, My actual knockout object is extremely huge. It contains over 20 properties and 2 of them are arrays with around 10 to 15 properties and within one of the arrays, i have 2 more arrays with 5 to 10 properties. So, it's a pretty complex form and mapping each and every property as name/value pairs would be tedious and also there's another problem where i have to get the values 1 by 1 and map them to my view model properties. Since i could never get both, the uploaded file(s) and entire ViewModel even as different parameters at the same time, i had to take the 2 ajax call approach. – zapper Apr 17 '16 at 10:40
  • I have got the files post back using Request.Files – Minh Nguyen Nov 15 '16 at 14:38
  • Hi, it works for me but there is something that I don't understad, If I use the var formdata = new FormData($('form').get(0)); parameter in the ajax, its ok, but the ajax shows me the result in another page, why? if I use "data: $(this).serialize()", this doesn't happen – Mitch3091 Mar 31 '17 at 21:53
  • @FernandoAguilar, I'm not sure what your mean by _shows me the result in another page_ - `new FormData($('form').get(0));` and `$(this).serialize()` are both just serializing the data from the form controls and have nothing to do with the actual ajax call. You will need to ask a new question with more detail and code to understand what your issue is. –  Mar 31 '17 at 22:04
  • can i use MVC data annotations with this way of posting data and file ? – Akshay Chawla Apr 19 '17 at 12:11
  • @AkshayChawla, Not sure what you mean. Data annotations are not related to posting data. –  Apr 19 '17 at 22:57
  • what about if we want to upload multiple files? – MSH Sep 13 '17 at 09:02
  • 2
    @MSH, It will upload multiple files (the parameter would just need to be `IEnumerable` if you had a `` –  Sep 13 '17 at 09:04
  • @StephenMuecke, Great help. – MVC Jul 25 '18 at 23:56
23

If you want to send Form data using Ajax.This is the way to send

var formData = new FormData();

//File Upload
   var totalFiles = document.getElementById("Iupload").files.length;


for (var i = 0; i < totalFiles; i++) {
    var file = document.getElementById("Iupload").files[i];

    formData.append("Document", file);
}

formData.append("NameCode", $('#SelecterID').val());
formData.append("AirLineCode", $('#SelecterID').val());


$.ajax({
        url: "/Controller/ActionName",
        type: "POST",
        dataType: "JSON",
        data: formData,
        contentType: false,
        processData: false,
        success: function (result) {
    }
})
Deendayal Garg
  • 5,030
  • 2
  • 19
  • 33
user3824027
  • 440
  • 3
  • 10
0

Using Pure Javascript, considering you have

<form id="FileUploadForm">
   <input id="textInput" type="text" />
  <input id="fileInput" type="file" name="fileInput" multiple>
  <input type="submit" value="Upload file" />
</form>

JS

document.getElementById('FileUploadForm').onsubmit = function () {

var formdata = new FormData(); //FormData object

var fileInput = document.getElementById('fileInput');

//Iterating through each files selected in fileInput
for (i = 0; i < fileInput.files.length; i++) {
    //Appending each file to FormData object
    formdata.append(fileInput.files[i].name, fileInput.files[i]);
}
//text value
formdata.append("textvalue",document.getElementById("textInput").value);

//Creating an XMLHttpRequest and sending
var xhr = new XMLHttpRequest();
xhr.open('POST', '/Home/UploadFiles');
xhr.send(formdata); // se
xhr.onreadystatechange = function () {
    if (xhr.readyState == 4 && xhr.status == 200) {
        //on success alert response
        alert(xhr.responseText);
    }
  }
  return false;
}  

in your C# controller you can get values it as below

[HttpPost]
public ActionResult UploadFiles(YourModelType model, HttpPostedFileBase fileInput)
{
      //save data in db
}

Reference : File Uploading using jQuery Ajax or Javascript in MVC

Vikas Lalwani
  • 1,041
  • 18
  • 29
-1

In view side ,if you are using ajax then,

$('#button_Id').on('click', function(){
        var Datas=JSON.stringify($('form').serialize());
        $.ajax({
            type: "POST",
            contentType: "application/x-www-form-urlencoded; charset=utf-8",
            url: '@Url.Action("ActionName","ControllerName")',
            data:Datas,
            cache: false,
            dataType: 'JSON',
            async: true,
            success: function (data) {

            },
        });
    });

In Controller side,

 [HttpPost]
 public ActionResult ActionName(ModelName modelObj)
 {
 //Some code here
 }
Sam
  • 1