3

There is problem in sending ajax requests that have multiple parameters to asp.net mvc core 3 action using http post method. the parameters do not bind. In dot net framework asp.net web api there was similar limitation but not in asp.net mvc actions. I want to know is there work around this in asp.net core 3 mvc or is this the new limitation? action:

public string SomeAction([FromBody]string param1, [FromBody]IEnumerable<SomeType> param2, [FromBody]IEnumerable<SomeType> param3)
{
       //param1 and param2 and param3 are null
}

client:

    $.ajax({
        contentType: 'application/json',
        data: JSON.stringify({
            "param1": "someString",
            "param2": someList,
            "param3": someList
        }),
        type: "POST",
        dataType: "json",
        url: "/SomeController/SomeAction",
        success: function (result) {
        },
        error: function (error) {
            console.error(error);
        }
    }
    );
Steve Homayooni
  • 135
  • 5
  • 11

3 Answers3

2

With the new version actions need to be explicit about what and where they expected to bind models from.

Create a mode to hold all the required data

public class SomeActionModel {
    public string param1 { get; set; }
    public IEnumerable<SomeType> param2 { get; set; }
    public IEnumerable<SomeType> param3 { get; set; }
}

Update the action to expect the data from the body of the request

public IActionResult SomeAction([FromBody] SomeActionModel model) {
    if(ModelState.IsValid) {
        string param1 = model.param1;
        IEnumerable<SomeType> param2 = model.param2;
        IEnumerable<SomeType> param3 = model.param3;

        //...

        return Ok();
    }

    return BadRequest(ModelState);
}

The client should also send the data in the correct format

var model = {
    param1: GeometricNetworkTrace_Class.flags,
    param2: GeometricNetworkTrace_Class.barriers,
    param3: feederIds
};

$.ajax({
    contentType: 'application/json',
    data: JSON.stringify(model),
    type: "POST",
    dataType: "json",
    url: "/controllerName/actionName",
    success: function (result) {
    },
    error: function (error) {
        console.error(error);
    }
});

Reference Model Binding in ASP.NET Core

Nkosi
  • 235,767
  • 35
  • 427
  • 472
  • Not with JSON. JSON is very literally "object notation", so you need to bind it to an object, not a bunch of different params. You can send via `x-www-form-urlencoded`, and bind that to multiple params, because it's just key-value pairs. – Chris Pratt Oct 22 '19 at 12:59
1

The reason for a single [FromBody] parameter is described in Parameter Binding in ASP.NET Web API. The request body might be stored in a non-buffered stream that can only be read once.

With a custom model binder you can get around it. See Posting JavaScript types to MVC 6 in .NET core, using Ajax.

Ivan G.
  • 5,027
  • 2
  • 37
  • 65
Peter
  • 11
  • 1
-2

Try adding [FromBody] attribute in your controller signature.

public string SomeAction([FromBody] string param1, IEnumerable<SomeType> param2, IEnumerable<SomeType> param3)
{
       //param1 and param2 and param3 are null
}
UNOPARATOR
  • 688
  • 1
  • 6
  • 18
  • FromBody attribute is used where we have complex object. And when we try to tell the mvc that the requested data is with in the body of the request. But here the parameters of the function you are specifying are just the simple types not the complex object – Malik Haseeb Jun 14 '20 at 05:55
  • Even if it does not look like a complex object, the 2nd & 3rd params are `IEnumerable`. `SomeType` may or may not be a complex type, and `Enumerable` when used in querystring can see easily lead to [a huge querystring & some problems] (https://stackoverflow.com/a/48230425/12163640). – UNOPARATOR Jun 15 '20 at 06:39