How do I handle JSONP with WebAPI? [duplicate] - jsonp

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
JSONP with MVC 4 WebApi
I have a get method for my WebAPI which is as follows:
private T Get<T>(string uri)
{
T result = default(T);
bool isSuccess = true;
client
.GetAsync(uri)
.ContinueWith(task =>
{
// EnsureStatus
isSuccess = task.Result.IsSuccessStatusCode;
task
.Result
.Content
.ReadAsAsync<T>()
.ContinueWith(t => result = t.Result)
.Wait();
})
.Wait();
return result;
}
The result is produced in a JSON format but I want it for JSONP.
I have read that ReadAsSync only handles built in mediaformatters. So is there a way I can change it to handle JsonP?

Stealing liberally from this duplicate....
To accomplish what you want you need three things :
to add a media formatter that outputs JSONP
register the media formatter (traditionally done through global.asx)
ensure the client requests jsonP.
You can steal this JSONP media formatter.
Then, you need to register the media formatter. You can do this programatically with the following code snippet:
var config = GlobalConfiguration.Configuration;
config.Formatters.Insert(0, new JsonpMediaTypeFormatter());
Since you apparently don't use global.asax you're going to need to make sure the formatter is registered somehow. YOU don't provide enough information on how to do it, but i suspect a judiciously placed IF statement and a static variable indicating registration would get you there.
I still don't quite know what type of client you're using, but if it's jquery something like the following will get you there:
$.ajax({
url: 'http://myurl.com',
type: 'GET',
dataType: 'jsonp',
success: function (data) {
alert(data.MyProperty);
}
})
The important part is the accept header sent matches the accept header your shiny new jsonp formatter is listening for. The top two choices in my opinion are either: application/javascript or text/javascript.

Related

ASP.Net MVC Api won't accept an int parameter

I have the following code:
[HttpPost]
public async Task<ReturnStatus> Delete([FromBody]int id)
{
await new BusinessLogic.Templates().DeleteTemplate(id);
return ReturnStatus.ReturnStatusSuccess();
}
When I run this as an AJAX request, the id is null. I've inspected the data coming in through Fiddler and the body is:
{"id":"11"}
The header has Content-Type: application/json; charset=UTF-8.
If I modify the code slightly to
[HttpPost]
public async Task<ReturnStatus> Delete([FromBody]string id)
{
await new BusinessLogic.Templates().DeleteTemplate(Convert.ToInt64(id));
return ReturnStatus.ReturnStatusSuccess();
}
it works just fine.
What am I doing wrong here?
Please read this part, number 3 in particular:
http://encosia.com/using-jquery-to-post-frombody-parameters-to-web-api/
3. [FromBody] parameters must be encoded as =value
(quoting the section for future reference:)
There are two ways to make jQuery satisfy Web API’s encoding requirement. First, you can hard code the = in front of your value, like this:
$.post('api/values', "=" + value);
Personally, I’m not a fan of that approach. Aside from just plain looking kludgy, playing fast and loose with JavaScript’s type coercsion is a good way to find yourself debugging a “wat” situation.
Instead, you can take advantage of how jQuery encodes object parameters to $.ajax, by using this syntax:
$.post('api/values', { '': value });

Getting results from api

