JsonConvert.DeserializeObject fails when string contains nulls ("NaN") - c#

I am posting data to a controller stringified by knockout:
var data = ko.toJSON(viewModel);
$.ajax({
type: 'POST',
url: '#Url.Action("Action")',
data: { data: data },
dataType: 'json'
....
})
Then server-side, I try to deserialize the data with JsonConvert.
var viewModel = JsonConvert.DeserializeObject<ViewModel>(data,
new JsonSerializerSettings
{
DateTimeZoneHandling = DateTimeZoneHandling.Local,
DateFormatHandling = DateFormatHandling.IsoDateFormat
});
This fails if data contains null values (serialized as "NaN"), looking like this:
"MyField":"NaN"
Without null values, it works fine.
I tried adding NullValueHandling = NullValueHandling.Include/Ignore to the serializer settings, both without success.

I got around the problem by adding a small replacer function to the knockout stringifier (as suggested by DavidG - thank you, I should have made this work from the beginning).
var data = ko.toJSON(viewModel, function (key, value) {
if (value == "NaN") {
return;
}
else {
return value;
}
});

Related

c# mvc ajax convert list to JSON string

I'm trying to code a simple autocomplete using LINQ to entities and Razor (new to c# sharp as well) and i'm having trouble displaying json data in my view.
My controller is as follows:
public ActionResult AutoCompleteCity(string guess)
{
List<City> listData = null;
if (!string.IsNullOrEmpty(guess))
{
listData = db.AutoCompleteCity(guess);
}
return Json(new { Data = listData });
}
AJAX call:
function getCities(input) {
var serviceURL = $("#autocompleteURL").val();
var url =
$.ajax({
type: "POST",
url: serviceURL,
data: {
'guess': input
},
dataType: 'json',
success: function (response) {
if (response.Data != null) {
if ($("#targetUL") != undefined) {
$("#targetUL").remove();
}
Data = response.Data;
$.each(Data, function (i, value) {
$("#targetUL").append($("<li class='targetLI' onclick='javascript:agregarTexto(this)'>" + JSON.stringify(value) + "</li>"));
});
});
}
I might be missing a bracket or two :D
Any way when i retrieve records from the database and try to pass JSON values to the view the output is:
{"Data":[{"Selected":false,"Text":null,"Value":null}]}
I assume I'm not passing the JSON listData correctly. Any input will be greatly appreciated, thanks!
EDIT: here is a screencap of the values returned by listData in my controller
This is my LINQ query
public List<City> AutoCompleteCity(string guess)
{
using (var context = new Sports.SportsEntities())
{
var query = (from loc in context.city
join prov in context.state on loc.STATE_ID equals prov.STATE_ID
where loc.CITY_DESC.Contains(guess.ToUpper())
select new
{
city = loc.CITY_DESC,
state = prov.STATE_DESC,
});
IEnumerable<City> cityList= from ba in query.AsEnumerable()
select new City(ba.city, ba.state);
return cityList.ToList();
}
}
This error:
{"Data":[{"Selected":false,"Text":null,"Value":null}]}
was caused by having declared private attributes in the City Class, or by failing to declare getter/setter methods if said attributes are meant to be private.
I figured that out by looking at the screen capture posted on my question, only displaying the "selected", "text" and "value" properties and not the city and state description in the query results, which was what I needed to display below the textbox input.
This controller method will do the trick:
public JsonResult AutoCompleteCity(string term)
{
List<City> listData = new List<City>();
if (!string.IsNullOrEmpty(term))
{
listData = db.AutoCompleteCity(term);
}
return Json(listData, JsonRequestBehavior.AllowGet);
}
The problem is probably this piece of code in the AJAX call:
if ($("#targetUL") != undefined) {
$("#targetUL").remove();
}
By doing this you are removing the ul tag from the DOM and therefore cannot add the li elements you are constructing in this piece of code:
$.each(Data, function (i, value) {
$("#targetUL").append($("<li class='targetLI' onclick='javascript:agregarTexto(this)'>" + JSON.stringify(value) + "</li>"));
});
If you want to clear the list use .empty():
if ($("#targetUL") != undefined) {
$("#targetUL").empty();
}
if you want to return a JSON, change that:
public ActionResult AutoCompleteCity(string guess)
by
public JsonResult AutoCompleteCity(string guess)
and also try that:
Data = JSON.parse(response.Data);
It looks like your method returns a list of City objects, so maybe you need to use the property of that objects to get to the city name, something like this:
$.each(Data, function (i, city) {
$("#targetUL").append($("<li class='targetLI' onclick='javascript:agregarTexto(this)'>" + city.Name + "</li>"));
});

Return list of datetimes to drop down using Ajax

I have a drop down list that I need to fill with datetime values passed from an ajax call. The values that populate look like this: "/date1234847269/" and not actual dates. I just need the dates to be passed into the drop down list. I do not need the time stamps that are also in the datetime value that is returned from the controller.
I'm not sure if jQuery has issues with handling c# datetime values and not strings. Any help would be appreciated. Thanks
My View:
<select id="ddlDate" class="form-control bold">
<option value='0'>--Select Date--</option>
</select>
My Ajax Call:
function loadDateDDL(historicalIsChecked, monthlyIsChecked) {
$.ajax({
type: 'POST',
url: '#Url.Action("GetGroupReportDates")',
dataType: 'json',
data: { isMonthly: monthlyIsChecked },
success: function (returnData) {
convertDate(returnData);
$("#ddlDate").empty();
$("#ddlDate").append("<option value='0'>--Select Date--</option>");
$.each(returnData, function (value, key) {
$("#ddlDate").append($("<option></option>")
.attr("value", value).text(key));
});
//alert(returnData);
},
error: function (ex) {
alert('Failed to retrieve dates.' + ex);
}
});
}
function convertDate(returnData)
{
var date = new Date(returnData);
return date;
}
My Controller:
public JsonResult GetGroupReportDates ( Boolean isMonthly )
{
List<DateTime> reportDates = RealmsModel.RealmsAuditDataInterface ( ).GetGroupQueryRptDates ( isMonthly );
return new JsonResult ( )
{
Data = reportDates,
MaxJsonLength = Int32.MaxValue
};
}
Update 1/21/2016:
I am now passing my json data "returnData" to the javascript function below and converting it based on another stack post: How do I format a Microsoft JSON date?
function convertDate(returnData)
{
var date = new Date(returnData);
return date;
}
This now gives me the error "date = Invalid Date {}, returnData = ["/Date(1451628000000)/"]". I feel like I'm getting close. Any help is appreciated.
I resolved this with the following:
function convertDate(returnData)
{
var pattern = /Date\(([^)]+)\)/;
var results = pattern.exec(returnData);
var dt = new Date(parseFloat(results[1]));
return (dt.getMonth() + 1) + "/" + dt.getDate() + "/" + dt.getFullYear();
}
The format you're seeing is the old "microsoft" way of formatting dates. There are 2 ways to get around it.
One way would be to use the JSON.Net serialiser instead of the built in JavaScriptSerializer, as it (since version 4.5) formats dates so that they can be automatically parsed.
Another (quicker) way would simply be to extract the numbers from the date in it's current format as pass them to a new javascript Date object.
function toDate(value) {
return new Date(parseInt(/Date\(([^)]+)\)/.exec(value)[1], 10));
}

