Stuck deserializing JSON string [duplicate] - c#

This question already has answers here:
How to parse a JSONString To Dataset?
(6 answers)
Closed 2 months ago.
I am using table data from jQuery Datatable and passing it to an ajax function. The function calls a web service to process the data and I am stuck trying to deserialize it.
The initial call comes from datatable's 'buttons' button group, where I am trying to implement a custom export to Excel:
buttons: [
{
extend: "collection",
text: "Export",
buttons: [
{
text: 'My Excel',
action: function (e, dt, node, config) {
exportToExcel(dt);
}
},
...
]
function exportToExcel(dt) {debugger
// var tableRows = dt.rows().data().toArray();
var tableRows = dt.data().toArray();
var blah = JSON.stringify({ TableData: tableRows });
$.ajax({
type: "POST",
dataType: "json",
contentType: "application/json; charset=utf-8",
cache: false,
url: "../WebService/ABC.asmx/ExportToExcel",
data: JSON.stringify({ TableData: blah }),
}).done(function (result) {
}).fail(...
I tried creating classes to see if that would work but no luck.
public string ExportToExcel(string TableData)
{
string JSONresult = string.Empty;
//Errors_Counts[] oDict = (JsonConvert.DeserializeObject<Dictionary<string, Errors_Counts[]>>(TableData)).Values.FirstOrDefault();
return JSONresult;
}
The data, once JSON-stringified looks like this:
{"TableData":
[
{"THEDATE":"2022-12-10T00:00:00","E38":0,"E39":1,"E40":37,"E41":0,"E42":0},
{"THEDATE":"2022-12-11T00:00:00","E38":0,"E39":0,"E40":20,"E41":0,"E42":0},
...
]
}
How would I deserialize this to end up with a dataset or data table that I can further process? Right now I just have a JSON string. The third party soaftware that I use for exporting to Excel works best with data table. So if I can end up with a data table with column names as TheDate, E38, E39, ... it would solve my issue.

if you just need a DataTable instance
public string ExportToExcel(JObject TableData)
{
//DataTable dataTable = TableData["TableData"].ToObject<DataTable>();
return TableData["TableData"].ToString();
}

Related

How can I retrieve the content of my jquery datatable in c#?

I have an HTML table that I'm converting into datatable. In this datatable, I can edit a value in a cell. I want to attach a "save" button to this datatable and once a user clicks it then it should save the content of the datatable into SQL Server database.
My problem is, I couldn't find out how I can extract the data from js:datatable object into c#? I think I need to use something like below but it doesn't work and returning error.
"Cannot read properties of undefined (reading 'type')". Here is the code:
<table id="tb_voteProjects" class="compact nowrap custom" cellspacing="0" >
<%=getColumnHeaders()%>
<%=getActiveData()%>
</table>
...
var table = $('#tb_voteProjects').DataTable({
...,
buttons: [
...
{
text: 'Save',
action: function ( e, dt, node, config ) {
$.ajax({
type: "POST",
url: 'Ranking.aspx/SaveRanks',
data: {table}, //HOW TO SEND THE TABLE CONTENT INTO C# ???
contentType: "application/json; charset=utf-8",
dataType: "json",
success: function (msg) {
window.location.reload();
},
error: function (e){
Console.log(e);
}
});
}
Any help would be appreciated.
Thanks.
Edit1: using ...data: table.rows().data()..., instead of ...data:table..., in my ajax didn't fix the issue.
You can use the dt object in your action function - that represents the DataTables API for your table.
From there you can use dt.rows().data().toArray(). This creates an array containing each row of table data in a sub-array.
You can then convert that JavaScript array to a JSON string:
data: JSON.stringify( dt.rows().data().toArray() ),
I assume you already know how to use your C# server code to retrieve the JSON payload from the body of the POST request.
Reference:
rows().data()
toArray()

ASP.NET MVC JSON get value with two Parameters

I am trying to get value based on 2 parameters, below is my function where I added my 2 parameters in JSON stringify :
function GetItemLocationOnHand(itemId, locationId) {
var data = JSON.stringify({
itemId: itemId,
locationId: locationId
});
$.ajax({
async: true,
type: 'GET',
dataType: 'JSON',
contentType: 'application/json; charset=utf-8',
data: data,
url: 'getItemInventory3',
success: function (data) {
$("#txtInventory3").val(parseFloat(data).toFixed(2));
},
error: function () {
alert("Error")
}
});
}
Below is my code in my controller to retrieve the data I want based on these two parameters :
[HttpGet]
public JsonResult GetItemLocationOnHand(int itemId, int locationId)
{
var itemLocQuantity = objDB.ItemLocationDatas.Single(items => items.ItemId == itemId && items.LocationId == locationId).Quantity;
return Json(itemLocQuantity, JsonRequestBehavior.AllowGet);
}
Upon calling this function via below on change code, I can't seem to get my data and is always returning the error.. If I only have 1 parameter, then no error encountered.
Please advise what went wrong when trying to pass 2 parameters.
$("#LocationId").change(function () {
var itemId = $("#ItemId").val();
var locationId = $("#LocationId").val();
GetItemLocationOnHand(itemId, locationId)
});
Issue solved by doing the following :
added correct URL which is GetItemLocationOnHand
removed Stringify and used var data = ({ itemId: itemId, locationId:
locationId });
thanks a lot to Freedom and Reflective and others for your comments!
function GetItemLocationOnHand(itemId, locationId) {
var data = ({ itemId: itemId, locationId: locationId });
$.ajax({
async: true,
type: 'GET',
dataType: 'JSON',
contentType: 'application/json; charset=utf-8',
data: data,
url: 'getItemLocationOnHand',
success: function (data) {
$("#txtInventory3").val(parseFloat(data).toFixed(2));
},
error: function () {
alert("Error")
}
});
}
Just to avoid some misunderstanding how AJAX GET works and setting some parameters which you don't have to set (i.e. you are still not so deep into jQuery AJAX) you may use the shortcut they also implemented i.e. $.get so your request will look as simple as that and you can't get wrong as it will use the proper defaults for GET. If you want the response to be treated as JSON, just set Content-type of your response headers (from backed) to application/json. This will be checked by jQuery AJAX response handler and it will parse the incoming data as JSON.
var data = {itemId: 1, locationId: 2 };
$.get('GetItemLocationOnHand', data, function (data) {
$("#txtInventory3").val(parseFloat(data).toFixed(2));
}).fail(function (jqXHR, textStatus ) {
alert(`Error = ${jqXHR.status} ${textStatus}`);
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
See my example below. This works for me when doing ajax requests to a MVC controller with multiple params.
Below is my MVC controller action with multiple params.
// GET
[HttpGet]
public ActionResult Index(string referenceID, int typeID, int supplierID, bool isArchived)
{
// Do CODE here
}
Below is my Ajax request that I use to get or post. Depending on your needs. I use data type 'JSON' and format my data as a JSON object.
var formData = {referenceID: 'Test', typeID: 3, supplierID: 2, isArchived: false};
$.ajax({
type: 'GET',
cache: false,
url: getActionUrl, // url: domain/controller/action |or| domain/area/controller/action
dataType: 'json',
contentType: 'application/json; charset=utf-8',
headers: headers, // ignore if not needed. I use it for __RequestVerificationToken
data: formData,
success: function (data, status, xml) {
// do something with the data
},
error: function (xml, status, error) {
console.log(xml)
// do something if there was an error
},
complete: function (xml, status) {
}
});
I think your issue might be that you are using 'JSON.stringify'. It could be interpreting your JSON string as a single parameter input and not two separate parameters.
Please see below snippets from documentation. https://api.jquery.com/jquery.ajax/
If json is specified, the response is parsed using jQuery.parseJSON before being passed, as an object, to the success handler. The parsed JSON object is made available through the responseJSON property of the jqXHR object.
The data option can contain either a query string of the form key1=value1&key2=value2, or an object of the form {key1: 'value1', key2: 'value2'}. If the latter form is used, the data is converted into a query string using jQuery.param() before it is sent. This processing can be circumvented by setting processData to false. The processing might be undesirable if you wish to send an XML object to the server; in this case, change the contentType option from application/x-www-form-urlencoded to a more appropriate MIME type.

Json is not properly binded as c# object

My app is made in ASP.NET MVC 5. User can use search form which is displaying filtered data. Now I want to add button which will export displayed data.
To do this I am sending Search object to view and save it in html. Now When clicking export button I want to pass this object to controller, get data from database using this Search object and save results as text.
The thing is I cant bind json to c# object. Thats my view:
<div id="originalForm" style="visibility:hidden">
#Html.Raw(Newtonsoft.Json.JsonConvert.SerializeObject(Model))
</div>
This is my ajax code:
function exportRaportToCsv() {
var $formData = $('#originalForm').text();
var allIds = getCheckedIds();
var dataToSend = JSON.stringify({
ids: allIds,
search: $formData
});
$.ajax({
type: "POST",
url: '#Url.Action("ExportToCsv", "BankCosts")',
data: dataToSend,
contentType: "application/json; charset=utf-8",
success: function (datar) {
window.location = '/BankCosts/Download?fileGuid=' + response.FileGuid
+ '&filename=' + response.FileName;
},
error: function (xhr) {
},
});
}
And this is my controller:
[HttpPost]
public ActionResult ExportToCsv(string[] ids, Search search)
{
// search is null here
}
When I spy sending data with Fiddler I can see, that I am passing this:
{"ids":[],"search":"\n {\"ID\":0,\"DateFrom\":\"2018-06-23T00:00:00\",\"DateTo\":\"2018-06-25T00:00:00\",\"hasUnrecognizedStatus\":false,\"skippedSearchResults\":0,\"paginationLimit\":100}\n"}
I think it is worth to mention, that ids is properly passed. If it contains data, that data is passed. I think the problem is that I have \ in my json. How can I remove this? Is there something wrong with my ajax?
When I use console.log to print $formData I can see that \ characters are gone and it looks better:
{"ID":0,"DateFrom":"2018-06-23T00:00:00","DateTo":"2018-06-25T00:00:00","hasUnrecognizedStatus":false,"skippedSearchResults":0,"paginationLimit":100}
[HttpPost]
public ActionResult ExportToCsv(string[] ids,[FromBody]Search search)
{
}
Try adding FromBody if your Search model is ok it should work.
based on your comments, I think that search object already stringified, so you don't need to stringify it.
just make your json like this
var dataToSend = {
"ids": allIds,
"search": $formData
};
Use JSON.parse() to transforms JSON string to a JavaScript object. Your $('#originalForm').text() is a JSON string actually.
var $formData = JSON.parse($('#originalForm').text());
var allIds = getCheckedIds();
var dataToSend = JSON.stringify({
ids: allIds,
search: $formData
});
In your case, $formData is a string (JSON string actually). So JSON.stringify() again trying to convert to JSON string which is already a JSON string that's causing unnecessary '/' character in form data that you are posting.
Make sure to set the content type to 'application/json' in ajax call properties Otherwise MVC model binder will not be able to map and fill .NET model from JSON posted data.
contentType: "application/json; charset=utf-8",
Since you are using
JSON.stringify
the search value posted in string format not object
Search
so
Try replace your controller with this
[HttpPost]
public ActionResult ExportToCsv(string[] ids, string search)
{
//then deserialize search json like
Search objSearch = JsonConvert.DeserializeObject<Search>(search);
}
or
[HttpPost]
public ActionResult ExportToCsv(string[] ids, JObject search)
{
//then deserialize search json like
Search objSearch = JsonConvert.DeserializeObject<Search >
(dataModel["search"].ToString());
}
View
$.ajax({
type: "POST",
url: '#Url.Action("ExportToCsv", "BankCosts")',
data:{ids= allIds.toString(),search:JSON.stringify($formData)}
contentType: "application/json; charset=utf-8",
success: function (datar) {
window.location = '/BankCosts/Download?fileGuid=' + response.FileGuid
+ '&filename=' + response.FileName;
},
error: function (xhr) {
},
});

Kendo DataSource with sending dynamic data to the server

I'm new to Kendo and from several days I'm trying to figure out how to populate kendo grid with search data. My case is the following:
I have javascript viewmodel:
sl.kendo = function () {
var billingReportViewModel = kendo.observable({
billingReportCriteria: [],
executeSearch: function (e) {
var $grid = $("#gridResults").data("kendoGrid");
$grid.dataSource.read();
$grid.refresh();
}
});
return {
billingReportViewModel: billingReportViewModel
}
} ();
And I initialize the billingReportCriteria from the server with this function:
var initCriteriaViewModel = function () {
$.ajax({
url: 'GetBillingReportCriteria',
type: "GET",
dataType: "json",
success: function (model) {
**$.extend(sl.kendo.billingReportViewModel.get("billingReportCriteria"), kendo.observable(model));**
// bind to the viewModel
kendo.bind($("#searchTable"), sl.kendo.billingReportViewModel);
}
});
}()
Than I declare my grid DataSource that sends this billingReportCriteria to the server as parameter:
var gridDataSource = new kendo.data.DataSource({
transport: {
read: {
url: "GetBillingReportResults",
data: JSON.stringify(sl.kendo.billingReportViewModel.get("billingReportCriteria")),
cache: false,
type: "POST"
}
},
schema: {
data: "Items",
total: 10 // total number of data items is returned in the "count" field of the response
}
});
And I init my kendo grid:
$("#gridResults").kendoGrid({
columns: [
{
field: "Name"
},
{
field: "Title"
}],
dataSource: gridDataSource,
autoBind: false
});
When I execute the search from the view model 'executeSearch' I go the server, but the billingReportCriteria is empty! When I check the 'billingReportViewModel' value from F12 Chrome tools everything seems to be OK, but when I check the value of 'sl.kendo.billingReportViewModel.billingReportCriteria' or 'sl.kendo.billingReportViewModel.get("billingReportCriteria")' - it's empty though 'sl.kendo.billingReportViewModel.get("billingReportCriteria.Name")' for example has the right value!
Can you suggest what the problem is? Somehow I can't send the right 'billingReportCriteria' to the server!
I figure out the following thing. When I get the method on the server that is responsible for returning the results the only way I can get the passed parameters is by using the Response.Form or Response.QueryString in the body of the method. How can I pass the arguments to that method so I can get them like this:
public JsonResult GetBillingReportResults(string billingCriteria)
{
string criteria = Request.Form["billingCriteria"]; //I can do it like this, but I want to pass the arguments as method parameters
}

Basic Simple Asp.net + jQuery + JSON example

I'm trying to learn how to make a simple call to the server from Javascript/jQuery. I've been trying to learn and could not find a tutorial with those simple steps.
I want to send a message to the server with two parameters (a DateTime and a String) and get back a DateTime. I want to do that via JSON.
How would the code in the server look like (structure only)?
Is there something special I should do on the server side? And how about security?
How would I implement the call in jQuery?
And how would I handle the result?
I'm most interested on code structure.
Update
I found the answer below great to get me started. However, I recently stumbled upon Full ASP.NET, LINQ, jQuery, JSON, Ajax Tutorial. It's just a fantastic and very didactic step-by-step that I want to share with anyone else who comes across this question in the future.
There are several ways that you can do this; this will serve as a single example.
You could write something like this for your jQuery code:
urlToHandler = 'handler.ashx';
jsonData = '{ "dateStamp":"2010/01/01", "stringParam": "hello" }';
$.ajax({
url: urlToHandler,
data: jsonData,
dataType: 'json',
type: 'POST',
contentType: 'application/json',
success: function(data) {
setAutocompleteData(data.responseDateTime);
},
error: function(data, status, jqXHR) {
alert('There was an error.');
}
}); // end $.ajax
Next, you need to create a "generic handler" in your ASP.net project. In your generic handler, use Request.Form to read the values passed in as json. The code for your generic handler could look something like this:
[WebService(Namespace = "http://tempuri.org/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
public class handler : IHttpHandler , System.Web.SessionState.IReadOnlySessionState
{
public void ProcessRequest(HttpContext context)
{
context.Response.ContentType = "application/json";
DateTime dateStamp = DateTime.Parse((string)Request.Form["dateStamp"]);
string stringParam = (string)Request.Form["stringParam"];
// Your logic here
string json = "{ \"responseDateTime\": \"hello hello there!\" }";
context.Response.Write(json);
}
See how this work out. It will get you started!
Update: I posted this code at the CodeReview StackExchange: https://codereview.stackexchange.com/questions/3208/basic-simple-asp-net-jquery-json-example
If you are using jQuery you could do it with a GET or POST.
$.get ('<url to the service>',
{ dateParam: date, stringParam: 'teststring' },
function(data) {
// your JSON is in data
}
);
$.post ('<url to the service>',
{ dateParam: date, stringParam: 'teststring' },
function(data) {
// your JSON is in data
}
);
Note that the name of the parameters in (e.g. dateParam, stringParam) need to be the same as the name of the parameters your service method is expecting. Also that your service will need to format the result as JSON, the data parameter in the call back will contain anything your service sends back (e.g. text, xml, json, etc).
See the jQuery documentation for $.ajax, $.get, $.post: http://api.jquery.com/jQuery.ajax/, http://api.jquery.com/jQuery.get/, http://api.jquery.com/jQuery.post/
Here sample code using jquery ajax call and on serverside webmethod returns jSon format data.
Jquery :
$(‘#myButton’).on(‘click’,function(){
var aData= [];
aData[0] = “2010”;
aData[0]=””
var jsonData = JSON.stringify({ aData:aData});
$.ajax({
type: "POST",
url: "Ajax_function/myfunction.asmx/getListOfCars", //getListOfCars is my webmethod
data: jsonData,
contentType: "application/json; charset=utf-8",
dataType: "json", // dataType is json format
success: OnSuccess,
error: OnErrorCall
});
function OnSuccess(response.d)) {
console.log(response.d)
}
function OnErrorCall(response)) { console.log(error); }
});
Codebehind : Here a webmethod which is returning json format data i.e list of cars
[webmethod]
public List<Cars> getListOfCars(list<string> aData)
{
SqlDataReader dr;
List<Cars> carList = new List<Cars>();
using (SqlConnection con = new SqlConnection(cn.ConnectionString))
{
using (SqlCommand cmd = new SqlCommand())
{
cmd.CommandText = "spGetCars";
cmd.CommandType = CommandType.StoredProcedure;
cmd.Connection = con;
cmd.Parameters.AddWithValue("#makeYear", aData[0]);
con.Open();
dr = cmd.ExecuteReader(CommandBehavior.CloseConnection);
if (dr.HasRows)
{
while (dr.Read())
{
string carname=dr[“carName”].toString();
string carrating=dr[“carRating”].toString();
string makingyear=dr[“carYear”].toString();
carList .Add(new Cars{carName=carname,carRating=carrating,carYear=makingyear});
}
}
}
}
return carList
}
//Created a class
Public class Cars {
public string carName;
public string carRating;
public string carYear;
}

Categories