A few months ago, I was enabling paging on a .NET Core 3.1 MVC application and had my search model passed into a controller method via AJAX. Well, it didn’t work. I received a NULL DTO object no matter what I tried. Trying to figure out what to do about an MVC Ajax JSON Null DTO in a controller method had me chasing my tail.
Fast forward to a few days ago, and guess what, another web app, same use case, same issue. Problem was, I couldn’t remember how I resolved it. Well, after another two hours of tinkering around with different objects, removing default settings in my DTO, and more endless googling, I finally found the issue… again.
Main issue I had is that System.Text.Json is not really usable. I found out that unless all your properties are strings, you have to setup custom comparers for each type. That about sums it up. Unless you’re passing in a very simple object that only has string properties, you can pretty much forget about using this library out of the box.
Take a look at the things that are not supported in System.Text.Json: https://docs.microsoft.com/en-us/dotnet/standard/serialization/system-text-json-migrate-from-newtonsoft-how-to
For those of you in a hurry, here is a summary of what I did. Details of the implementation will follow:
- Make sure you have “FromBody” in your controller method. I already had this, but it’s what most blog posts focus on.
[HttpPost]
public async Task<IActionResult> CatDisplay([FromBody] SearchModel<LuCategory> searchModelIn)
2. Change the default JSON serializer in your Startup.cs
using Microsoft.AspNetCore.Mvc;
public void ConfigureServices(IServiceCollection services)
{
services.AddControllersWithViews().AddNewtonsoftJson();
If you get the little squigglies under this method name, then add the Nuget package: Microsoft.AspNetCore.Mvc.NewtonsoftJson
Just so you can see how I’m calling this, here is the Javascript/Jquery/JSON that I’m sending in:
function GetPaging(ToPage) {
var _url = "/@Model.controllerName/@Model.actionName";
// Set the global values for sorting post back
var searchModel = {};
searchModel.SortColumn = '@Model.SortColumn';
searchModel.PrevSortColumn = ''; // Leave blank so sorting doesn't kick;
searchModel.CurrentPage = ToPage;
searchModel.PageSize = @Model.PageSize;
searchModel.SearchTerm = '@Model.SearchTerm';
searchModel.SearchFilter = '@Model.SearchFilter';
searchModel.SortDescending = '@Model.SortDescending';
searchModel.ActiveOnly = '@Model.ActiveOnly';
searchModel.RefId = @Model.RefId;
searchModel.RefUniqueId = '@Model.RefUniqueId';
$.ajax({
type: "POST",
url: _url,
async: true,
contentType: "application/json",
data: JSON.stringify(searchModel),
dataType: "html",
success: function (result, status, xhr) {
$("#gridPartial").html(result)
},
error: function (xhr, status, error) {
alert("Result: " + status + " " + error + " " + xhr.status + " " + xhr.statusText)
}
});
}
3. The last problem I ran into was boolean values. In the above example, the boolean value was coming from the Model, so there is no issue. However, if you are trying to get a boolean value from javascript or jquery, big problems. In order to be sure that what is being passed as a value can be deserialized into an object, you should have code like:
searchModel.SortDescending = $('descending').val().toLowerCase() != 'false') ? true : false;
This issue has hit me several times, so I’ve used this code to resolve it.
Thanks for reading and happy coding!