jQuery POST does not send JSON data - wcf

I'm trying to do a POST to a service running on localhost with jQuery AJAX, but it keeps returning status code 0 even after I've set jQuery.support.cors = true. I can also navigate to my WCF REST service successfully from my browser. This is what my JavaScript looks like:
<script>
jQuery.support.cors = true;
$(document).ready(function(){
$.ajax({
type: "POST",
url: "http://localhost:8000/Test",
data: '{"test":"test"}',
contentType: "application/json",
dataType: "json",
success: function (msg) {
alert('success');
},
error:function(x,e){
if(x.status==0){
alert('error 0');
}
}
});
});
</script>
Does anyone know what could be causing this? I should also mention that I can't POST to anything on localhost using jQuery.
According to Fiddler, the JSON data is not sent, and a HTTP OPTIONS is done instead of a POST.

try this
var dataObj = {test:"test"};
var json = JSON.stringify(dataObj);
then in your ajax call
data: json,

I didn't want to spend anymore time on this issue, so I resorted to using raw HTML form POST as the usage of JSON wasn't essential in my case.
For anyone else having the same issues outlined in the original post, see this thread for an explanation and a solution: Problem sending JSON data from JQuery to WCF REST method
To summarize, your service needs to be able to handle the HTTP OPTIONS method if it is expected to respond to cross domain calls.

You should use a tool like network monitor etc. to see if the browser is asking the server for the allowed headers (using the OPTIONS header request), you may need to supply the correct headers in an OPTIONS response before the actual request is sent to the server (see the article at the bottom).
Also, you could try adding this to the actual call or the ajaxSetup, as you will need to tell the browser to send credentials and allow the cross domain call (I know someone else already mentioned 'crossDomain'):
$.ajaxSetup({
crossDomain: true,
xhrFields: {
withCredentials: true
}
});
Have a read of this if you get time too.. https://developer.mozilla.org/en/http_access_control

So, when the request is cross domain, jQuery will send your post request as a get request anyways.
Are you accessing "localhost" in the URL but then your application is sending the requests to the local IP of your machine instead of localhost? Because that's technically cross-domain, which means that you won't receive the request in the expected manner.
E.g. (just tested this locally)
Visiting my local site at:
http://localhost/test/
A form on the site submits to my local ip address instead of localhost via $.post():
<form action="http://10.0.0.17/test/" method="post">
....[form stuff...]
</form>
This is a cross-domain request
If you're calling $.post() or jquery's ajax() call set to post, it automatically moves your parameters from the post body into the query string.
If you ARE accessing local host, try hitting the site via whatever address your jquery post() method is using as the domain and see if that helps.
See more on cross-domain policies:
http://en.wikipedia.org/wiki/Same_origin_policy

Send the data as an Object literal instead of a string
data: '{"test":"test"}',
to
data: {test:"test"},

Related

How to prevent some methods

I'm developing some APIs with Laravel 5.5
The methods I am using are only 'GET'/'POST'/'PUT'/'PATCH'/'DELETE'.
All works fine except if the request is HEAD or LOCK (for example) ....
In this case, the backend returns a 405 error with an html response. And in this html response there are a lot confidential data.
Is it possible , only for some methods, that the back returns a single text "Method not allowed" and not an html file ? Is it a good practice to do that or not necessary?
I imagine a middleware, but which one?
The reason you're getting debug information with confidential data is likely due to debug being set to true in your config. If you turn this to false, the error message will remove the confidential data.
I found a solution.
File Exceptions/handler.php, method render, I had this:
if ($request->is('api/*') and ! in_array($request->method(), ['get', 'post', 'put', 'delete']) ){
return response()->json("request not allowed", 405);
}
It works fine. Now I receive a JSON response instead of an HTML response for all my API routes, depending on 'get/put/post/delete'.

How to distinguish between GET and POST

