Complex type is getting null in a ApiController parameter

C#AjaxJsonasp.net Web-Api

C# Problem Overview


I don´t know why my parameter "ParametroFiltro Filtro" is getting null, the other parameters "page" and "pageSize" is getting OK.

public class ParametroFiltro
{
    public string Codigo { get; set; }
    public string Descricao { get; set; }
}

My ApiController Get method:

public PagedDataModel<ParametroDTO> Get(ParametroFiltro Filtro, int page, int pageSize)

My ajax call:

var fullUrl = "/api/" + self.Api;
$.ajax({
    url: fullUrl,
    type: 'GET',
    dataType: 'json',
    data: { Filtro: { Codigo: '_1', Descricao: 'TESTE' }, page: 1, pageSize: 10 },
    success: function (result) {
        alert(result.Data.length);
        self.Parametros(result.Data);
    }
});

C# Solutions


Solution 1 - C#

You are trying to send a complex object with GET method. The reason this is failing is that GET method can't have a body and all the values are being encoded into the URL. You can make this work by using [FromUri], but first you need to change your client side code:

$.ajax({
    url: fullUrl,
    type: 'GET',
    dataType: 'json',
    data: { Codigo: '_1', Descricao: 'TESTE', page: 1, pageSize: 10 },
    success: function (result) {
        alert(result.Data.length);
        self.Parametros(result.Data);
    }
});

This way [FromUri] will be able to pick up your complex object properties directly from the URL if you change your action method like this:

public PagedDataModel<ParametroDTO> Get([FromUri]ParametroFiltro Filtro, int page, int pageSize)

Your previous approach would rather work with POST method which can have a body (but you would still need to use JSON.stringify() to format body as JSON).

Solution 2 - C#

Provide the contentType property when you make the ajax call. Use JSON.stringify method to build the JSON data to post. change the type to POST and MVC Model binding will bind the posted data to your class object.

var filter = { "Filtro": { "Codigo": "_1", "Descricao": "TESTE" }, 
                                               "page": "1", "pageSize": "10" }; 
$.ajax({
    url: fullUrl,
    type: 'POST',
    dataType: 'json',
    contentType: 'application/json',
    data: JSON.stringify(filter),
    success: function (result) {
        alert(result.Data.length);
        self.Parametros(result.Data);
    }
});

Solution 3 - C#

It's also possible to access POST variables via a Newtonsoft.Json.Linq JObject.

For example, this POST:

$.ajax({
    type: 'POST',
    url: 'URL',
    data: { 'Note': note, 'Story': story },
    dataType: 'text',
    success: function (data) { }
});

Can be accessed in an APIController like so:

public void Update([FromBody]JObject data)
{
    var Note = (String)data["Note"];
    var Story = (String)data["Story"];
}

Solution 4 - C#

If you append json data to query string, and parse it later in web api side. you can parse complex object too. It's useful rather than post json object, espeicaly in some special httpget requirement case.

//javascript file 
    var data = { UserID: "10", UserName: "Long", AppInstanceID: "100", ProcessGUID: "BF1CC2EB-D9BD-45FD-BF87-939DD8FF9071" };
    var request = JSON.stringify(data);
    request = encodeURIComponent(request);
    
    doAjaxGet("/ProductWebApi/api/Workflow/StartProcess?data=", request, function (result) {
        window.console.log(result);
    });
    
    //webapi file:
    [HttpGet]
    public ResponseResult StartProcess()
    {
        dynamic queryJson = ParseHttpGetJson(Request.RequestUri.Query);
    		int appInstanceID = int.Parse(queryJson.AppInstanceID.Value);
        Guid processGUID = Guid.Parse(queryJson.ProcessGUID.Value);
        int userID = int.Parse(queryJson.UserID.Value);
        string userName = queryJson.UserName.Value;
    }
    
    //utility function:
    public static dynamic ParseHttpGetJson(string query)
    {
        if (!string.IsNullOrEmpty(query))
        {
            try
            {
                var json = query.Substring(7, query.Length - 7); //seperate ?data= characters
                json = System.Web.HttpUtility.UrlDecode(json);
                dynamic queryJson = JsonConvert.DeserializeObject<dynamic>(json);
    
                return queryJson;
            }
            catch (System.Exception e)
            {
                throw new ApplicationException("can't deserialize object as wrong string content!", e);
            }
        }
        else
        {
            return null;
        }
    }

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionwillView Question on Stackoverflow
Solution 1 - C#tpeczekView Answer on Stackoverflow
Solution 2 - C#ShyjuView Answer on Stackoverflow
Solution 3 - C#graphicdivineView Answer on Stackoverflow
Solution 4 - C#Bes LeyView Answer on Stackoverflow