user12585721
user12585721

Reputation:

Model Binding in Asp.Net Core from an Ajax call

I have a Javascript function that makes a call to a Asp.Net Core controller:

    const details =
    {
        thisModel: {
            Id: '@Model.OrderId',
            Name: '@Model.Name',
            Data: data,
            StringData: ''
        }
    };

    const data = JSON.stringify(details);

    $.ajax({                    
        type: "POST",
        url: "/Orders/CreateOrder",
        data: data,
        datatype: "json",
        contentType: 'application/json; charset=utf-8',
        success: function (data) {
            // Success!
        }
    });

I'm trying to call an Asp.Net Core controller method:

    [HttpPost]
    public async Task<IActionResult> CreateOrder([FromBody]OrderDetails orderDetails)
    {

The OrderDetails model looks like this:

public class OrderDetails
{
    public string Id { get; set; }
    public string Name { get; set; }
    public IFormFile Data { get; set; }
    public string StringData { get; set; }
}

The problem that I have is that, whilst the controller method does get called, every value inside orderDetails is null. I've looked at the MS documentation and, as far as I can tell, I'm following all the rules, so I'm a little unsure why the data isn't being passed through. Can anyone help?

Upvotes: 1

Views: 3003

Answers (1)

Lutti Coelho
Lutti Coelho

Reputation: 2264

As you have an IFormFile property in your model I understand that you want to upload a file to your API.

The problem here is that you can't upload a file inside a JSON. It is a "limitation" of HTTP protocol. To upload a file you should use FormData

Given that you already have an html form like this:

<form method="post" name="fileinfo">
  <label>Your file:</label>
  <input type="file" name="data" required />
  <input type="submit" value="Upload" />
</form>

Then you should add new hidden fields to store the @Model.OrderId and @Model.Name:

<form method="post" id="fileUploadForm">
  <input type="hidden" name="OrderId" value="@Model.OrderId" />
  <input type="hidden" name="Name" value="@Model.Name" />
  <label>Your file:</label>
  <input type="file" name="Data" required />
  <input type="submit" value="Upload" />
</form>

Now on your javascript code you need to convert your forms inputs into an new FormData variable and then submit it to your api. The easiest way to do this is:

var form = $('#fileUploadForm')[0];

var data = new FormData(form);

$.ajax({                    
    type: "POST",
    url: "/Orders/CreateOrder",
    data: data,
    enctype: 'multipart/form-data', // Important!!!!
    processData: false,  //prevent jQuery transforming the data into a query string
    contentType: false,
    cache: false,
    success: function (data) {
        // Success!
    }
});

Upvotes: 2

Related Questions