Convert to Json and call page method - c#

I have been trying to get this working for too long and thought I might ask for help here. I am trying to pass a javascript object to server side and then back to client side. Kind of like, on every postback I want to update the value of the object code behind or client side depending upon certain conditions. I can use hiddenfield here but I am trying to learn ajax so.
I have declared a global variable client side called sortList which stores the info about what task is stored in what slot. So its like:
var sortList = {};
sortList[tid] = sid;
Next I wrote a web method:
[WebMethod]
public static string storeList(DragList dict)
{
DragList dl = dict;
int i = 0;
return "success";
}
public class DragList
{
public string taskName { get; set; }
public string slotName { get; set; }
}
and on the client side I am calling it using:
console.log(JSON.stringify(sortList));
$.ajax({
type: "POST",
url: "Jobs.aspx/storeList",
data: JSON.stringify({dict: sortList}),
contentType: "application/json; charset=utf-8",
dataType: "json",
success: function(msg) {
}});
}
My problem is in the webmethod, the DragList object dict is always null, though in the request, dict is a json object with value in it.
I have been stuck too long now on this and almost planning to move to hidden field to get the task done. But would really appreciate if some one could point me in the right direction.
Changes I made after:
I am using tid as a key to find sid in the object array, so if I break it into parts, I will lose the key value pairing. Instead, I created a new string in a proper JSON format:
jsonStr = "{";
var w = 0;
for (var key in sortList) {
var obj = sortList[key];
jsonStr += '"key":{"taskName":"' + key + '", "slotName":"' + obj + '"},';
w++;
}
jsonStr = jsonStr.substring(0, jsonStr.length - 1);
jsonStr += '}';
console.log(jsonStr);
$.ajax({
type: "POST",
url: "Jobs.aspx/storeList",
data: {dict: jsonStr},
contentType: "application/json; charset=utf-8",
dataType: "json",
success: function(msg) {
}});
}
But now, I get the following error:

Your Json is wrong:
You are sending it as
{"taskName:mainContent_ptask5":"alotName:mainContent_palot0"}
Instead of
{"taskName":"mainContent_ptask5", "alotName":"mainContent_palot0"}
Former considers the property name as taskName:mainContent_ptask5 so it cannot deserilaize to your argument name taskName or slotName
The culprit must be:
var sortList = {};
sortList[tid] = sid; // here i guess tid is "taskName:mainContent_ptask5" and sid is "alotName:mainContent_palot0"
Instead try something like this:
var tidParts = tid.split(':');
var sidParts = sid.split(':');
var sortList = {
};
sortList[tidParts[0]] = tidParts[1];
sortList[sidParts[0]] = sidParts[1];

Related

Error: Undefined object! while parsing JSON using jquery

