jQuery and parsing JSON in the callback - asp.net

I'm using jQuery to call an asmx and return some data. I'm making the call like this
function getRequestInfo(event) {
var id = $('#<%= RequestDaysId.ClientID %>').val();
var formattedId = "{'id': '115'}";
$.ajax({
type: "Post",
url: "services/VacationServices.asmx/GetVacationInfo",
data: "{'id': '" + id + "'}",
dataType: "json",
contentType: "application/json; charset=utf-8",
processdata: true,
success: function(data) {
$('#<%=Note.ClientID %>').val(data.Note);
$('.pendingrequestinfo').show().fadeIn(2000);
},
error: function(result, errortype, exceptionobject) {
$('.failureMessage').fadeIn(2000).fadeOut(2000);
}
})
};
Everything seems to be working fine, I set a break point in my success function and inspect the data object and see this.
"{"Note":"this is a note","dayInfo":[{"ShortDate":"3/4/2010","DayType":"Vacation","HalfDay":""},{"ShortDate":"3/5/2010","DayType":"Vacation","HalfDay":""}]}"
The problem comes when I try to get the values out of the JSON. If I do something like data.Note, I get undefined back.
It's late, It's Saturday and I've been at it all day, I sure would like a push in the right direction when it comes to parsing though my JSON.
EDIT:
I'm using Asp.net and JavaScriptSerializer.Serialize() to create the JSON. When I set a break point and inspect the 'data' object it looks to have a property d that contains the string that should be JSON.
ANOTHER EDIT:
If I do something like this in my success
$('#<%=Note.ClientID %>').val(data.d.[0]);
I get the { opening curly brace. I guess i'm getting a string instead of JSON, but it seems to go against what the jquery api states about the return value when the datatype is set to JSON.
Thanks guys.
Jim

First make sure that the JSON string exists in the "d" variable in the response returned in the success callback. Next, in order to get the JSON object you will need to convert the string into the JSON. You can use the eval function or the JQuery built in function to convert string to JSON. I like the jquery-json plug in to convert string into JSON representation.
Your code will look something like this:
var jsonObject = eval('(' + data.d + ')');
Now, you can use jsonObject.Note or any other property.
With jquery-json plugin you can do the following:
var note = $.evalJSON(data.d).Note;

That's not a valid JSON format. Remove the doublequotes at beginning and end to make it fullworthy JSON.

This one is so silly...sorry guys. When returning data from the asmx there is no need to serialize it into JSON
I have the following class that I'm populating and returing from my web method
public class VacationInfo
{
public string Note { get; set; }
public List<DayInfo> dayInfo { get; set; }
public VacationInfo(string note, List<DayInfo> dayinfo)
{
this.Note = note;
this.dayInfo = dayinfo;
}
public class DayInfo
{
public string ShortDate { get; set; }
public string DayType { get; set; }
public string HalfDay { get; set; }
public DayInfo(string shortdate, string daytype, string halfday)
{
this.ShortDate = shortdate;
this.DayType = daytype;
this.HalfDay = halfday;
}
}
}
as long as your web service is decorated with
[System.Web.Script.Services.ScriptService]
your object will be serialized and returned as JSON at no charge to you. :)
then I'm able to do this
data.d.Note
in my call back.
Thanks for the help guys.
Credit where credit is due

Here is how I process. Note the dataFilter: part - this makes it work with either newer or older asp.net stuff.
$.ajax({
type: "POST",
contentType: "application/json; charset=utf-8",
data: objectSaveData,
dataFilter: function(data)
{
var msg;
if (typeof (JSON) !== 'undefined' &&
typeof (JSON.parse) === 'function')
msg = JSON.parse(data);
else
msg = eval('(' + data + ')');
if (msg.hasOwnProperty('d'))
return msg.d;
else
return msg;
},
url: "/mywebservice.asmx/myMethodName",
success: function(msg)
{
//do stuff
},
failure: function(msg)
{
//handlefail
}
});

Related

AJAX Passing multiple parameter to WebApi

