JavaScriptSerializer on JSON containing an array - c#

There is a similar question with the same title, but the solution is not valid for my problem.
I'm trying to serialize the following JSON:
{"Id":1,
"Questions":
[{"Id":"q-1-Q0001","Text":"Volume Too High"},
{"Id":"q-1-Q0002","Text":"Volume Too Low"}],
"Text":"My text."}
With this structure in my C#:
public class Issue
{
public Issue() { Questions = new List<Question>(); }
public string Id { get; set; }
public List<Question> Questions { get; set; }
public string Text { get; set; }
}
public class Question
{
public string Id { get; set; }
public string Text { get; set; }
}
I have JavaScript send a POST with the JSON above to this C# function:
public JsonResult AddIssueToQueue(Issue issue)
{
var id = issue.Id; // Set correctly
var text = issue.Text; // Set correctly
var q = issue.Questions; // NOT set correctly. Set to List of two empty Question items.
}
id and text are set correctly, but q is set to a List that contains two empty Question objects (Id and Text are null in each).
Is my JSON formatted incorrectly? Why doesn't the Questions array propagate correctly?

This is a just a wild guess, but your JSON structure has an ID with an integer, as rsbarro mentioned above. But your proxy class in C# is expecting a string - is it possible the type conversion is getting mixed up there?

This my ajax call and it is working fine I am getting the question List
$.ajax({
type: 'POST',
contentType: 'application/json; charset=utf-8',
data: "{'issue':{'Id':1,'Questions':[{'Id':'q-1-Q0001','Text':'Volume Too High'},{'Id':'q-1-Q0002','Text':'Volume Too Low'}],'Text':'My text.'}}" ,
dataType: 'html',
url: 'AddIssueToQueue',
success: function (data) {
if (data) {
//Do something
}
}
});
Can you share your code as well.

Related

JQUERY ajax posts JSON to C# MVC controller, but the incoming data is null

I have a strange problem. I have a C# data structure with two classes:
public class AddQuestionModel2
{
public int? QuestionID { get; set; }
public string QuestionString { get; set; }
public int? TrueAnswer { get; set; }
public QuestionType Type { get; set; }
public IEnumerable<AddQuestionModelAnswer> Answers { get; set; }
}
public class AddQuestionModelAnswer
{
public int? ID { get; set; }
public string AnswerString { get; set; }
public bool? IsRight { get; set; }
public int? Order { get; set; }
}
public enum QuestionType
{
SingleSelect,
MultiSelect,
OrderAnswers,
FillingGap,
ExampleRequired,
TrueOrFalse
}
The javascript generates the javascript object (which looks fine for the data structure) and JSON.stringify translates to the following json string:
{"QuestionString":"<p>Question 1</p>","TrueAnswer":"0","Type":"0","Answers":[{"AnswerString":"<p>Answer 1</p>","IsRight":"0"},{"AnswerString":"<p>Answer 2</p>","IsRight":"0"},{"AnswerString":"<p>Answer 3</p>","IsRight":"0"},{"AnswerString":"<p>Answer 4</p>","IsRight":"0"}]}
The json data is sent by the following jquery command:
$.ajax({
url: "/Questions/Add",
method: "POST",
async: true,
dataType: "json",
data: JSON.stringify(data),
contentType: "application/json; charset=utf-8",
success: function (e) {
if (e.Success) {
document.location = "/Questions";
}
},
error: function (e) {
var i;
for (i in e) {
console.log(e[i]);
}
}
});
On the C# side, I have the following method to receive the post data:
[HttpPost]
public async Task<string> Add([FromBody] AddQuestionModel2 q)
{
var ctx = this.HttpContext;
JsonResultModel res = new JsonResultModel();
}
The parameter "q" is always null. If I expand ctx (HttpContext), the Request.Form data is threw System.InvalidOperationException.
Does any if you have any idea what could be wrong?
The biggest problem is that I am unable to debug what is happening within HttpContext and why it is throwing exception.
Thanks in advance!
Gabor
In you ajax code try data:data, instead of data: JSON.stringify(data). The JSON.stringify() method converts a JavaScript object or value to a JSON string, but ajax data need JavaScript object. Another things to try instead of 0 or 1 use "true" or "false" in your bool fields.
In the postman everything works.

JsonConvert.DeserializeObject<T>(value) does not deserialize the object assigned