I'm writing a simple api for training using express. Here's my testing code:
var express = require('express');
var app = express();
app.post("/api/:var_name", function(req, res) {
res.send(req.params.var_name);
});
is simply testing to see if POST is working. When I call http://localhost:3000/api/1 I get Cannot GET /api/1, so the server is obviously interpreting the POST request as GET, what do I need to do to call POST instead?
Anything you call in the address bar of your browser will be sent via get. This is due to the fact that post-messages (and almost all other methods) do have a body-part. But there is no way for your browser to send additional information inside the body of the http packet.
If you want to test your routes for any method other than GET I would suggest you download a tool like postman.
https://www.getpostman.com/
BEWARE: This is my preference. You can of curse also use text based browsers like curl to test it.
The server interprets the request according to the verb you set in the HTTP request. If no method/verb is specified it is interpreted as GET(not sure about this part).
When you call that URL, you need to use the method as well. For example if you use the fetch API, you can call it like:
fetch(url, {method:"POST"})
If you're entering it in your browser and expect it to be interpreted as a post request, it's not. All browser url requests are GET. Use a tool like Postman to call different HTTP verbs. It's really useful when creating such APIs.
You can check out this answer on details of how to add body and headers to a post request: Fetch: POST json data

Restangular: How to get HTTP response header?