AJAX request:
$.ajax({
url: url,
dataType: 'json',
type: 'Post',
data: {token:"4", feed:{"id":0,"message":"Hello World","userId":4} }
});
Server Side Web API:
[HttpPost]
public HttpResponseMessage Post(string token, Feed feed)
{
/* Some code */
return new HttpResponseMessage(HttpStatusCode.Created);
}
Error Code 404: {"message":"No HTTP resource was found that matches
the request URI 'localhost:8080/api/feed'.","messageDetail":"No action
was found on the controller 'Feed' that matches the request."}
Why I am getting this error and Why I am not able POST multiple parameters to my API?
Start by writing a view model:
public class MyViewModel
{
public string Token { get; set; }
public Feed Feed { get; set; }
}
that your controller action will take as parameter:
[HttpPost]
public HttpResponseMessage Post(MyViewModel model)
{
/* Some code */
return new HttpResponseMessage(HttpStatusCode.Created);
}
and finally adapt your jQuery call to send it as JSON:
$.ajax({
url: url,
type: 'POST',
contentType: 'application/json',
data: JSON.stringify({
token: '4',
feed: {
id: 0,
message: 'Hello World',
userId: 4
}
})
});
Important things to note for the AJAX call:
setting the request contentType to application/json
wrapping the data in a JSON.stringify function to effectively convert the javascript object to a JSON string
removed the useless dataType: 'json' parameter. jQuery will automatically use the Content-Type response header sent by the server to deduce how to parse the result passed to the success callback.
Try this server-side (from memory you can only have a single FromBody parameter so it needs to contain all the incoming properties):
public class TokenAndFeed
{
public String token {get; set;}
public Feed feed {get; set;}
}
public HttpResponseMessage Post([FromBody]TokenAndFeed tokenAndFeed)
{
/* Some code */
return new HttpResponseMessage(HttpStatusCode.Created);
}
I had a similar problem recently and here's some info on how I solved it. I think the problem is to do with how WebApi handles parameters. You can read a bit about it here and here but essentially there are two ways to post parameters, in the body or in the uri. The body can only contain one parameter, but it can be a complex parameter, whereas the uri can contain any number of parameters (up to the uri character limit) but they must be simple. When jquery does a POST ajax call it tries to pass all data parameters in the body, which does not work in your case since the body can only have one parameter.
In code terms I think you need something like this:
var token = "4";
var feed = {Id:0, Message:"Hello World", UserId:4};
$.ajax({
url: "/api/Feed/?token=" + token,
dataType: 'json',
type: 'Post',
data: JSON.stringify(feed)
});
Hope that helps.
Can you post your Feed class, just to make sure the properies match up.
var data = {
token: "4",
feed: {Id:0,Message:"Hello World",UserId:4}
}
$.ajax({
url: "/api/Feed/",
dataType: 'json',
type: 'Post',
data: JSON.stringify(data)
});
Try with this one. You have to get json object data from body. Read Request's input streem and map it to your data model.
public class TokenAndFeed
{
public string Token { get; set; }
public Feed Feed { get; set; }
}
[HttpPost]
public HttpResponseMessage Post()
{
System.IO.Stream str;
String jsonContents;
Int32 strLen, strRead;
str = HttpContext.Current.Request.InputStream;
strLen = Convert.ToInt32(str.Length);
byte[] byteArray = new byte[strLen];
strRead = str.Read(byteArray, 0, strLen);
jsonContents = Encoding.UTF8.GetString(byteArray);
TokenAndFeed tAndf = JsonConvert.DeserializeObject<TokenAndFeed>(jsonContents);
// some code here
return new HttpResponseMessage(HttpStatusCode.Created);
}
hope this will help.

jQuery Ajax: Parse Error Getting Result to Alert Box

I have a very simple ajax call to my handler from jquery which is failing to retrive data and it gives me parsererror when i try to show the result in alert box.
ASP.NET Handler code:
public void ProcessRequest (HttpContext context) {
string json = new StreamReader(context.Request.InputStream).ReadToEnd();
context.Response.ContentType = "application/json";
context.Response.Write(json);
}
Jquery
$('.submit').on("click",function(e) {
e.preventDefault();
var data1 = { "hi": "hello" };
alert(data1.hi);
$.ajax({
url: "/charity-challenge/CompetitionHelper.ashx",
data: data1,
dataType: 'json',
type: 'POST',
contentType: 'application/json; charset=utf-8',
success: function (data) {
alert("response = " + data);
},
error: function (data, status) {
alert("FAILED:" + status);
}
});
});
Note: I can see the response coming fine in chrome while debugging. BUT somehow when i try to show it in alert box it gives me parsererror.
Also, I want to assign the json data in handler. i dont have any clue how to do that.
i have a sample calss like this in handler. how to loop through the json data and assign values to this variables so i can work on those.
public class userData
{
public string EmailAddress { get; set; }
public string EntryId { get; set; }
}
Found the work around to this.
i added a complete callback and now its showing the result in alertbox. i dont know why it is not working without it BUT if someone knows please post the answer.
here is the complete call back.
complete: function(xhr, status) {
if (status === 'error' || !xhr.responseText) {
alert("Error");
}
else {
var data = xhr.responseText;
alert(data);
//...
}
}
It has to do with your request payload being sent by the ajax call as hi=hello
As a test, try this (requires Newtonsoft.Json nuget):
public void ProcessRequest(HttpContext context)
{
//string json = new StreamReader(context.Request.InputStream).ReadToEnd();
context.Response.ContentType = "application/json";
context.Response.Write(JsonConvert.SerializeObject(new { hi = "hello" }));
}
So I guess you have to parse your input stream e generate the json correctly.
You could also fix this in the client side, by calling using JSON.stringify(data1) in your data parameter in the ajax call.

Why am I not able to pass a JSON object to a WCF web service?

I built a fairly complex app using the older "ASMX" web service implementation and I am migrating to WCF. There is one thing that is just driving me crazy - it should be easy but my AJAX calls error out no matter how I try to structure this call. This worked fine with ASMX calls but not with WCF.
Here is the AJAX call:
var ProfileData = new Object();
ProfileData.SUID = SUID;
ProfileData.FirstName = $("#FirstName").val();
ProfileData.LastName = $("#LastName").val();
ProfileData.Birthdate = new Date($("#Birthdate").val());
var DTO = {'ProfileData': ProfileData };
$.ajax({
type: "POST",
url: "AllianceService.svc/SaveBasicProfile",
data: JSON.stringify(DTO),
contentType: "application/json; charset=utf-8",
dataType: "json",
success: function (msg) {
UpdateTips($("#BasicProfileValidate"), "Success! Your data has been updated.");
}
},
error: function (xhr, ajaxOptions, thrownError, request, error) {
alert('Error Saving Basic Profile Data');
}
});
Here is the declaration of the type on the C# / Server side:
[DataContract]
public class BasicFolderData
{
[DataMember]
public string SUID { get; set; }
[DataMember]
public string FirstName { get; set; }
[DataMember]
public string LastName { get; set; }
[DataMember]
public DateTime Birthdate { get; set; }
}
And here is the definition of the service:
[OperationContract]
public int SaveBasicProfile(BasicFolderData ProfileData)
{
... do stuff
}
Now, if I break out all of the datamembers and use them as parameters, I can get this to work with a simple
data: JSON.stringify(ProfileData)
But the object is actually much longer than this and I'd like to know how to pass objects.
Also, I have tried:
data: JSON.stringify({"ProfileData": ProfileData }),
and
data: JSON.stringify('{"ProfileData":' + ProfileData + '}'),
and
data: '{"ProfileData":' + JSON.stringify(ProfileData) + '}',
but all to no avail...I get the error message on all of them.
If I use:
data: JSON.stringify(ProfileData),
then, oddly enough, the request makes it to the server but the ProfileData parameter is null. I suspect that the problem is my datacontract but don't know where to start. Also, I have a lot of functions with scalar parameters that work just fine - it is only when I attempt to pass objects that I fail. Any help would be greatly appreciated!!
Following DonAndre's suggestion, I have found that simply changing the parameter to a scalar type will make the call succeed. However, the parameter is always null.
WCF wraps the JSON with a d if you have enableWebScript set to true in your config on the server. Take a look here: JsonConvert.DeserializeObject and "d" wrapper in WCF
Ok - the problem was trivial: the "BasicFolderClass" had a DateTime field (Birthdate) in it.
When JSON.stringify is called on the DTO object, it turns the DateTime field in the javascript side into a string before sending it up. The mismatch on that field between the JSON string being presented and the DateTime being expected is what led to the error.