I have created a page with a KnockoutJS viewmodel. I want to post the Data to my Server using Web API.
I use this AJAX post:
$.ajax({
url: "/api/blogpost",
contenttype: "application/x-www-form-urlencoded",
data: '=' + encodeURIComponent(ko.toJSON(self.Blog)),
type: "POST",
dataType: "JSON",
timeout: 10000,
success: function (Result) {
},
error: function (xhr, status) {
alert(status + " - " + xhr.responseText);
}
});
To send the JSON data to my Web API method.
This is the JSON that is sent to the server:
{
"BlogTitle": "Sample Post",
"BlogHTML": "<p><strong>Sample JSON Blog Post</strong></p>\n\n<h1><strong>It never works :( </strong></h1>\n",
"BlogThumbnail": "http://mysystemURL/SamplePost/What.jpg",
"BlogSummary": "This is a sample post",
"BlogFQURL": "Sample_Post",
"BlogTags": [
"json",
"devlopment",
"newtag",
""
],
"BlogCategory": 1
}
My WEB API method received the JSON data correctly. The RAW string value looks like this:
"{\"BlogTitle\":\"Sample Post\",\"BlogHTML\":\"<p><strong>Sample JSON Blog Post</strong></p>\\n\\n<h1><strong>It never Works :(</strong></h1>\\n\",\"BlogThumbnail\":\"http://mysystemURL/SamplePost/What.jpg\",\"BlogSummary\":\"This is a sample post\",\"BlogFQURL\":\"Sample_Post\",\"BlogTags\":\"[\\\"json\\\",\\\"devlopment\\\",\\\"newtag\\\",\\\"\\\"]\",\"BlogCategory\":1}"
when I use the JSON visulizer on my data I get this:
I use this BlogPost vari = JsonConvert.DeserializeObject<BlogPost>(value); to deserialize my object but everything stays null
My BlogPost Object looks like this:
public class BlogPost
{
public int BlogPostID { get; set; }
public string BlogPostTitle { get; set; }
public string BlogPostHTML { get; set; }
public string BlogPostThumbnailURL { get; set; }
public string BlogPostSummary { get; set; }
public string BlogPostFQURL { get; set; }
public int BlogPostCategory { get; set; }
public List<TagDTO> BlogPostTags { get; set; }
}
I am really stumped.. Any help would be greatly appreciated!
Your property names don't match. The C# object's properties are BlogPost* and the JSON has Blog*, without the Post.
Correct the names either on the Javascript or on the C# side or use the JsonProperty attribute to specify the name of the serialized property.

Json posted array has null values