I have a REST server which returns a Link HTTP header with a response to a PUT to indicate the URL of the newly-created entity:
Link:<entities/6>; rel="created"
Is there any possibility to read that link header with Restangular?
The only facility to intercept HTTP requests with Restangular I've met so far is to register a response interceptor in the app config:
restangular.addResponseInterceptor(function (data, operation, what, url, response, deferred) {
console.log(response.headers())
return response.data;
});
However, with above demo implementation in place, the only HTTP header which gets logged is content-type. Still, I can see in the browser development toolbar that a response comes indeed with many additional HTTP response headers, such as Server, Date, and the aforementioned Link.
Why do I not have access to the full array of HTTP response headers through addResponseInterceptor()? Is there any way to capture the HTTP response header in question using Restangular?
Note: I don't search for an answer using HAL or any other special response body format. I would rather like to know whether I can use plain HTTP headers with Restangular or not (if not, I will probably resort to HAL or something).
You don't need a ResponseInterceptor to do this. You just need to set fullResponse to true to get the whole response (including the http headers) every time you do any request.
Restangular.setFullResponse(true);
You can set it globally in your app configuration. Something like this:
angular.module('YourApp')
.config(['RestangularProvider',
function (RestangularProvider) {
RestangularProvider.setFullResponse(true);
...
Then, every time you receive a response, you can access all the response headers.
Restangular.all('users').getList().then(function(response) {
$scope.users = response.data;
console.log(response.headers);
}
Example:
response.headers('Link')
NOTE: Be careful because using fullResponse, the response data is located in response.data, not directly in response.
EDIT: As #STEVER points, you also need to expose the headers in your server API.
Example:
Access-Control-Expose-Headers: Link
You can get more detailed information in Restangular documentation
Hope it helps.

How to post to another domain with ajax

I work on a website (called websiteA) who wants some bespoke data to be stored.
As such, we realised the best way is to have another website (websiteB) which would handle this. So, when a user visits websiteA, it calls websiteB and passes some information across.
The code I used to use (which I recieved form this post How to get json from MVC4 C# with no javascript and no Ajax) is
using (var client = new HttpClient())
{
var responseString = client.GetStringAsync("http://www.example.com/recepticle.aspx?withQueryString=true"); //I don't actually use the responseString
}
The point is though, when I asked that question, a comment was left (now deleted) explaining I should use WebApi instead. So I did... And this is where it is going wrong.
I have created the Web Api 2 project, and I post using Ajax and it works in my local host. I've now deployed to my test environment and realised I can't achieve what I want because of cross domain origin issues.
Further reading suggests I can't use json, but must use jsonp but, jsonp only works with get where as I need post (How to use type: "POST" in jsonp ajax call).
I guess I could use 'get' and just ignore the response but this feels like a hack...
Sorry for asking 2 questions but I think they're very much related.
Question 1 is: if the jsonp requires a callback, is it actually using a get but the get is being called from the target machine (websiteB)? So, instead of posting from websiteA to websiteB, does jsonp actually mean websiteA passes the callback to websiteB, and websiteB actually invokes the callback (meaning essentially, websiteB is calling websiteA)?
Question 2 (the main question) : How do I post information from websiteA to websiteB using javascript/ajax/jquery. Or will I have to enable CORS on websiteB server and then use a ajax's post and json?
Dave Ward has the perfect article on how to do this on his blog:
http://encosia.com/using-cors-to-access-asp-net-services-across-domains/
In short, place the following in your webconfig.
<system.webServer>
<httpProtocol>
<customHeaders>
<add name="Access-Control-Allow-Origin" value="*" />
<add name="Access-Control-Allow-Headers" value="Content-Type" />
</customHeaders>
</httpProtocol>
</system.webServer>
First, I want to introduce these names to make the explanation a little less confusing.
WebsiteA = App = Web-Client application
WebsiteB = API = Data provider
Question 1:
if the jsonp requires a callback, is it actually using a get but the get is being called from the target machine (websiteB)?
So, instead of posting from websiteA to websiteB, does jsonp actually mean websiteA passes the callback to websiteB, and websiteB actually invokes the callback (meaning essentially, websiteB is calling websiteA)?
Answer to question 1:
The API does not invoke any JavaScript closures (callback) from the App. The callback in the JSONP communication technique is the name of the (global) function in the context of the client, specified by the App itself. This callback is invoked by the App, after the payload is received from the remote service. It is by convention alone that the App can specify the name of the padding function. Meaning that the service is kind enough to let you decide which function you want to call after data is received.
The service outputs this function as "plain text" because <script> expects to find valid JavaScript under src=. The response can not contain a valid JSON object alone because <script> is not responsible for assigning variables, but for running actual scripts and if the remote service would respond with var weatherData = { ... }, then weatherData would be accessible in the context of the client. I'm not sure why the padding-function approach is considered as more favorable. Probably because it is easier to parse safely.
App.html
(incorrect syntax for the sake of brevity)
<html>
<head>
<title> Weather App
<script src=weater-station.com/next-week/?callback=parseRemoteWeatherData />
<script>
var app = {
main: function() { /* init views, etc */ },
receiveWeatherData: funciton(maybeJson) {
// validate payload in maybeJson
}
}
// expose the callback
window.parseRemoteWeatherData = app.receiveWeatherData
API response to /next-week/?callback=parseRemoteWeatherData
HTTP/1.1 200 OK
Date: Mon, 01 Dec 2008 00:23:53 GMT
Server: Apache/2.0.61
Access-Control-Allow-Origin: *
Keep-Alive: timeout=2, max=100
Connection: Keep-Alive
Transfer-Encoding: chunked
Content-Type: application/javascript
parseRemoteWeatherData('any-text, but JSON by convention');
So the simple explanations is:
The client specifies a function name and gets a script that calls this function with the data as the first parameter.
Question 2:
How do I post information from websiteA to websiteB using javascript/ajax/jquery. Or will I have to enable CORS on websiteB server and then use a ajax's post and json?
Answer to question 2
As per the CORS (and HTTP 1.1) specification you can issue a POST method to any service, provided that:
Content-Type header contains one of application/x-www-form-urlencoded, multipart/form-data, or text/plain.
The request does not contain any custom headers
If you want to post Content-Type: application/json, then CORS must be enabled on both the server and the client. The server must handle OPTION negotiation call (Preflighted requests) correctly and respond with the header Access-Control-Allow-Origin: * (or the domain name of the client) while the client must send the header Origin: hostname.tld.
Relevant specifications
https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS
https://developer.mozilla.org/en-US/docs/Web/HTTP/Server-Side_Access_Control
https://developer.mozilla.org/en-US/docs/Web/Security/Same-origin_policy
https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest
http://www.w3.org/TR/cors/
https://en.wikipedia.org/wiki/JSONP

Cannot load Google Images from its API using jQuery getJSON

My code is below:
$.getJSON('https://ajax.googleapis.com/ajax/services/search/images?q=Google&v=1.0',
function(json) {
alert(json);
})​
You can try this code here: http://jsbin.com/ofaru3/edit
The ajax is error
imagesFailed to load resource
How cna I fix this problem? Thanks!
You need &callback=? on the URL there to trigger JSONP, like this:
$.getJSON('https://ajax.googleapis.com/ajax/services/search/images?q=Google&v=1.0&callback=?',
function(json) {
alert(json);
});
You can test it out here. Without the &callback? it's trying to fetch the data from a remote domain with an XmlHttpRequest (AJAX) and failing/being blocked due to the same origin policy. This is exactly the type of situation JSONP is for.
From the $.getJSON() docs:
JSONP
If the URL includes the string "callback=?" (or similar, as defined by the server-side API), the request is treated as JSONP instead. See the discussion of the jsonp data type in $.ajax() for more details.