How to call non static method from AJAX?

Here is my code behind I am calling from AJAX...
[WebMethod]
[ScriptMethod]
public static string save(string parameter)
{
country_master obj_country = new country_master();
obj_country.Country_Name = Page.Request.Params["name"].ToString().Trim();
obj_country.saved();
return "";
}
Here I am not able to access parameters passed from the page via Page.Request.
string name = HttpContext.Current.Request.QueryString["name"].Trim();
return "error";
after writing the first line, return statement does not return anything to the AJAX.
Please Help me how to do that.
Thanks...
To get the current context you can use HttpContext.Current, which is a static property.
Once you have that you can access things like session or profile and get information about the state of the site
HttpContext.Current.Session etc..
This link may help you : Call Server Side via AJAX without a Static Method
The reason behind restricting the web method to be static is to avoid it access the controls of the instance page.
Yo could use the HttpContext.Current static class, however you can skip that if you declare on your method the parameters you want to use and just pass the parameters with your AJAX call
You should pass parameters directly to the method.
I have several working examples on my Github repository, feel free to browse the code.
As a summary, to call a PageMethod:
Note: how using AJAX the jobID PageMethod parameter is being passed along with the request and how is used inside the PageMethod transparently
AJAX call
$.ajax({
type: 'POST',
url: '<%: this.ResolveClientUrl("~/Topics/JQuery/Ajax/PageMethods_JQueryAJAX.aspx/GetEmployees") %>',
contentType: 'application/json; charset=utf-8',
dataType: 'json',
data: '{"jobID" : ' + jobID +'}',
async: false,
cache: false,
success: function (data) {
$('#employees').find('option').remove();
$.each(data.d, function (i, item) {
$('<option />').val(item.EmployeeID).text(item.FirstName).appendTo('#employees');
});
},
error: function (xhr) {
alert(xhr.responseText);
}
});
Page Method
[WebMethod]
public static List<EmployeeModel> GetEmployees(int jobID)
{
var ctx = new PubsDataContext();
return (from e in ctx.employee
where e.job_id == jobID
orderby e.fname
select new EmployeeModel
{
EmployeeID = e.emp_id,
FirstName = e.fname
}).ToList();
}