Sql Table values in JSON c#

Hi i have a table with following values
Country Count
China 2
India 3
Pakistan 3
i want these in JSON as "China" : 2,"India" : 3,"Pakistan" : 3
I don't want the header Count and Country. I Have tried using ajax and HTTP Handler but no avail
$(document).ready(function () {
$.ajax({
url: 'CountryRegistrations.ashx',
type: 'POST',
dataType: 'json',
success: function (data) {
var test = data.Country + data.Count;
alert(test);
},
error: function (data) {
alert("Error");
}
});
});
public void ProcessRequest(HttpContext context)
{
FilterCountry emp = getCounts();
// serialize and send..
JavaScriptSerializer serializer = new JavaScriptSerializer();
StringBuilder sbJsonResults = new StringBuilder();
serializer.Serialize(emp, sbJsonResults);
context.Response.Clear();
context.Response.ContentType = "application/json; charset=utf-8";
context.Response.Write(sbJsonResults.ToString());
}
private FilterCountry getCounts()
{
FilterCountry fc = new FilterCountry();
fc.Country = "PK";
fc.Count = 600;
return fc;
}
I gives me as PK600 but it should give "PK":600 and how to get these values from database right now im trying to get from hard coded values.
var test = data.Country + data.Count;
Try to change to:
var test = data.Country + ':' + data.Count;
If you are using JavaScriptSerializer then it will will serialize the object in to JSon format like "Key":"Value" that is also based on the object you are passing to Serialize method.
Your class "FilterCountry" has two property "Country" and "Count" and assigning values on it.
So it will be serialize like as follows { "Country" : "PK", "Count":600 }
Please go through JSon and serialize examples

Send data from ajax to c# server

