jqGrid: displaying server error message - jqgrid

I have a jqGrid edit form that contains a date field. I want to implement exception handling so that error messages from the server will be displayed in the edit form. Example response:
HTTP/1.1 400 Bad Request
Server: Apache-Coyote/1.1
Date: Fri, 28 Jun 2013 15:47:21 GMT
Content-Type: application/json
Transfer-Encoding: chunked
Connection: close
11
"Bad Date format"
0
jqGrid only displays "error status:'Bad Request' Error Code: 400", at the top of the form. How can I have it also display the error message: "Bad Date format" ?

You should use errorTextFormat callback of form editing. As the parameter the callback get jqXHR object which is wrapper on XMLHTTPRequest object. It's responseText property represent the body of the response (11\n"Bad Date format"\n0 in your case). The status property gets you the HTTP status code (400 in your example). You can use getResponseHeader and getAllResponseHeaders to examine all HTTP headers.
By the way I find very strange that the response contains Content-Type: application/json, but the body of the response don't contains JSON string.

Assume that your response contains 2 fields: status (OK, ERROR,..) and message then you should write a function like this:
validateAfterSubmit = function(response, postdata){
var json = response.responseText; // response text is returned from server.
var result = JSON.parse(json); // convert json object into javascript object.
return [result.status == 'OK', result.message, null];
};
and specify in the edit/add options:
//edit options
{ url: '...',
afterSubmit: validateAfterSubmit
},
//add options
{ url: '...',
afterSubmit: validateAfterSubmit
},
hopefully this can help

Related

"The length of the string exceeds the value set on the maxJsonLength property" isn't respecting the web.config value?

I asked this question the other day but was not able to come up with a solution:
What happens between clicking a button and the Javascript method actually executing?
Posting a new question with better information including a screenshot of the ajax request, the details from the request / response, as well as my own understanding of what was going on yesterday more clearly so I could debug it better.
My jQuery sends the following request to my server:
The RtfErrorList in data is north of 4 million characters and includes RTF encoding.
Despite adding a variety of XML nodes to my web.config to increase the the maxJsonLength, I'm still getting this exception.
If I look at the network tab in Chrome's dev tools, I get the following information (I stripped some unimportant bits out like origin: locahost and other things like that)
Request Method:POST
Status Code:500 Internal Server Error
Response Headers:
HTTP/1.1 500 Internal Server Error
Content-Type: text/html; charset=utf-8
Server: Microsoft-IIS/7.5
X-AspNet-Version: 4.0.30319
X-UA-Compatible: IE=Edge
Request Headers:
Content-Length: 3799356
Content-Type: application/json;
Accept: text/html, /; q=0.01
X-Requested-With: XMLHttpRequest
Request Payload:
FileName : "someFileName"
RtfErrorList : "some4MillionCharacterStringIncludingRtfEncoding"
The last few entries from the stack trace:
[ArgumentException: Error during serialization or deserialization using the JSON JavaScriptSerializer. The length of the string exceeds the value set on the maxJsonLength property.
Parameter name: input]
System.Web.Script.Serialization.JavaScriptSerializer.Deserialize(JavaScriptSerializer serializer, String input, Type type, Int32 depthLimit)
System.Web.Mvc.JsonValueProviderFactory.GetValueProvider(ControllerContext controllerContext)
System.Web.Mvc.ValueProviderFactoryCollection.GetValueProvider(ControllerContext controllerContext)
I've tried adding the following keys to my web.config:
<add key="JSONMAXJSONLENGTH" value="2147483644" />
<add key="aspnet:MaxJsonDeserializerMembers" value="2147483644" />
I'm actually not sure what that first node is from; it was here before me.
As well as the snippet found here.
Per this SO answer it is my understanding these web.config values are used only by the internal JavaScriptSerializer class, not any "custom" code I might write in a controller myself. In that case, this should be fine as it is System.web.SCript.Serialization.javaScriptSerializer.Deserialize that is throwing the exception. This should be using the web.config value, right?
I cannot figure out what could possibly be causing this...
Are you expecting to receive html format as you set dataType:'html' in Ajax ?
Did you try this in your Ajax:
data: JSON.stringify(data),
contentType: 'application/json; charset=utf-8',
dataType: 'json',
Moreover, according to the documentation, the value of the MaxJsonLength property applies only to the internal JavaScriptSerializer instance that is used by the asynchronous communication layer to invoke Web services methods.
In this case, you may need to serialize manually in the controller. For instance:
public ActionResult FOO()
{
var serializer = new JavaScriptSerializer { MaxJsonLength = Int32.MaxValue };
// You could also read MaxJsonLength from your config
//serializer.MaxJsonLength = Int32.MaxValue;
var myLargeData = new {
ID = "5",
Foo = "Bar",
Value = "foo"
};
var result = new ContentResult
{
Content = serializer.Serialize(myLargeData),
ContentType = "application/json"
};
return result;
}

