MVC3 & JSON.stringify() ModelBinding returns null model
Solution 1
Change your $.getJSON line to:
$.ajax({
url: '@Url.Action("FilterReports")',
data: JSON.stringify(viewModel),
contentType: 'application/json',
dataType: 'json',
success: function (data) { alert(data); }
});
This way MVC knows that it is receiving JSON and will bind it to your model correctly.
Solution 2
Here's a few different things you could try:
Apparently you shouldn't use nullable properties in your objects if you want to use the
DefaultModelBinder
: ASP.NET MVC3 JSON Model-binding with nested class. So you could try making your ints not nullable or if that's not an option, implementIModelBinder
yourself?Have you marked your classes with the
SerializableAttribute
?Try setting the type parameter in the ajax method to 'POST' - it will be using 'GET' by default..
type: 'POST'
Try explicitly setting the contentType parameter in the ajax method to this instead...
contentType: 'application/json; charset=utf-8'
And finally, are you definitely using MVC 3, not MVC 2? I ask because MVC 3 has the JsonValueProviderFactory baked into the framework where as MVC 2 didn't so if you were using MVC 2 that might explain the problem you're having...
Solution 3
Ok, replace:
{ model: JSON.stringify(viewModel) }
with
{ model: viewModel }
You're mixing objects with JSON strings, so jQuery will JSON.stringify the entire object. Which will double encode viewModel.
Solution 4
here is what I would suggest, in your controllers action method should look as follows:
public JsonResult FilterAction(string model)
{
var viewModel=new JavaScriptSerializer().Deserialize<DealSummaryComparisonViewModel>(model);
}
Also make sure your request is reaching the right action and look at Firebug for the same.
shuniar
I am a .NET developer and enjoy learning about and implementing new technologies.
Updated on August 03, 2022Comments
-
shuniar over 1 year
I am trying to get model binding with MVC3 and JSON working but I have had no luck... No matter what I do I seem to be getting a
null
model on the server.Method Signature:
public ActionResult FilterReports(DealSummaryComparisonViewModel model)
Javascript UPDATED:
<script type="text/javascript" language="javascript"> $(document).ready(function () { $('#filter-reports').click(filterReports); }); function filterReports() { var filters = { SelectedRtoId: $('#SelectedRtoId').val(), SelectedPricingPointId: $('#SelectedPricingPointId').val(), SelectedLoadTypeId: $('#SelectedLoadTypeId').val(), SelectedBlockId: $('#SelectedBlockId').val(), SelectedRevisionStatusId: $('#SelectedRevisionStatusId').val() } var dealSummaries = { SelectedItemIds: $('#SelectedItemIds').val() } var model = { ReportingFilters: filters, DealSummaries: dealSummaries } $('#selected-items select option').attr("selected", "selected"); $.ajax({ url: '@Url.Action("FilterReports")', data: model, contentType: 'application/json', dataType: 'json', success: function (data) { alert(data); } }); } </script>
Models:
public class DealSummaryComparisonViewModel { public ReportingFiltersViewModel ReportingFilters { get; set; } public LadderListViewModel DealSummaries { get; set; } } public class LadderListViewModel { public MultiSelectList AvailableItems { get; set; } public int[] SelectedItemIds { get; set; } public MultiSelectList SelectedItems { get; set; } } public class ReportingFiltersViewModel { public int? SelectedRtoId { get; set; } public ICollection<Rto> Rtos { get; set; } public int? SelectedPricingPointId { get; set; } public ICollection<PricingPoint> PricingPoints { get; set; } public int? SelectedLoadTypeId { get; set; } public ICollection<LoadType> LoadTypes { get; set; } public int? SelectedBlockId { get; set; } public ICollection<Block> Blocks { get; set; } public int? SelectedRevisionStatusId { get; set; } public ICollection<RevisionStatus> RevisionStatuses { get; set; } public bool? DealStatus { get; set; } }
The model looks fine on the client side:
{"ReportingFilters":{ "SelectedRtoId":"5", "SelectedPricingPointId":"20", "SelectedLoadTypeId":"55", "SelectedBlockId":"21", "SelectedRevisionStatusId":"11" },"DealSummaries":{ "SelectedItemIds":["21","22","23","24","25"] }}
So why am I getting nothing back on the controller? This has been giving me trouble for the past two days so please help! Thanks!!
UPDATE I've updated my javascript section to what I am currently using. This section now returns the model to the controller with the ReportingFilers and DealSummaries objects, but all values within are null.
Does it possibly have something to do with the values being strings? If so, how can I fix this?
-
shuniar over 12 yearsThis is closer to working, the model object isn't null anymore, but the ReportingFilters and DealSummaries objects underneath it are.
-
Joe over 12 yearsCan you replace your strings with ints?
["21","22","23","24","25"]
becomes[21,22,23,24,25]
-
shuniar over 12 yearsCombining this with @IAbstractDownvoteFactory's answer I am one step closer, now I have the model object with the ReportingFilters and DealSummary objects, but now all of thier properties are null even though I am passing values to them.
-
shuniar over 12 yearsShould removing the stringify achieve this?
-
shuniar over 12 yearsI recieve the same result as initializing them the other way.
-
Joe over 12 yearsNo, how are you building that javascript object?
-
Richard Dalton over 12 yearsWhat happens when you try exactly what I posted?
-
shuniar over 12 yearsYou're right, it's stringified. I'm using the
ListBoxFor(m = m.SelectedItemIds, Model.SelectedItems)
which is the reason for the select all hack before the ajax query is called. How would I go about replacing the string values? -
shuniar over 12 yearsI get a model with two null objects.
-
shuniar over 12 yearsYes, I've tried combiniations of them all, and it seems that the initialization doesn't make a differnece.
-
shuniar over 12 yearsThanks! Updating it to a post and stringifying gives me all the data in my model in the controller, but now my postback isn't being reached... any sugguestions?
-
shuniar over 12 yearsUnfortunately, I can only accept one as the answer to my problem, so you get it because your post was the most helpful to solving my problem. Switching to the $.ajax from $.getJSON made the most significant contribution as the others built off of it. Thanks to everyone!
-
codefrenzy over 12 yearsHmm, what do you mean your postback isn't being reached? If you put a breakpoint in your FilterReports Action and debug, does it stop? And your model no longer has nulls in it? Do you mean that the ajax callback isn't being reached? If so, what are you returning from your action? Have you tried specifying the 'error' parameter on the ajax method as well?
-
shuniar over 12 yearsI was referring to the ajax postback but I was able to figure it out. I wasn't returning JSON from my FilterReports method.
-
SteveCav almost 5 yearsOh, no it won't.