I've created a dictionary on cliend side and want to send it on sever side. In my script, dictionary is created correctly, but I'm not sure abount my ajax code.
$("#btnSubmit").click(function () {
var sendList = new Array();
var elems = $(".elemValue");
$.each(elems, function (key, value) {
if (value.attributes.elemName.nodeValue != "PhotoImg") {
sendList[value.attributes.elemName.nodeValue] = value.attributes.value.nodeValue;
}
});
var data = JSON.stringify({dict : sendList});
$.ajax({
type: "GET",
url: "dataloader.aspx/GetData",
data: data,
contentType: "application/json; charset=utf-8",
dataType: "json",
success: function (result){
alert(result.d);
}
});
});
On server side I wrote
[System.Web.Services.WebMethod]
public static string GetData(Dictionary<string,string> dict)
{
Dictionary<string, string> serverDict = new Dictionary<string, string>();
serverDict = dict;
string result = "";
foreach (var value in dict)
{
result += "The key is:" + value.Key + "The value is:" + value.Value;
}
return result;
}
Where are my mistakes, and how can I fix them? Help, please=)
I don't think it's possible to create a Dictionary from JSON. At least not without a lot of work. I would try changing it from a Dictionary to a List<KeyValuePair<string,string>> and see if it deserializes for you.
Reference for KeyValuePair
Once you've done that if you still need the Dictionary you can convert it fairly easily.
var Dictionary = new Dictionary<string,string>();
foreach(var KVP in List) Dictionary.Add(KVP.Key, KVP.Value);
Couple of things here:
You need to allow GET verb explicitly:
[System.Web.Services.WebMethod]
[System.Web.Script.Services.ScriptMethod(UseHttpGet=true)]
You are returning plain text from the server, which means that this line:
dataType: "json"
won't let jQuery parse the response correctly. You should either remove this line, or build response in JSON format.

C# method to return two values from SQL Query, then get via jquery ajax call

UPDATE: This code now works! Between the answer below and my dev who emailed me from Romania, I got it sorted out.
[Method]
public object ConvDetails(string SENDERNAME, string VIEWURL)
{
{
var list = new List<object>();
new Command("select top 1 o.name [SENDERNAME], view_url [VIEWURL] from MESSAGE m join OPR_SECD o on UPDATED_BY = O.RECNUM where VIEW_URL like 'conversation.aspx%' and DELIVER_TO in (select OPR_INITIAL from OPR_SECD where recnum = #CURRENT_USER_ID) order by m.RECNUM desc")
.AddInt("CURRENT_USER_ID", Common.UserID)
.Each(R => list.Add(new
{
VIEWURL = R.GetString("VIEWURL"),
SENDERNAME = R.GetString("SENDERNAME")
}));
return list;
};
}
Here's my ajax call to get the two strings from my method:
convDetails: function() {
$.ajax({
url: BASE_URL + "pages/services/messages.ashx?method=convdetails",
dataType: "json",
async: true,
data: {},
success: function(data) {
$("a.new-message-alert").attr("href", '' + data[0].VIEWURL);
$("span#message-from").text("New Message From: " + data[0].SENDERNAME);
}
});
}
UPDATE:
Between the response I got below and a few emails to our developer who's in Romania, I was able to piece it together. I updated my code to what worked! The having just data.VIEWURL didn't work. I had to add the data[0].VIEWURL. So, thanks Matt for that one. Also, in my href i had to put in empty quotes or it would return NaN. No idea why.
Thanks!
Well, that JavaScript isn't going to work whatever you do on the C# side. You're attempting synchronous processing of the result of an asynchronous call.
Your C# doesn't look far off, for some reason I totally failed to read it correctly first time around. I've never used a .ashx in quite that manner, I've always just spat out my response from ProcessRequest, but if your code is getting called then I just learned something new. I do, however, notice that you're returning a serialized list, but only processing one element.
You could use a more LINQy approach to eliminate the explicit list filling, though:
var list =
from R in new Command("select top 1 o.name [SENDERNAME], view_url [VIEWURL] from MESSAGE m join OPR_SECD o on UPDATED_BY = O.RECNUM where VIEW_URL like 'conversation.aspx%' and DELIVER_TO in (select OPR_INITIAL from OPR_SECD where recnum = #CURRENT_USER_ID) order by m.RECNUM desc")
.AddInt("CURRENT_USER_ID", Common.UserID)
select new {
VIEWURL = R.GetString("VIEWURL"),
SENDERNAME = R.GetString("SENDERNAME") };
context.Response.Write(JsonConverter.SeralizeObject(list));
Your JS should look more like:
convDetails: function() {
$.ajax({
url: BASE_URL + "pages/services/messages.ashx?method=convdetails",
async: true,
data: {},
success: function(data) {
$("a.new-message-alert").attr("href", data[0].VIEWURL);
$("a.new-message-alert").text("New message from: " + data[0].SENDERNAME);
}
});
}

Categories

Resources