This should be simple but I cannot seem to get this to work correctly.
Given a JSON string that looks like this:
{
"?xml":
{
"#version":"1.0",
"#encoding":"ISO-8859-1"
},
"results":
{
"title":"AOL Movies - Closest Theater and Showtimes",
// etc,
"theater":
{
"theaterId":"10650",
"id":"10650",
// etc
},
"movie":
[
{
"studios":"Warner Bros.",
"movieId":"61683"
}
]
}
I continually get undefined objects when trying to get to any value, for example:
data.movie, or data.results.title.
Everything "looks" ok in the output.
jQuery.ajax({
type: 'GET',
contentType: 'application/json',
url: 'handler.ashx',
data: 'zip=' + postalCodes.join(','),
success: function (payload) {
var data = that.objectifyJSON(payload); // this returns typeof = object
that.constructMoviesArray(data);
},
error: function (error) {
alert(error.responseText);
}
});
this.constructMoviesArray = function (data) {
var key, movie, theater = null;
var movies = {};
movies.items = {};
movies.length = 0;
alert(data[0].movie); // FAIL - there's clearly an array but nothing displays
I hope this is enough information; I am not experienced with JSON and jQuery so I'm struggling to figure out why I can't seem to resolve this.
Add the json dataType. http://api.jquery.com/jquery.ajax/
The server response is probably still a string even though you set the contentType.
jQuery.ajax({
type: 'GET',
contentType: 'application/json',
url: 'handler.ashx',
data: 'zip=' + postalCodes.join(','),
dataType: 'json', // <--- UPDATE ME
success: function (payload) {
var data = that.objectifyJSON(payload); // this returns typeof = object
that.constructMoviesArray(data);
},
error: function (error) {
alert(error.responseText);
}
});
If that doesn't help, try adding a console.log or a breakpoint to the success callback. You'll be able to take a closer look at what kind of data you are working with in payload.
success: function (payload) {
console.log(payload);
},
Hope that helps!
Try Like
var geocodingAPI = "http://maps.googleapis.com/maps/api/geocode/json?address=1600+Amphitheatre+Parkway,+Mountain+View,+CA&sensor=true";
$.getJSON(geocodingAPI, function (json) {
// Set the variables from the results array
var address = json.results[0].formatted_address;
console.log('Address : ', address);
var latitude = json.results[0].geometry.location.lat;
console.log('Latitude : ', latitude);
var longitude = json.results[0].geometry.location.lng;
console.log('Longitude : ', longitude);
// Set the table td text
$('#address').text(address);
$('#latitude').text(latitude);
$('#longitude').text(longitude);
});
Demo

asmx round trip json

I am calling an asmx webservice which returns json (msg.d) that is consumed properly by knockout.js. When I attempt to return the identical json to asmx, I get error messages. Is there something obvious I'm missing? ... msg.d is a well formed object array.
calling storeGroupCategories(msg.d); returns webservice error ...
{"Message":"Invalid JSON primitive: Baby+Books."
calling storeGroupCategories(msg); returns webservice error ...
{"Message":"Invalid JSON primitive: d."
WebService
public class kbo_inexcludecategories : WebService
{
[WebMethod]
public List<Group> GetIncludeExcludeJson()
{
var Groups = new List<Group>();
ShopAssistGroupHandler.getInExCategories(Groups);
return Groups;
}
[WebMethod]
public GroupGuid StoreGroupCategories(List<InExCategory> inExCategories)
{
var inExString = JsonConvert.SerializeObject(inExCategories);
var returnGuid = DataHandler.SaveGroupJsonString(inExString);
return new GroupGuid(returnGuid);
}
}
Associated json ...
var _url = "kbo-inexcludecategories.asmx/";
var _method = "GetIncludeExcludeJson";
var _jsonData = "{}";
function storeGroupCategories(groupCategories) {
if(groupCategories != ""){
showProgressBar("Storing Group Categories");
getJsonData(_url, "StoreGroupCategories", groupCategories);
}
}
function getGroupMatrix() {
showProgressBar("Loading Group Categories");
getJsonData(_url, _method, _jsonData);
}
function getJsonData(url, method, jsonData) {
var myUrl = url + method;
$.ajax({
type: "POST",
url: myUrl,
data: jsonData,
contentType: "application/json; charset=utf-8",
dataType: "json",
async: false, //blocks window close
success: onSuccess,
error: onError
});
}
function onSuccess(msg) {
// Hide the fake progress indicator graphic.
hideProgressBar("");
if(msg.d.hasOwnProperty("Guid")) {
saveGroupGuid(msg.d);
}
else {
storeGroupCategories(msg.d);
//showGroupAccordion(msg.d);
//OpenAdvancedDialog();
}
}
json sample ...
"{\"groups\":[{\"__type\":\"group\",\"id\":1488,\"name\":\"Baby Books\",\"categories\":
[{\"__type\":\"groupcategory\",\"id\":152,\"name\":\"Activity Books\",\"value\":\"Included\"},
{\"__type\":\"groupcategory\",\"id\":167,\"name\":\"Bedtime and Dreams\",\"value\":\"Excluded\"}
To begin with I think you need to pass your json in like this:
storeGroupCategories(msg.d)
But within this function you also need to create valid json parameters to the post, which would look like this:
getJsonData(_url, "StoreGroupCategories", "{ inExCategories: " + groupCategories + " }");
I would also change your signature to the following, so groups matches the argument you are passing across:
public GroupGuid StoreGroupCategories(List<InExCategory> groups)
If you put a break point in the web page method, you will see exactly what is coming across, and check that it is what you are expecting.

JSON return data is always null from WebService (C#.NET)

I have stepped through my WebServices code to validate that I am actually returning data, but when I check the return on the JSON side, it always says "null."
Here is a snippet of the WebService code.
UPDATED: To simplify things greatly, I'm returning a simple List from the web service instead of a custom object, and I've condensed the AJAX call as well.
[WebMethod]
[ScriptMethod(ResponseFormat = ResponseFormat.Json)]
public List<string> GetLocations(string CustomerID)
{
List<string> LocationsList = new List<string>();
string sql = "select customer_site from demand_addresses where customer_identifier=" + CustomerID;
if (gDB.ExecuteRet(sql, "DB"))
{
DataTable dt = gDB.GetResultDataSet(0);
int i = 0;
if (dt.Rows.Count > 0)
{
foreach (DataRow rs in dt.Rows)
{
LocationsList.Add(rs["customer_site"].ToString());
}
}
else
{
LocationsList.Add("No Data Found.");
}
return LocationsList;
}
else
{
LocationsList.Add("No Data Found.");
return LocationsList;
}
And here is the AJAX call (UPDATED to reflect Kami's comments below):
$.ajax({
type: "POST",
url: "/webservices/services.asmx/GetLocations",
data: "{ 'CustomerID': '" + selectedCustomer + "' }",
contentType: "application/json; charset=utf-8",
dataType: "json",
success: function (data) { alert(data.d); },
error: function (status) {alert(status);}
});
The "alert(data.d)" line results in "TypeError: data is null", and if I change it to "alert(data)" I simply get an alert box that says "null."
I need help understanding why the web service is properly returning data, but it's not making it back to AJAX/JSON.
You are not passing the variable to the OnSuccess function.
Also, I have had issues in the past where you need to use an anonymous function to call your subfunction.
Try something like this
$.ajax({
type: "POST",
url: "/webservices/services.asmx/GetLocations",
data: "{ 'CustomerID': '" + selectedCustomer + "' }",
contentType: "application/json; charset=utf-8",
dataType: "json",
success: function(data, resp) { OnSuccess(data,resp)}, // anon function may be needed
error: function(data,resp) { OnError(data,resp)}
});
I was working on wcf webservice a days back and same was happening to me. At the final return statement everything was working fine. The data was there but when i saw it on the other side there was nothing.
The problem was custom object (in your case LOCATION) had a nullable property but was not defined as nullable. I did that and it started working. I am still not sure why but you should try it once.
public class Location
{
public string? customer_identifier { get; set; }
public string[]? customer_site { get; set; }
}

Complex type is getting null in a ApiController parameter

I don´t know why my parameter "ParametroFiltro Filtro" is getting null, the other parameters "page" and "pageSize" is getting OK.
public class ParametroFiltro
{
public string Codigo { get; set; }
public string Descricao { get; set; }
}
My ApiController Get method:
public PagedDataModel<ParametroDTO> Get(ParametroFiltro Filtro, int page, int pageSize)
My ajax call:
var fullUrl = "/api/" + self.Api;
$.ajax({
url: fullUrl,
type: 'GET',
dataType: 'json',
data: { Filtro: { Codigo: '_1', Descricao: 'TESTE' }, page: 1, pageSize: 10 },
success: function (result) {
alert(result.Data.length);
self.Parametros(result.Data);
}
});
You are trying to send a complex object with GET method. The reason this is failing is that GET method can't have a body and all the values are being encoded into the URL. You can make this work by using [FromUri], but first you need to change your client side code:
$.ajax({
url: fullUrl,
type: 'GET',
dataType: 'json',
data: { Codigo: '_1', Descricao: 'TESTE', page: 1, pageSize: 10 },
success: function (result) {
alert(result.Data.length);
self.Parametros(result.Data);
}
});
This way [FromUri] will be able to pick up your complex object properties directly from the URL if you change your action method like this:
public PagedDataModel<ParametroDTO> Get([FromUri]ParametroFiltro Filtro, int page, int pageSize)
Your previous approach would rather work with POST method which can have a body (but you would still need to use JSON.stringify() to format body as JSON).
Provide the contentType property when you make the ajax call. Use JSON.stringify method to build the JSON data to post. change the type to POST and MVC Model binding will bind the posted data to your class object.
var filter = { "Filtro": { "Codigo": "_1", "Descricao": "TESTE" },
"page": "1", "pageSize": "10" };
$.ajax({
url: fullUrl,
type: 'POST',
dataType: 'json',
contentType: 'application/json',
data: JSON.stringify(filter),
success: function (result) {
alert(result.Data.length);
self.Parametros(result.Data);
}
});
It's also possible to access POST variables via a Newtonsoft.Json.Linq JObject.
For example, this POST:
$.ajax({
type: 'POST',
url: 'URL',
data: { 'Note': note, 'Story': story },
dataType: 'text',
success: function (data) { }
});
Can be accessed in an APIController like so:
public void Update([FromBody]JObject data)
{
var Note = (String)data["Note"];
var Story = (String)data["Story"];
}
If you append json data to query string, and parse it later in web api side. you can parse complex object too. It's useful rather than post json object, espeicaly in some special httpget requirement case.
//javascript file
var data = { UserID: "10", UserName: "Long", AppInstanceID: "100", ProcessGUID: "BF1CC2EB-D9BD-45FD-BF87-939DD8FF9071" };
var request = JSON.stringify(data);
request = encodeURIComponent(request);
doAjaxGet("/ProductWebApi/api/Workflow/StartProcess?data=", request, function (result) {
window.console.log(result);
});
//webapi file:
[HttpGet]
public ResponseResult StartProcess()
{
dynamic queryJson = ParseHttpGetJson(Request.RequestUri.Query);
int appInstanceID = int.Parse(queryJson.AppInstanceID.Value);
Guid processGUID = Guid.Parse(queryJson.ProcessGUID.Value);
int userID = int.Parse(queryJson.UserID.Value);
string userName = queryJson.UserName.Value;
}
//utility function:
public static dynamic ParseHttpGetJson(string query)
{
if (!string.IsNullOrEmpty(query))
{
try
{
var json = query.Substring(7, query.Length - 7); //seperate ?data= characters
json = System.Web.HttpUtility.UrlDecode(json);
dynamic queryJson = JsonConvert.DeserializeObject<dynamic>(json);
return queryJson;
}
catch (System.Exception e)
{
throw new ApplicationException("can't deserialize object as wrong string content!", e);
}
}
else
{
return null;
}
}
In .NET Core, the HttpClient sets the transfer-encoding: chunked header by default. This can cause the .NET Web API controller parameters to be null.
To get around this, you'll need to set the ContentLength header explicitly:
var json = JsonConvert.SerializeObject(myObject);
var content = new StringContent(json, Encoding.UTF8, "application/json");
content.Headers.ContentLength = json.Length;
var response = await client.PostAsync("http://my-api.com", content);
SO answer if you already know the transfer-encoding header is the issue: How to disable Chunked Transfer Encoding in ASP.Net C# using HttpClient
Related bug which won't be fixed, which gives some insight into the problem: https://github.com/dotnet/runtime/issues/30283

Why is this jQuery ajax call to C# web method not working

Here is my JS:
function declassifyAjax(e) {
var items = getSelected();
var docIds = new Array();
items.each(get);
//get ids of QcItem/docId we are dealing with
function get(count, el) {
docIds[count] = $(el).parent().attr('id');
}
var dataObj = new Object();
dataObj.batchId = batchId;
dataObj.docIds = docIds;
var dataString = JSON.stringify(dataObj)
//make call to webservice to get html to recreate view showing
//pending declassification
$.ajax({
type: "POST",
url: applicationRoot + 'Models/BatchQC.asmx/declassify',
data: dataString,
contentType: "application/json; charset=utf-8",
success: function (data) {
if (ProcessWebMethodResult.processWebMethodResult(data) == true) {
declassifyProcess(data, e);
}
},
error: function (e) {
alert("Failed to Get declassification details");
}
});
}
And here is my Web Service:
//type to represent the input the declassify method
public class DeclassifyType
{
public int batchId;
public string[] docIds;
}
[WebMethod(EnableSession = true)]
public WebMethodResult declassify(DeclassifyType dataString)
{
}
Any and all help appreciated!
Debugging in Firebug shows that the variables dataObj, batchId, docIds and dataString are correct. There is something wrong with the way my Web Method signature is setup I think, because the Ajax is never fired off. When stepping through the .ajax method, it goes to error, not success.
Your web methods expects one parameter, the data object you already have, but you're passing multiple parameters since you're passing the object directly.
Instead, you need to have an object with one property, dataString, and that property's value should be your object, like this:
var dataString = JSON.stringify({ dataString: dataObj });
▲--should match--▼
public WebMethodResult declassify(DeclassifyType dataString)
Ah, I just fixed it,
just changed the signature to
[WebMethod(EnableSession = true)]
public WebMethodResult declassify(int batchId, string[] docIds)
{
}
Simple really. Thanks for checking my post!

Categories