Why does JSONP work with JSON-formatted data?

There is a URL I am using in a project of mine, that is working just fine. I make a request from one web server, to a different IP address, invoking a page that outputs data in this format:
[{"PhoneNumber":"+123456789","Name":"Mark"},
{"PhoneNumber":"+123456789","Name":"Josh"},
{"PhoneNumber":"+123456789","Name":"Alex"},
{"PhoneNumber":"+123456789","Name":"John"},
{"PhoneNumber":"+123456789","Name":"Sean"}]
And I can get and process that data with a function call such as this:
$.ajax({
url: serverAddress + "/getpeople",
dataType: "jsonp",
timeout: 4000,
success: function(response) {
for(var i in response) {
alert(response[i].Name);
}
}
});
Here is what's confusing me. From what I've learned about JSONP so far, it isn't actually data, but is instead a function. So the response should be wrapped in a function call, such as callback(), and then I could implement a function callback(data) {} in my project to process the data.
But in this case, the data seems to be just JSON data, which I think should cause a cross-origin error to be generated? But it doesn't.
When I try to call another URL from the same server, fetching an ordinary plain text file, then I do get a cross-origin error, which complains in the console:
Reason: CORS header 'Access-Control-Allow-Origin' missing
But the original getpeople URL does not have that header either. When I examine the response headers in Firefox's document inspector, all of the headers are:
Connection: "close"
Content-Type: "text/html;charset=utf-8"
Date: "Mon, 5 Oct 2015 08:29:07 GMT"
Server: "ServerName/1.1.10011.2211"
So:
The data is not formatted as a JSONP callback
It is served from a different IP address than the web application
The response doesn't have a Access-Control-Allow-Origin header
Why does this work?

Always empty response with $.getJSON

I have a simple web service that outputs a JSON object to a client.
If accessed with a plain browser it outputs the JSON string. However when accessed with $.getJSON it always return a empty response although there is a response header:
Content-Type application/json; charset=utf-8
Content-Length 122
Connection keep-alive
The code for the call is like this:
$.getJSON('http://192.168.0.1/api/v1/search', { query : $('#searchfield').val() },
function(data){
$.log("Response: %s", data.some_field);
}
);
Also the callback function is not invoked.
Any ideas?

WCF service returns incorrect Content-Length when using gzip encoding

