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.
Related
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.
I am working on asp.net web api. I am trying to make a call to controller(Security) using jquery ajax calls. I have a method in my controller with 3 parameters like,
public WebRequest GetRequest(string method,string type,string endpoint)
{
RSACryptoServiceProvider rsa=new RSACryptoServiceProvider();
var request = WebRequest.Create(endpoint);
request.Method = method;
request.ContentType = type;
UnicodeEncoding enc = new UnicodeEncoding();
ServicePointManager.ServerCertificateValidationCallback = delegate { return true; };
request.Headers.Add("Authorization-Token", RSAClass.StringConverter(RSAClass.RSAEncrypt(enc.GetBytes("User1"), rsa.ExportParameters(false), false)));
return request;
}
and i am making a jquery ajax call like,
CreateRequest("GET", "application/json;charset=utf-8", "http://localhost:49847/api/Security", function (request) { alert("Hello"); });
function CreateRequest(method, type, endpoint, callback) {
$.ajax({
url: "api/Security",
data: { method: method, type: type, endpoint: endpoint },
type: "GET",
contentType: "application/json;charset=utf-8",
statusCode: {
200: function (request) {
callback(request);
}
}
});
and also i have customfilterattribute class to validate authorization token like,
public override void OnActionExecuting(System.Web.Http.Controllers.HttpActionContext actionContext)
{
string token;
try
{
token = actionContext.Request.Headers.GetValues("Authorization-Token").First();
}
catch
{
actionContext.Response = new HttpResponseMessage(System.Net.HttpStatusCode.BadRequest) { Content = new StringContent("missing authorization token") };
return;
}
try
{
RSACryptoServiceProvider RSA = new RSACryptoServiceProvider();
UnicodeEncoding enc = new UnicodeEncoding();
AuthUsersRepository.GetAllUsers().First(x => x.Name ==enc.GetString(RSAClass.RSADecrypt(RSAClass.ByteConverter(token), RSA.ExportParameters(true), false)));
base.OnActionExecuting(actionContext);
}
catch
{
actionContext.Response = new HttpResponseMessage(System.Net.HttpStatusCode.Forbidden) { Content = new StringContent("Unauthorized User") };
return;
}
}
when iam making first request it asking me for authorization token. and also showing null values in the 3 parameters(method,type,endpoint). guide me.
You need this:
data: { 'method': method, 'type': type, 'endpoint': endpoint },
This passes the values in the request, although in your example I'm not sure why you would need to pass endpoint as a parameter to the method if its value is the URL of the controller / action?
You either need to
1) change your GET to POST the data as JSON. GET cannot have content.
2) Pass the data as query string parameters
If I am to do it myself, I would go for case 2:
http://localhost:49847/api/Security?method=someMethod&type=someType&endpoint=someendpoint
Since this is security related, it has to be HTTPS.
But I would not do it myself, instead use what security experts have developed: "Thinktecture.IdentityModel.40"
https://github.com/thinktecture/Thinktecture.IdentityModel.40
I was able to get the actual error message before when I was using jquery ajax+ asp.net web services. However, the same code inside jquery $ajax error no longer works.
Inside my .js I have
$.ajax({
contentType: 'application/json, charset=utf-8',
type: "POST",
url: "/Controller/DoSomething",
data: JSON.stringify({ varname: varvalue }),
cache: false,
dataType: "json",
success: function (wo) {
alert('yay!');
},
error: function (xhr) {
alert('error');
if (xhr.responseText) {
var err = JSON.parse(xhr.responseText);
if (err) {
alert(err.Message);
}
else {
alert("Unknown server error, please try again!");
}
}
}
});
Inside my Controller I have
public JsonResult DoSomething(string folderno)
{
CustomObject obj;
//get the obj value from repository here
throw new Exception("my test error message");
return Json(obj);
}
I looked at the Firebug and it appears that I am getting
"JSON.parse: unexpected character" error.
What I am trying to do here is to fake a situation when getting obj from repository throws an exception. Obviously, return Json(obj) never gets reached.
My question is, how do I deal with this situation and trap the error messages on the JS side? Do I need to do something in my controller?
In my earlier set up of Jquery+asp.net web services, I could throw an exception inside my web service method (as shown in my action now) and it would be trapped in my ajax error and the error message would be parsed out.
Now, it would appear that I need to catch the exception and pack in myself....question is how? And do I need to do this inside every action? This seems like a lot of work.
One thing I do is create a generic return object for AJAX calls.
Something like:
public class AJAXReturn
{
public string Message { get; set; }
public object Result { get; set; }
}
Then in your return functions wrap them in Exceptions (or create a generic exception handler) that will look something like:
public JsonResult DoSomething(string folderno)
{
CustomObject obj = new { FolderNo = folderno };
AJAXReturn result;
try
{
result.Message = "OK";
result.Result = obj;
}
catch (Exception ex)
{
result.Message = "ERROR";
result.Result = ex;
}
finally
{
return Json(result);
}
}
Edit: On the javascript side, just check your result for data.Message == 'OK'. If it isn't ok you can display either the specific exception info or anything you want.
Edit 2: Sorry I should've mentioned this will always return in the success callback so make sure you parse it there.
I have an ASP.NET service that I'm access from a asxh file that returns a JSON string. The service works great except when accessed from our blog sub domain which is on a separate server. (blog.laptopmag.com)
Here is my jQuery
$.ajax({
type: "GET",
url: "http://www.laptopmag.com/scripts/service.ashx",
data: { "op": "get_products" },
dataType: "json",
success: function (data) {
alert(data);
}
});
and here is my ashx file
public class service : IHttpHandler {
public void ProcessRequest (HttpContext context) {
string jsonStr = "{}";
string op = context.Request["op"];
// Process request
context.Response.ContentType = "application/json";
context.Response.Write(jsonStr);
}
public bool IsReusable {
get {
return false;
}
}
}
I've tried switching to a jsonp request, but must be doing something wrong because I can't get anything to pull back. Here is what I've tried.
and here is my jsonp attempt that doesn't seem to work when called from blog.laptopmag.com
$.getJSON('http://www.laptopmag.com/scripts/service.ashx?callback=ProcessRequest&op=get_products', function(json) {
console.log(json);
});
OK, I figured out what the problem was with my JSONP request thanks to the following post:
Jquery success function not firing using JSONP
The problem was that the request wasn't getting a response back in the expected format.
Now, my ashx file now looks like this:
public void ProcessRequest (HttpContext context) {
string jsonStr = "{}";
string op = context.Request["op"];
string jsonp = context.Request["callback"];
// Do something here
if (!String.IsNullOrEmpty(jsonp))
{
jsonStr = jsonp + "(" + jsonStr + ")";
}
context.Response.ContentType = "application/json";
context.Response.Write(jsonStr);
}
and the jQuery ajax request looks like this:
$.getJSON('http://www.laptopmag.com/scripts/service.ashx?callback=?&op=get_products', function(json) {
console.log(json);
});
Security restrictions prevent you from making cross-domain jquery ajax calls, but there are workarounds. IMO the easiest way is to create a page on your site that acts as a proxy and hit the page with your jquery request. In page_load of your proxy:
WebClient client = new WebClient ();
Response.Write (client.DownloadString ("your-webservice-url"));
Other solutions can be found by a quick Google search.
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
}
});