RestKit different mime type for one response - restkit

I would like to support different mime types for different responses. Most of the time the server returns json, but there are a few situations where it returns nothing and RestKit identifies these cases as plain/text mime types. Is there any solution?

I haven't tried this exactly, but it works for me when using purely AFNetworking calls. Try setting the underlying AFNetworking HTTPClient:
AFHTTPClient *client = [RKObjectManager sharedManager].HTTPClient;
[client setDefaultHeader:#"Accept" value:#"plain/text"]; // change default "Accept" header
// Put normal RestKit request code here
[client setDefaultHeader:#"Accept" value:#"application/json"]; // change back
This should work, unless RestKit is overriding the default headers somewhere. (If your request is a GET, and you don't even need RestKit's Object Mapping functionality, I suggest using the AFNetworking methods with the default client and skipping the RestKit methods in that case.)

Related

Disable cache in ExtLib REST control (which uses dojox.data.JsonRestStore)

In my XPage I have a xe:djxDataGrid (dojox.grid.datagrid) which uses xe:restService which seems to use dojox.data.JsonRestStore.
Everything works fine without proxy but my client accesses the application via a proxy because of corporate policy. After a user updates data in the DataGrid it shows old values when accessed behind the proxy.
When the REST Control/JsonRestStore sends an ajax GET request to get data, there is no Cache-Control parameter in request headers. And Domino does not place Expires parameter in the reponse headers. I believe that's why the old version of the GET request gets cached by the proxy.
We have tried to disable cache in browsers but that does not help which indicates the proxy is caching the requests.
I believe this could be solved either by:
Setting Cache-Control parameter in request headers OR
Setting Expires parameter in response headers
But I haven't found a way to set either of these. For the XPage Domino sets Expires:-1 response header but not for the ajax GET request which is:
/mypage.xsp/?$$viewid=!ddrg6o7q1z!&$$axtarget=view:_id1:_id2:callback1:restService1
This returns the JSON data to JsonRestStore and gets cached by the proxy.
One options is to try to get an exception to the proxy so requests to this site would bypass the proxy cache. But exceptions are generally not easy to get thru.
Any ideas? Thanks.
Update1
My colleque suggested that I could intercept the xhr GET requests made by dojox.data.JsonRestStore and add a time parameter to the URL to prevent cache. Here is my question about that:
Prevent cache in every Dojo xhr request on page
Update2
#SvenHasselbach has a great solution for preventing cache for all xhrs:
http://openntf.org/XSnippets.nsf/snippet.xsp?id=cache-prevention-for-dojo-xhr-requests
It seems to work perfectly, &dojo.preventCache= parameter is added to the URLs and the requests seem to return correct JSON also with this parameter. But the DataGrid stops working when I use that code. Every xhr causes this error:
Tried with Firefox and Chrome. The first page of data still loads because xhr interception is not yet in place but the subsequent pages show only "..." in each cell.
The solution is Sven Hasselbach's code in the comment section of Julian Buss's blog which needs to be slightly modified.
I changed xhrPost to xhrGet and did not place the code to dojo.addOnLoad. When placed there it was not effective in the first XHR by the DataGrid/Store.
I also removed the headers modification because it overrides existing headers. When the REST control requests data from server with xhrGet the URL is always the same and rows requested are in HTTP header like this:
Range: items=0-9
This (and other) headers disappear when the original code is used. To just add headers we would have take the existing headers from args and append to them. I didn't see a need for that because it should be enough to add the parameter in the URL. Here is the extremely simple code I'm using:
if( !(dojo._xhrGet )) {
dojo._xhrGet = dojo.xhrGet;
}
dojo.xhrGet = function (args) {
args['preventCache'] = true;
return dojo._xhrGet(args);
}
Now I'm getting all rows and all XHR Get URLs have &dojo.preventCache= parameter which is exactly what I wanted. Next we'll test in customer environment to see if this solves their problem.
Update
As Julian points out in his blog I could also use a Web Site Rule to set Expires or cache-control http response headers.
Update
The customer reports it's working now for them!

valums file-uploader IE and #Responsebody. IE Launches download dialog.

I am using valums file-uploader to upload files. This works great if my Spring controller returns void. If I add a #Responsebody Object to my controller IE things that I am about to download instead of uploading a file and launches a dialog.
The reason I would like to have a #Responsebody Object and not void is for error handling. How can I trick IE in this case?
I'm assuming that Spring is automagically setting the content-type to application/json for you, which will not work in IE. Ensure the content-type of your response is text/plain. Some will say that text/html is correct, and that is true for most cases. However, text/html will cause you problems if your JSON response contains HTML as IE will mess with the response. So, your safest bet is to ensure the content-type of your response is text/plain.
While we are on the topic of IE quirkiness, also be sure that you only return a 200 response if you intend to also include JSON in your response. IE will, by default, replace the content of "small" non-200 responses with a "friendly" message. "Small", I believe, is defined as a response that is less than 512 (or possibly 256) bytes.
For a list of all things you should be aware of when using IE, have a peek at the "limitations of IE" section in the Fine Uploader readme.

How to set the default serializer in ASP.NET Web API?

I'm currently watching a video course about ASP.NET Web API. When a controller gets called, the data gets returned in JSON by default. I was just wondering, because when I copy this sample project from the video, I get XML.
The frustration is big, please help me to solve this.
I'm pretty new to ASP.NET Web API, so please bear with me.
UPDATE
The controller doesn't contain special code. It's the simple code, which gets generated from the API Controller with empty read/write actions template.
ASP.NET WebAPI comes with built-in content negotitation therefore the format of the return value is determined by the request itself - more specifically by the Accept/Content-Type headers (depending on which ones are present, Accept header appears to be favoured over the Content-type).
I assume you're viewing the results in a browser and by default it's probably asking for application/xml. You will need to toy around with some settings/developer tools on the browser and force it to send Content-Type: application/json to get the correct response (assuming your returning HttpResponseMessage).
in Global.asax: add the line:
GlobalConfiguration.Configuration.Formatters.XmlFormatter.SupportedMediaTypes.Clear();
It'll look like this.
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
RegisterGlobalFilters(GlobalFilters.Filters);
RegisterRoutes(RouteTable.Routes);
BundleTable.Bundles.RegisterTemplateBundles();
GlobalConfiguration.Configuration.Formatters.XmlFormatter.SupportedMediaTypes.Clear();
}
James is close, but the content negotiation actually uses the [Accept] header,
not [Content-Type]
As with nearly everything else in MVC, you can override the content negotiation components to ensure the desire content is returned
W3c clearly states-
14.1 Accept
The Accept request-header field can be used to specify certain media types which are acceptable for the response.
-and-
14.17 Content-Type
The Content-Type entity-header field indicates the media type of the entity-body sent to the recipient or, in the case of the HEAD method, the media type that would have been sent had the request been a GET.
This page headers is very useful to understand request/response negotiation.

Retrieving JSON from an external API with backbone

I'm new to backbone.js and I've read other solutions to similar problems but still can't get my example to work. I have a basic rails api that is returning some JSON from the url below and I am trying to access in through a backbone.js front end. Since they are one different servers I think I need to use a 'jsonp' request. I'm currently doing this by overriding the sync function in my backbone collection.
Api url:
http://guarded-wave-4073.herokuapp.com/api/v1/plans.json
sync: function(method, model, options) {
options.timeout = 10000;
options.dataType = 'jsonp';
options.url = 'http://guarded-wave-4073.herokuapp.com/api/v1/plans.json'
return Backbone.sync(method, model, options);
}
To test this I create a new 'plans' collection in my chrome console using "plans = new Plans()" and then "plans.fetch()" to try and get the JSON.
When I call plans.models afterwards I still have an empty array and the object that returns from plans.fetch() doesn't seem to have any json data included.
Any ideas where I'm going wrong?
I have had the same problem before. You should not have to override your sync method.
Taken from Stackoverflow Answer
"The JSONP technique uses a completely different mechanism for issuing HTTP requests to a server and acting on the response. It requires cooperating code in the client page and on the server. The server must have a URL that responds to HTTP "GET" requests with a block of JSON wrapped in a function call. Thus, you can't just do JSONP transactions to any old server; it must be a server that explicitly provides the functionality."
Are you sure your server abides to the above? Test with another compatible jsonp service (Twitter) to see if you receive results?
Have you tried overriding the fetch method as well?
You should add ?callback=? to your api url in order to enable jsonp

Should I be using POST or GET when retrieving JSON data into jqGrid in my ASP.NET MVC application?

I am using jqgrid in my ASP.NET MVC application. Currently I have mTYpe: 'POST' like this:
jQuery("#myGrid").jqGrid({
mtype: 'POST',
toppager: true,
footerrow: haveFooter,
userDataOnFooter: haveFooter,
But I was reading this article, and I see this paragraph:
Browsers can cache images, JavaScript, CSS files on a user's hard
drive, and it can also cache XML HTTP calls if the call is a HTTP GET.
The cache is based on the URL. If it's the same URL, and it's cached
on the computer, then the response is loaded from the cache, not from
the server when it is requested again. Basically, the browser can
cache any HTTP GET call and return cached data based on the URL. If
you make an XML HTTP call as HTTP GET and the server returns some
special header which informs the browser to cache the response, on
future calls, the response will be immediately returned from the cache
and thus saves the delay of network roundtrip and download time.
Given this is the case, should I switch my jqGrid mType all to use "GET" from "POST" for the mType? (It says XML (doesn't mention JSON). If the answer is yes, then actually what would be a situation why I would ever want to use POST for jqGrid mType as it seems to do the same thing without this caching benefit?
The problem which you describe could be in Internet Explorer, but it will be not exist in jqGrid if you use default options.
If you look at the full URL which will be used you will see parameters like
nd=1339350870256
It has the same meaning as cache: true of jQuery.ajax. jqGrid add the current timestemp to the URL to make it unique.
I personally like to use HTTP GET in jqGrid, but I don't like the usage of nd parameter. The reason I described in the old answer. It would be better to use prmNames: {nd:null} option of jqGrid which remove the usage of nd parameter in the URL. Instead of that one can control the caching on the server side. For example the setting of
Cache-Control: private, max-age=0
is my standard setting. To set the HTTP header you need just include the following line in the code of ASP.NET MVC action
HttpContext.Current.Response.Cache.SetMaxAge (new TimeSpan (0));
You can find more details in the answer.
It's important to understand, that the header Cache-Control: private, max-age=0 don't prevent the caching of data, but the data will be never used without re-validation on the server. Using other HTTP header option ETag you can make the revalidate really working. The main idea, that the value of ETag will be always changed on changing the data on the server. In the case if the previous data are already in the web browser cache the web browser automatically send If-None-Match part in the HTTP request with the value of ETag from the cached data. So if the server see that the data are not changed it can answer with HTTP response having 304 Not Modified status and empty body of the HTTP response. It allows the web browser to use local previously cached data.
In the answer and in this one you will find the code example how to use ETag approach.
If the data that the server sends changes, then you should use POST to avoid getting cached data everytime you request it.
You should not use GET for all the purposes. GET requests are supposed to use for getting data from the server not for saving or deleting operation. GET requests has some limitation since the data you are sending to the server or appended as query-strings you can't send very large data using GET requests. Also you should not use GET request to send sensitive information to the server. You should the POST request in all the other cases like adding, editing and deleting.
As far as I'm aware jqgrid appends a unique key in every GET request so you don't get any benefit from browser caching.
One way around the caching behavior is to make the GET unique each time the request is made. jQuery.ajax() does this with "cache: false" by appending a timestamp to the end of the request. You can replicate this behavior with something similar:
uri = uri + '?_=' + (new Date()).getTime(); // uri represents the URI to the endpoint

Resources