I have a web page containing a filtering text box and a list box. Modifications to the text box trigger an AJAX request, which returns an array of values with which to populate the list box.
I had problems with these calls failing sometimes, dependent on the size of the data returned. Small-sized returned data would result in an error, large-size data was returned and processed succesfully.
This problem only happens when I use a jQuery version greater than 4.2. If I use jQuery version 4.2, I don't have the problem.
Here is the code of the call:
jQuery.ajax(
{
cache: false,
url: "../Services/CmsWebService.svc/GetAvailableVideosForCompany",
type: "GET",
complete: function (jqXHR, textStatus) {
var responseText = jqXHR.responseText;
jQuery('#debugConsole').text(responseText);
availableVideosPopulationState.isRunning = false;
setTimeout(populateAvailableVideosListBox, 100);
},
data: { "companyIdString": queryParameters.companyIdField,
"textFilter": queryParameters.filterText
},
dataType: 'json',
error: function (jqXHR, textStatus, errorThrown) {
var errorString = 'Error thrown from ajax call: ' + textStatus + 'Error: ' + errorThrown;
alert(errorString);
},
success: function (data, textStatus, jqXHR) {
populateVideoListFromAjaxResults(data);
}
}
);
Here is the contents of the debug console if two elements are returned:
{"d":[{"__type":"ListEntry:#WebsitePresentationLayer","Text":"SOJACKACT0310DSN1.mpg - [SOJACKACT0310DSN1]","Value":"5565_5565"},{"__type":"ListEntry:#WebsitePresentationLayer","Text":"SOJACKACT0310DSN1Q.mpg - [SOJACKACT0310DSN1Q]","Value":"5566_5566"}]}
But if one element is returned:
{"d":[{"__type":"
So, of course, we get an "Unterminated String Constant" error.
I have done some investigation using fiddler.
On all responses (even the succesful ones), fiddler displayed an error:
Fiddler has detected a protocol violation in session #n1.
Content-Length mismatch: Response Header indicated n2 bytes, but
server sent n3 bytes.
If the response header indicates a size greater than than actual size, then the results could still be interpreted by the browser.
If the response header indicates a size less than the actual size, then the browser could not interpret the results.
The obvious assumption to make there is that the response handling code reads the Content-Length header and doesn't read any more data than that stipulated in the length.
The next step in my investigation is to compare the request/response headers for jQuery version 1.6.1 (which breaks) and version 1.4.2 (which does not break).
jQuery 1.6.1 request header:
GET /Web/Services/CmsWebService.svc/GetAvailableVideosForCompany?companyIdString=2&textFilter=3DSBDL2&_=1315869366142 HTTP/1.1
X-Requested-With: XMLHttpRequest
Accept: application/json, text/javascript, */*; q=0.01
Referer: http://localhost:52200/Web/Admin/PlayerGroupEditor.aspx?groupid=76
Accept-Language: en-au
Accept-Encoding: gzip, deflate
User-Agent: Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0)
Host: localhost:52200
Connection: Keep-Alive
Cookie: .ASPXAUTH=CE853BBD860F40F0026400610074006D006500640069006100310000002B5387799D71CC01002B5B5D62C771CC0100002F0000006B119589A7305098A560E57515498C56ECB332035F300427CDA2B28205D5E6B6
jQuery 1.6.1 response headers
HTTP/1.1 200 OK
Server: ASP.NET Development Server/10.0.0.0
Date: Mon, 12 Sep 2011 23:02:36 GMT
X-AspNet-Version: 4.0.30319
Content-Encoding: gzip
Content-Length: 140
Cache-Control: private
Content-Type: application/json; charset=utf-8
Connection: Close
And here is the request header when I use jQuery 1.4.1. Notice that the Accept header is different from the jQuery 1.6.1 value.
GET /Web/Services/CmsWebService.svc/GetAvailableVideosForCompany?_=1315870305531&companyIdString=2&textFilter=3DSBDL2 HTTP/1.1
Referer: http://localhost:52200/Web/Admin/PlayerGroupEditor.aspx?groupid=76
Content-Type: application/x-www-form-urlencoded
X-Requested-With: XMLHttpRequest
Accept: application/json, text/javascript, */*
Accept-Language: en-au
Accept-Encoding: gzip, deflate
User-Agent: Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0)
Host: localhost:52200
Connection: Keep-Alive
Cookie: .ASPXAUTH=CE853BBD860F40F0026400610074006D006500640069006100310000002B5387799D71CC01002B5B5D62C771CC0100002F0000006B119589A7305098A560E57515498C56ECB332035F300427CDA2B28205D5E6B6
And the response back to jQuery 4.1.1:
HTTP/1.1 200 OK
Server: ASP.NET Development Server/10.0.0.0
Date: Mon, 12 Sep 2011 23:31:46 GMT
X-AspNet-Version: 4.0.30319
Content-Length: 131
Cache-Control: private
Content-Type: application/json; charset=utf-8
Connection: Close
So the obvious difference is that when the call is made via jQuery 1.6.1 the response is compressed using gzip, and when the call is made via jQuery 1.4.2 the response is not compressed.
So now I can do a work around solution, which is to override the default Accept header to ensure it does not contain the "q=0.01" string. (The best explanation I can find for "q=0.01" is here, but I fail to see why my service implementation is interpreting this as a request to zip up the response badly.)
// Make the AJAX call, passing in the company id and the filter string
jQuery.ajax(
{
accepts: 'application/json, text/javascript, */*',
cache: false,
url: "../Services/CmsWebService.svc/GetAvailableVideosForCompany",
type: "GET",
complete: function (jqXHR, textStatus) {
var responseText = jqXHR.responseText;
jQuery('#debugConsole').text(responseText);
availableVideosPopulationState.isRunning = false;
setTimeout(populateAvailableVideosListBox, 100);
},
data: { "companyIdString": queryParameters.companyIdField,
"textFilter": queryParameters.filterText
},
dataType: 'json',
error: function (jqXHR, textStatus, errorThrown) {
var errorString = 'Error thrown from ajax call: ' + textStatus + 'Error: ' + errorThrown;
alert(errorString);
},
success: function (data, textStatus, jqXHR) {
populateVideoListFromAjaxResults(data);
}
}
);
So after all this investigation, the remaining question is why is there a disparity between the content length header and the actual content length when the response is GZIP compressed?
I'm using a WCF service with webHttpBinding.
First of all-Very good question. This question provided me with enough information to reach a solution for my problem.
I had a similar issue, and posting the fix here- so that it might help someone.
Ajax get & post requests were returning null in IE
Was working fine in rest of the browsers, but saw the 'Response Header indicated n bytes, but server sent nn bytes' message in fiddler for the request.
The obvious assumption to make there is that the response handling
code reads the Content-Length header and doesn't read any more data
I think so too!
In this case, I was clear with one thing. Something was tampering the request/response.
I tried switching back to older version of jQuery (as mentioned in your question), but that didn't help.
Fix-
I opened up the web config of my application, and read through it.
There was a 'RadCompression Module' from telerik included in modules, and on removal of it everything started working fine.
RadCompression module is known to be buggy and cause multiple issues by compressing the Response.
If you are having similar issues, try checking what might be intercepting your request/response.
Response Header indicated 140 bytes, but server sent 254 bytes says much. Does the same happen independently of the browser you use? If so, we may say that IE or jQuery 1.4.3 and further in IE does not read bytes after reading as many bytes as specified in Response Header, while other browsers read all the content anyway.
It is also possible (yet I hardly believe this) that response header is wrongly formed only for IE requests. Then you must look at the differences between IE and other browser requests and your service code. Maybe your services handles IE requests specifically?
It would be interesting to calculate how much bytes there is after the last captured quotation mark (") in your JSON string. 114 maybe?

jQuery.ajax call to Twitter succeeds but returns null for Firefox

I've got code that makes a simple get request to Twitter (search) using jQuery's Ajax method. The code works fine on Safari, but fails on Firefox (3.6.3). In the Firefox case, my jQuery.ajax parameters 'success' method is invoked, but the supplied data is null. (In Safari, I receive a lot of JSON data.)
My Ajax call is:
$.ajax({
url: 'http://search.twitter.com/search.json?q='+searchTerm,
dataType: 'json',
async: true,
beforeSend: function(request) {
window.console.log('starting AJAX request to get Twitter data');
},
success: function(data, textStatus, request) {
window.console.log('AJAX request to get Twitter succeeded: status=' + textStatus);
callback(data);
},
error: function(request, status, error) {
window.console.log('Ajax request to get user data --> Error: ' + status);
errback(request, status, error);
}
});
Firebug shows Response headers:
Date Sun, 11 Apr 2010 22:30:26 GMT
Server hi
Status 200 OK
X-Served-From b021
X-Runtime 0.23841
Content-Type application/json; charset=utf-8
X-Served-By sjc1o024.prod.twitter.com
X-Timeline-Cache-Hit Miss
Cache-Control max-age=15, must-revalidate, max-age=300
Expires Sun, 11 Apr 2010 22:35:26 GMT
Vary Accept-Encoding
X-Varnish 1827846877
Age 0
Via 1.1 varnish
X-Cache-Svr sjc1o024.prod.twitter.com
X-Cache MISS
Content-Encoding gzip
Content-Length 2126
Connection close
The HTTP status is OK (200), the Content-Type is properly application/json, and the Content-Length of 2126 (gzip'd) implies data came back. Yet, Firebug shows the Response to be empty, and a test of the supplied data shows it to be 'null.'
I am aware of a similar post on Stack Overflow, jQuery $.get() function succeeds with 200 but returns no content in Firefox and from that would assume this problem is possibly related to cross-domain security, but... I know there are many JavaScript widgets and whatnot that Ajax get data from Twitter. Is there something I need to enable to allow this?
You are attempting to make a cross domain Ajax call. For this to happen you need to use JSONP.
JQuery understands JSONP and it will handle all the underlying tricks for you.
You only need to add the parameter &callback=? to your URL and JQuery will make the request as a Cross domain call. More important is, it will understand and handle the JSONP response from the server, so for you it will be transparent.

Resources