I am trying to do a domain availability search using an API from free domain API.
After i create an account, it shows:
**Make a REST request using this URL:**
http://freedomainapi.com/?key=11223344&domain=freedomainapi.com
And looking in the documentation page, it has only:
Request http://freedomainapi.com?key=YOUR_API_KEY&domain=DOMAIN_NAME
Result:
{
"status": "success",
"domain": "freedomainapi.com",
"available": false
}
I am very new to APIs...
What I need is to show a domain search box, and when the user enters, it should return with result.
It claims to show domain suggestions as well. I hope it will also work.
Using jquery and a jsonp proxy
http://jsfiddle.net/mp8pukbm/1/
$.ajax({
type: 'GET',
url: "https://jsonp.nodejitsu.com/?callback=?",
data: {url: 'http://freedomainapi.com?key=14ejhzc5h9&domain=freedomainapi.com'},
dataType: "jsonp",
success: myfn
});
function myfn(data) {
console.log(data);
}
you have to use the proxy because cross domain json is not permitted
EDIT:
i made an update to show the result in a div (stringified)
http://jsfiddle.net/mp8pukbm/2/
EDIT #2: i created a test key on that site, you have to use your own
EDIT #3: and there's your combo: http://jsfiddle.net/mp8pukbm/4/
Assuming that you will use java script for showing the search box, you can use AJAX feature of java script (or jQuery or Dojo) ... All you need to do is a "GET" request that like you can pasted and you will get the result back on the response object. To try out the API you can use "Postman" application in Chrome. https://chrome.google.com/webstore/detail/postman-rest-client/fdmmgilgnpjigdojojpjoooidkmcomcm?hl=en
In the response object of the AJAX call you will get a JSON object which you can parse and display the result.
Normally when we use REST we need to differentiate one REST call from another.
Assuming this url
http://freedomainapi.com/checkAvailability?key=YOUR_API_KEY&domain=DOMAIN_NAME
In Application layer we need to write an interface
#GET
#Path("/checkAvailability")
#Produces({MediaType.APPLICATION_JSON})
public ReturnObject getDomainAvailability(#QueryParam("key") String key,
#QueryParam("domain") String doaminName );
Once interface is done you need to write your implementation class.
This class will intract with business layer and perform search task and based on
result collected will create ReturnObject.
ReturnObject => will contain status, domain and availability
On screen
$.ajax({
type: "GET",
url: 'root/checkAvailability',
success: function(jsonData)
{
// read json and perform operation
}
,
error: function (error)
{
// handle error
}
});
If you are using JAVA as backend then you can use gson to parse the result, which is a json. After parsing you can read the values from result and display accordingly :)
Any API is a way to extend a given software. (Might be a website or an application)
In both ways there is a certain way to communicate with the software. In your example freedomainapi.com allows you to fetch if given domain is avaiable. There is no such thing as a suggestion tho, atleast i cannot find any suggestions at all.
Given output is a message format know as JSON. It can be easily interpreted by many major Languages such as Java, Javascript and PHP.
Given String might be easily interpreted as a Map consisting of a status (String), a domain (string) and avaiable (boolean)
A domain availability search could not be easier, assuming K is your key, D is your search input (Domain):
Download http://freedomainapi.com/checkAvailability?key=K&domain=D as input
Parse JSON from input as json
return json["status"] == "success" and json["avaiable"]
Depending on your language you might need to use methods to access properties of json, but that does not influence the basic usage of this api.
on user enters, it calls click_button function and I am assuming your result displaying div id is "main_container" you can give domain suggestions by passing related DOMAIN_NAME s as arguments to click_button function
function click_button(DOMAIN_NAME){
$.ajax({
url : 'http://freedomainapi.com?key=YOUR_API_KEY&domain=DOMAIN_NAME',
type: 'GET',
crossDomain: true,
contentType: "application/json; charset=utf-8",
success: function(data) {
data=JSON.parse(data);
if(data['available']){
$('#main_container').html($('#main_container').html()+'<br>'+DOMAIN_NAME+': Available');
else{
$('#main_container').html($('#main_container').html($('#main_container').html()+'<br>'+DOMAIN_NAME+': Not Available');
}//success
});//ajax
}
hope it helpful !

Display result from server in IBM Worklight

I have implemented HTTP adapter in IBM Worklight. I want to display the result returned from server. I want to display HTML file. My code is
function getFeeds() {
var input = {
method : 'get',
returnedContentType : 'text',
path : "marketing/partners.html"
};
WL.Logger.debug("sdfsds");
return WL.Server.invokeHttp(input);
}
I want to receive(display) WL.Server.invokeHttp(input). After receiving it I want to parse the data.
Take a look at the Server-side Development Getting Started Modules. Inside the HTTP adapter – Communicating with HTTP back-end systems Module on Slide 15 - 'XSL Transformation Filtering' will show you how to filter data you get back from the backend. Further parsing and showing data has to be done on the client using onSuccess callback for WL.Client.invokeProcedure. There's a module for that too.
Here's an example of getting data and showing to a user:
var invocationData = {
adapter : 'adapter-name',
procedure : 'procedure-name',
parameters : []
};
var options = {};
options.onSuccess = function (response) {
//response is a JavaScript object
$("#id").html(response.invocationResponse.text);
}
options.onFailure = function (response) {
alert('Failed!'); //You probably want something more meaningful here.
}
WL.Client invokeProcedure(invocationData, options);
There are JavaScript libraries you can add to make searching for values inside the JSON response easier, such as: jspath and jquery-jspath. There's also XPath if you're working with XML.
If you retrieve it as plain text, once you got it back to your application, do something like
$("#container-id").html(response.invocationResponse.text);
This will inject the HTML you've retrieved to an element with id container-id.

Differences between $.ajax type put and model.save in backbone.js?

There seems to be some differences between saving a model using this.model.save() and using jquery ajax type PUT?
I have the following method in my api controller
public void Put(string id, [FromBody]IContent value) {
// save
}
I have also enabled TypeNameHandling on JSON formatter serializer setting like this:
config.Formatters.JsonFormatter.SerializerSettings.TypeNameHandling = TypeNameHandling.Auto;
If I PUT some data using jquery ajax like this
$.ajax({
url: "/api/page/articles/1",
type: "PUT",
dataType: "json",
contentType: "application/json",
data: JSON.stringify({"$type": "BrickPile.Samples.Models.Article,BrickPile.Samples","id": "articles/1", "heading": "Some heading..." })
});
my object binds correct in the put method but when I try to save my object using model.save() in backbone the input value is null and it cannot bind the object?
This is how I do it:
this.model.set({ heading: 'foo' });
this.model.save();
the request headers seem to look ok and the payload is seems to be JSON, at least if I look in firebug. It's also possible to PUT some data to my api using fiddler with the same payload but not if I copy the payload source from firebug see: http://cl.ly/Nked
Can anyone explain what I'm doing wrong here?
Without knowing more about your model implementation it is hard to say for sure. One thing I can see from your firebug screenshot is that the id attribute is being passed as "articles/1" which is unusual for standard Backbone. If you were saving a model object then the id would normally be "1". So a model.save() would generate a HTTP PUT to articles/1 and pass the json as something including {"id":"1", ... }. The Backbone.sync documentation has more details on the default behaviour.

Dojo datagrid jsonrest response headers

I'd like to use custom headers to provide some more information about the response data. Is it possible to get the headers in a response from a dojo datagrid hooked up to a jsonRest object via an object store (dojo 1.7)? I see this is possible when you are making the XHR request, but in this case it is being made by the grid.
The API provides an event for a response error which returns the response object:
on(this.grid, 'FetchError', function (response, req) {
var header = response.xhr.getAllResponseHeaders();
});
using this I am successfully able to access my custom response headers. However, there doesn't appear to be a way to get the response object when the request is successful. I have been using the undocumented private event _onFetchComplete with aspect after, however, this does not allow access to the response object, just the response values
aspect.after(this.grid, '_onFetchComplete', function (response, request)
{
///unable to get headers, response is the returned values
}, true);
Edit:
I managed to get something working, but I suspect it is very over engineered and someone with a better understanding could come up with a simpler solution. I ended up adding aspect around to allow me to get hold of the deferred object in the rest store which is returned to the object store. Here I added a new function to the deffered to return the headers. I then hooked in to the onFetch of the object store using dojo hitch (because I needed the results in the current scope). It seems messy to me
aspect.around(restStore, "query", function (original) {
return function (method, args) {
var def = original.call(this, method, args);
def.headers = deferred1.then(function () {
var hd = def.ioArgs.xhr.getResponseHeader("myHeader");
return hd;
});
return def;
};
});
aspect.after(objectStore, 'onFetch', lang.hitch(this, function (response) {
response.headers.then(lang.hitch(this, function (evt) {
var headerResult = evt;
}));
}), true);
Is there a better way?
I solved this today after reading this post, thought I'd feed back.
dojo/store/JsonRest solves it also but my code ended up slightly different.
var MyStore = declare(JsonRest, {
query: function () {
var results = this.inherited(arguments);
console.log('Results: ', results);
results.response.then(function (res) {
var myheader = res.xhr.getResponseHeader('My-Header');
doSomethingWith(myheader);
});
return results;
}
});
So you override the normal query() function, let it execute and return its promise, and attach your own listener to its 'response' member resolving, in which you can access the xhr object that has the headers. This ought to let you interpret the JsonRest result while fitting nicely into the chain of the query() all invokers.
One word of warning, this code is modified for posting here, and actually inherited from another intermediary class that also overrode query(), but the basics here are pretty sound.
If what you want is to get info from the server, also a custom key-value in the cookie can be a solution, that was my case, first I was looking for a custom response header but I couldn't make it work so I did the cookie way getting the info after the grid data is fetched:
dojo.connect(grid, "_onFetchComplete", function (){
doSomethingWith(dojo.cookie("My-Key"));
});
This is useful for example to present a SUM(field) for all rows in a paginated datagrid, and not only those included in the current page. In the server you can fetch the COUNT and the SUM, the COUNT will be sent in the Content-Range header and the SUM can be sent in the cookie.