I have the following json object, sorry for the image;
The jquery code I have looks like this;
var data = {
table: table,
favour: $("[name='radFavour']:checked").val(),
data: jsonObj
};
$.ajax({
url: appDomain + "/Compare/Ajax_Update",
type: "post",
dataType: "json",
data: data
});
The c# code looks like;
[HttpPost]
public void Ajax_Update(CompareFVM fvm)
{
}
The FVM contains a string for table and for favour and the data for those two properties comes through.
For "data" I have the following in the FVM;
public List<CompareItem> data { get; set; }
And the item;
public class CompareItem
{
public int prodId { get; set; }
public int stageId { get; set; }
public string value { get; set; }
public string property { get; set; }
}
The List has the correct amount of elements in it, in this case two, but each of them has nulls set.
So the data I am posting back is not coming through for the array elements but it is for the single fields.
Any ideas?
while ajax calling, pass the objectname as 'fvm'(name should be matching with the C# code parameter). also, please check passing json abject using JSON.stringify(data).
var fvm = {
table: table,
favour: $("[name='radFavour']:checked").val(),
data: jsonObj
};
$.ajax({
url: appDomain + "/Compare/Ajax_Update",
type: "post",
dataType: "json",
data: JSON.stringify(fvm)
});
Just basing off what similar things I've done in the past, I'd structure your code like so:
// if your C# is
public void Ajax_Update(CompareFVM fvm) {
}
// then your ajax call should be along the lines of
$.ajax({
data : {
'data' : [
{ /* compareItem */ },
{ /* compareItem */ },
// ...
]
}
})
The thing being, your C# endpoint is expecting an object, so you should give it a JSON object.
If your C# class is
public class CompareFVM {
public IList<CompareItem> data { get;set; }
}
then your corresponding JSON should be:
{ 'data' : [] }
where .data would be an array of CompareItem objects.
e.g.
{
'data' : [
{'prodId':'3175','stageId':'19045','value':'TUE','property':'despatchDay'},
{'prodId':'3175','stageId':'19045','value':'TUE','property':'despatchDay'}
]
}

MVC JSON object with array not set properly

I am making a tool in which one can get a Quotation throw javascript and then send himself that quotation. The making of the quotation is going fine but when sending the email, the quotation data is corrupt.
The data in the Quotation object is fine except for the Options array. When sending 3 array items the Options array holds 3 items except for their names are null and the price is 0.
The quotation is send to ASP.NET MVC 3 using jQuery.post.
Quotation object in C# looks like:
public class Quotation
{
public string Email { get; set; }
public string Product { get; set; }
public int Amount { get; set; }
public decimal BasePrice { get; set; }
public decimal SendPrice { get; set; }
public Option[] Options { get; set; }
public decimal Discount { get; set; }
public decimal SubTotal { get; set; }
public decimal TotalPrice { get; set; }
}
public class Option
{
public string Name { get; set; }
public decimal Price { get; set; }
}
The Action Method looks like:
[HttpPost]
public JsonResult Offerte(Models.Quotation quotation)
{
//
}
The jQuery looks like:
$.post(baseUrl + "/api/Offerte/", jsonContent, function (data) {
alert(data.Message);
});
The jsonContent object looks like:
{
"Options":[
{
"Name":"Extra pagina's (16)",
"Price":40
},
{
"Name":"Papier Keuze",
"Price":30
},
{
"Name":"Omslag",
"Price":29.950000000000003
}
],
"Amount":"5",
"BasePrice":99.96000000000001,
"SubTotal":199.91000000000003,
"SendPrice":0,
"Discount":19.991,
"TotalPrice":179.91900000000004,
"Email":"someone#example.com"
}
Does anyone know why the array is not set properly?
EDIT
If I add this debug code to the controller:
using (var writer = System.IO.File.CreateText(Server.MapPath("~/App_Data/debug.txt")))
{
writer.AutoFlush = true;
foreach (var key in Request.Form.AllKeys)
{
writer.WriteLine(key + ": " + Request.Form[key]);
}
}
Options[0][Name]: Extra pagina's (52)
Options[0][Price]: 156
Options[1][Name]: Papier Keuze
Options[1][Price]: 68.4
Options[2][Name]: Omslag
Options[2][Price]: 41.94
Amount: 6
BasePrice: 149.91899999999998
SubTotal: 416.25899999999996
SendPrice: 0
Discount: 45.78848999999999
TotalPrice: 370.47051
Email: someone#example.com
This means that the data does get to the controller but the Options still doesn't get set right. And I don't want an easy fix that I parse it myself afterwards, I want to know the correct way to handle it so MVC will take care of it.
If you want to send JSON data to an ASP.NET MVC controller action and you want the model binding work currently (e.g. binding collections on your model) you need to specify the contentType as "aplication/json".
Because with the $.post you are not able to specify the contentType you need to use $.ajax and you also need to JSON.stringify your data:
$.ajax({
url: baseUrl + "/api/Offerte/",
type: 'POST',
data: JSON.stringify(jsonContent),
contentType: "application/json",
success: function (data) {
alert(data.Message);
}
});

MVC3 & JSON.stringify() ModelBinding returns null model

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?
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.
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, implement IModelBinder 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...
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.
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.
Try this:
var filters = new Object();
filters.SelectedRtoId = $('#SelectedRtoId').val();
filters.SelectedPricingPointId = $('#SelectedPricingPointId').val();
filters.SelectedLoadTypeId = $('#SelectedLoadTypeId').val();
filters.SelectedBlockId = $('#SelectedBlockId').val();
filters.SelectedRevisionStatusId = $('#SelectedRevisionStatusId').val();
var dealSummaries = new Object();
dealSummarties.SelectedItemIds = $('#SelectedItemIds').val();
var viewModel = new Object();
viewModel.ReportingFilters = filters;
viewModel.DealSummaries = dealSummaries;
$('#selected-items select option').attr("selected", "selected");
$.getJSON('#Url.Action("FilterReports")', { model: JSON.stringify(viewModel) }, function (data) {
alert(data);
});

Categories

Resources