Reputation: 5631
I've got an odd case where my jquery.post returns a code #200 (OK) but the error-handler is hit.
This is my MVC WebAPI serverside code (all it does is returning code #200 OK):
[HttpPost]
public HttpResponseMessage Post(T input)
{
//_handler.Create(input);
return Request.CreateResponse(HttpStatusCode.OK);
}
and this is my client script
ServerAccess.prototype.Save = function (m) {
$.post("http://localhost:55482/M/", m)
.success(
function (o) {
alert("success");
})
.error(
function (xhr, textStatus, errorThrown) {
if (typeof console == 'object' && typeof console.log == 'function') {
console.log(xhr);
console.log(textStatus);
console.log(errorThrown);
}
}
);
};
The console output in Firebug is:
POST
http://localhost:55482/M/
200 OK 894msHeaders
Response Headers
Content-Length 6
Content-Type application/json; charset=utf-8
Date Sun, 28 Oct 2012 18:55:17 GMT
Server Microsoft-HTTPAPI/2.0
Request Headers
Accept /
Accept-Encoding gzip, deflate
Accept-Language nb-no,nb;q=0.9,no-no;q=0.8,no;q=0.6,nn-no;q=0.5,nn;q=0.4,en-us;q=0.3,en;q=0.1
Connection keep-alive
Content-Length 21
Content-Type application/x-www-form-urlencoded; charset=UTF-8
Host localhost:55482
Origin null
User-Agent Mozilla/5.0 (Windows NT 6.2; WOW64; rv:16.0) Gecko/20100101 Firefox/16.0
and
Object { readyState=0, status=0, statusText="error"}
error
(an empty string)
I've browsed around and seen others had similar problems, usually malformed JSON in the response. Since I only return a 200 OK an no content this doesn't seem to fit my case. However I did try to return a empty object like so
var o = new System.Web.Script.Serialization.JavaScriptSerializer().Serialize(new T());
return Request.CreateResponse(HttpStatusCode.OK, o);
The serverside runs from Visual Studio 2012, and the client is just a standalone .html with some .js files. Also, with a breakpoint in VS I know the request is received by the server, and with Postman for Chrome everyting works great.
So the question is of course: what am I doing wrong here? Why is the error-handler hit?
Thanks!
Upvotes: 9
Views: 4541
Reputation: 890
I have just encountered this issue while using a JSON request to a WebApi 2 service. For me, it was solved by simply changing the parameter list for the success and error functions (no changes were needed on the WebApi side)
I changed my code from this
success: function (data) { alert(data); },
error: function (error) { jsonValue = jQuery.parseJSON(error.responseText); }
to this
success: function (data, textStatus, xhr)
{
alert("data: " + data + "\ntextStatus: " + textStatus + "\nxhr: " + xhr);
},
error: function (xhr, textStatus, errorThrown)
{
alert("xhr: " + xhr + "\ntextStatus: " + textStatus + "\nerrorThrown " + errorThrown);
}
Note the change in the arguments list
Upvotes: 0
Reputation: 4120
It's quite possible it has something to do with the empty response you are sending. See this bug report: http://aspnetwebstack.codeplex.com/workitem/1664
You can solve this by setting an empty string as response.
return Request.CreateResponse(HttpStatusCode.OK, "");
The bug report contains a workaround, which involves creating a message handler which adds an empty string where content == null.
public class HttpResponseMessageHandler : DelegatingHandler
{
protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, System.Threading.CancellationToken cancellationToken)
{
var response = await base.SendAsync(request, cancellationToken);
if (response.Content == null && request.Headers.Accept.Any(a => a.MediaType == "application/json"))
{
var content = new StringContent("{}");
content.Headers.ContentLength = 2;
content.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue("application/json");
response.Content = content;
}
return response;
}
}
Upvotes: 0
Reputation: 2676
As I understood you need cross-domain so you should have a handler or service caller
read THIS it might be useful for you.
Add JsonpFormatter as filter in application start then you can enjoy jsonp.
Upvotes: 0
Reputation: 25081
Try this instead:
ServerAccess.prototype.Save = function (m) {
$.ajax({
"type": "POST",
"url": "http://localhost:55482/M/",
"data": m,
"dataType": "json",
"success": function (data, textStatus, xhr) {
alert("success");
},
"error": function (xhr, textStatus, errorThrown) {
if (typeof console === 'object' && typeof console.log === 'function') {
console.log(xhr);
console.log(textStatus);
console.log(errorThrown);
}
}
});
};
This allows you to set an expected return MIME type of application/json
.
UPDATE
If you're running your standalone HTML page on http://localhost:55482
, then it won't be cross-domain. If you're running it on file:///C:/Users/.../Desktop/test.htm
or somewhere else, then it will be a cross-domain request. http
versus https:
also makes the difference.
A jsonp
request is a GET
request and cannot be a POST
. This is because jsonp
requests are implemented by adding a <script>
element to the page with the source set to your url, with data
appended to the querystring (plus a timestamp parameter). Any POST
requests that expect a jsonp
return should be automatically converted to GET
requests.
Finally, since your routine expects data back, you'll need to return some actual data as jQuery will try to parse the JSON that's returned into an object (which it cannot do if no data is returned) and will throw an error if the data cannot be parsed.
Try changing your response message to:
String o = "success";
System.Web.Script.Serialization.JavaScriptSerializer ser = new System.Web.Script.Serialization.JavaScriptSerializer();
return Request.CreateResponse(HttpStatusCode.OK, ser.Serialize(o));
Upvotes: 3