Pass JSON to MVC 3 Action

I am trying to submit JSON to a MVC action. What I want is to take the JSON object and then access it's data. The number of JSON fields will vary each time so I need a solution that will handle all cases.
This is my POST to my action, address could have 3 fields or 20 it will vary on each post.
Update: I'll go into a little more detail. I'm trying to use the LinkedIn API, I'll be sent a JSON which will look like the JSON at the end of this page : link. I need to create an Action which will accept this JSON which will vary for every person.
var address =
{
Address: "123 rd",
City: "Far Away",
State: "Over There"
};
$.ajaxSetup({ cache: false });
$.ajax({
type: "POST",
contentType: "application/json; charset=utf-8",
url: "/Account/GetDetails/",
data: JSON.stringify(address),
dataType: "json",
success: function () {
alert("Success from JS");
}
});
This is my action in MVC, I need to be apply to take whatever JSON object is passed and access its fields.
[HttpPost]
public ActionResult GetDetails(object address)
{
//address object comes in as null
#ViewBag.Successs = true;
return View();
}
I don't believe nobody saying this so I will try. Have your code like this
public class Personal
{
public string Address { get; set; }
public string City { get; set; }
public string State { get; set; }
//other properties here
}
[HttpPost]
public ActionResult GetDetails(Personal address)
{
//Should be able to get it.
#ViewBag.Successs = true;
return View();
}
In general, you can add those possible properties into the class Personal (or whatever you can name it). But according to linkedin API, you will need a tool to generate the data class due to its complexity. I think xsd.exe can help if you can get xsd file for that (or you can even generate xsd file from xml)
Remove data: JSON.stringify(address) with data: address
Action method
[HttpPost]
public ActionResult GetDetails(string Address, string City, string State, string PropName)
{
//access variable here
}
As you have said your data object may contain 20 props, to avoid creating 20 parameters, you can use formscollection like below
[HttpPost]
public ActionResult GetDetails(FormCollection address)
{
string city= address["city"] ;
string anotherPro=address["prop"];
}
Not sure if this will work (never done this myself), but you could try the following signature:
public ActionResult LinkedIn(dynamic address)
I'm actually quite interested myself to see what will happen then. Or, as suggested in the comment by Kristof Claes, use a FormCollection.
Second, when things like this happen, always check whether the browser actually sends the data you expected to the server. IE9 and Chrome support this out of the box, otherwise you can use a tool like Fiddler.
EDIT: Just tried for myself with a dynamic parameter and that doesn't work.. The runtime type of the parameter is object so everything you submitted is lost. You'd better
use FormCollection.
I believe you can use a FormCollection for this.
public ActionResult LinkedIn(FormCollection address)
{
var street = address["street"];
...
return View();
}
Might just be a typo, but you are calling GetDetails ActionResult, but yet your code is LinkedIn ?
You need to wrap your JSON object in the name of parameter you are expecting in your action method. Something like this:
var data = { address: { address: '123 Test Way', city: 'Parts Unknown', state: 'TX' } };
$.ajax({
type: "POST",
contentType: "application/json; charset=utf-8",
url: "/Account/GetDetails/",
data: JSON.stringify(data),
dataType: "json",
success: function () {
alert("Success from JS");
}
Then in your action method, do this:
public ActionResult GetDetails(dynamic address) {}
My take is all the answers are sort of right.
As your don't know the number of things you're sending, use formcollection on the server. But also remove the stringfy from the ajax call. These means the data will be sent using www-encoding.
If you wnat to send n address objects, change the mvc action parameter to an array of address objects and use stringfy.
This is how I do it. I have a MyProject.Model.Entities and I serialize them in by using [ParamSerializationFilter] attribute on the given action method.
Full code here: https://gist.github.com/3b18a58922fdd8d5a963
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
if (!Enum.GetNames(typeof(AllowedMethods)).Any(n => n == filterContext.HttpContext.Request.HttpMethod))
throw new InvalidOperationException("Invalid Request: HttpMethod");
foreach (var param in filterContext.ActionDescriptor.GetParameters())
{
if (ModelTypes.Contains(param.ParameterType))
{
if ((filterContext.HttpContext.Request.ContentType ?? string.Empty) == ("application/json"))
{
filterContext.ActionParameters[param.ParameterName] =
JsonSerializer.DeserializeFromStream(param.ParameterType, filterContext.HttpContext.Request.InputStream);
}
else if (filterContext.HttpContext.Request.ContentType.Contains("xml"))
{
filterContext.ActionParameters[param.ParameterName] =
XmlSerializer.DeserializeFromStream(param.ParameterType, filterContext.HttpContext.Request.InputStream);
}
}
}
}
You're doing too much work! You can pass the JSON Literal directly to the server and access the elements via the action method parameters, like this:
var address =
{
Address: "123 rd",
City: "Far Away",
State: "Over There"
};
$.ajaxSetup({ cache: false });
$.ajax({
type: "POST",
contentType: "application/json; charset=utf-8",
url: "/Account/GetDetails/",
data: address,
dataType: "json",
success: function () {
alert("Success from JS");
}
});
[HttpPost]
public ActionResult LinkedIn(string Address, string City, string State)
{
// now you have everything you want as params
#ViewBag.Successs = true;
return View();
}
Note: This will only work if your action params are named the exact same as your JSON Literal attributes.

Resources