AJAX POST in .NET - javascript

I have the below javascript AJAX request which works:
$.ajax({
type: "POST",
url: requestUrl,
data: {
var1: 'value1',
var2: 'value2',
var3: 'value3'
},
xhrFields: {
withCredentials: true
},
dataType: "json",
crossDomain: true,
complete: function (jqXhr, textStatus) {
if (jqXhr !== undefined && jqXhr !== null && jqXhr.statusText === "OK") {
alert("Request Success" + jqXhr.responseText);
} else {
alert("Request Failed" + (jqXhr.responseText || textStatus));
}
}
});
I would like to do the same using .NET.
I tried the following:
string result = string.Empty;
try
{
using (var client = new WebClient())
{
client.Credentials = new NetworkCredential("userName", "password");
var values = new NameValueCollection();
values["var1"] = "value1";
values["var2"] = "value2";
values["var3"] = "value3";
var response = client.UploadValues(requestUrl, values);
result = Encoding.Default.GetString(response);
}
}
catch (Exception exception)
{
Console.WriteLine("Error=" + exception.Message);
}
Console.WriteLine("result=" + result);
However I get an Internal Server Error.
How do I recreate a cross domain request? Is there a specific header to set?
WebException details:
Response: "The remote server returned an error: (500) Internal Server Error."
Headers:
Persistent-Auth: true
Content-Length: 5143
Cache-Control: private
Content-Type: text/html; charset=utf-8
Date: Tue, 14 Jul 2015 12:03:21 GMT
Server: Microsoft-IIS/7.5
X-AspNet-Version: 4.0.30319
X-Powered-By: ASP.NET

Without seeing the error it's hard to say exactly what's going on but if you suspect this is a CORS issue then you can add these headers:
var data = JsonConvert.SerializeObject(
new
{
Prop1 = 1,
Prop2 = "data 2"
});
using (var client = new WebClient { UseDefaultCredentials = true })
{
client.Headers.Add("access-control-allow-origin", "*");
client.Headers.Add("access-control-allow-methods", "GET, POST, OPTIONS");
client.Headers.Add("access-control-allow-headers", "Authorization, content-type, accept");
client.Headers.Add(HttpRequestHeader.ContentType, "application/json; charset=utf-8");
client.UploadData("your url", "POST", Encoding.UTF8.GetBytes(data));
}

Related

Can't 'save' incomming cookie's from my go server

I made a go server that can do the basics. Now I want to do a request to my server from my node.js frontend (Axios) get a cookie back (for my login system) here is the code for putting the cookie in my response:
var hashKey = []byte("testkey") //for testing purpopes
var blockKey = []byte(securecookie.GenerateRandomKey(32))
var s = securecookie.New(hashKey, blockKey)
if encoded, err := s.Encode("cookie-name", value); err == nil {
cookie := &http.Cookie{
Name: "cookie-name",
Value: encoded,
Path: "/",
Secure: true,
HttpOnly: true,
}
http.SetCookie(*w, cookie) // w = *http.ResponseWriter
...
when I use my REST tool to see what I get I can see that the 'set-cookie' header is present. The same is If I inspect in Microsoft Edge I can see the set-cookie header. But if I inspect in Google Chrome then I can't see the header. Also if I look in the cookies tab in both Chrome and edge the cookie is not set.
this is my function that is ran for the request:
async post( url, data, ct ) {
try {
const res = await axios.post(url, data, {
headers: {
'Content-Type': (ct || "text/plain")
},
withCredentials: true
});
if (res.status === 200) {
return res.data;
}
} catch (e) {
console.error(e);
return false;
}
}
my Response Headers:
server: nginx/1.14.0 (Ubuntu)
date: Thu, 17 Jan 2019 14:29:07 GMT
content-type: text/plain charset=utf-8
content-length: 4
connection: keep-alive
setcookie:cookiename=MTU0NzczNTM0N3xGOTJYUUw5TFNXZHI2dU9jT3hCeTZUTE5TaTBFNU1XN1F 5WGMzb3c1dGZRUENEU2xPZHFwTXJQLW8zND18_VCYxNVRbIAUrs9_8EcGpTUEiqVyYL_2M5Olbjhnkeg =; Path=/
access-control-allow-origin:https://beta.bvwitteveen.nl
access-control-allow-methods:GET, POST, OPTIONS
access-control-allow-credentials:true
access-control-allow-headers:DNT,User-Agent,X-Requested-With,If-
ModifiedSince,Cache-Control,Content-Type,Range,Set-Cookie
access-control-expose-headers:Content-Length,Content-Range
Why is my cookie behaving so weird? What am I doing wrong here?

Using Autodesk's Forge OSS, I can upload to a bucket, but the body of the download is empty

I'm using Autodesk's Forge Object Storage Service and while I can upload my file to my bucket, when I try to download it, the body comes out empty. However, when using Head, the Data-Size is correct.
Here is my upload (note that I'm using the signed url upload API):
var url = uploadOptions.url;
var fileReader = new FileReader();
// UploadOptions.Body contains a Blob
fileReader.readAsBinaryString(uploadOptions.Body);
fileReader.onloadend = function (e) {
var xhr = new XMLHttpRequest();
var lastLoadedValue = 0;
xhr.onreadystatechange = function () {
if (xhr.readyState === 4 && (xhr.status === 200 || xhr.status === 201)) {
console.log('UPLOAD FINISHED:', xhr.responseText);
callback();
}
};
xhr.open("PUT", url, true);
xhr.withCredentials = true;
// uploadOptions.ContentType = 'application/octet-stream'
xhr.setRequestHeader('Content-Type', uploadOptions.ContentType);
xhr.send(e.target.result);
Here is my download:
superagent
.get(_autodesk_api_baseurl
+ baseUrl
+ downloadOptions.bucket
+ '/objects/'
+ encodeURIComponent(downloadOptions.key))
.set('Authorization', 'Bearer '
+ token.access_token)
.query({'response-content-type': 'application/octet-stream'})
.end(function (err, resp) {
if (typeof callback === 'function') {
// All works fine
callback(undefined, resp);
}
});
And then, in the callback, I print my response and the body is empty.
I even wrote the JSON encoded response to a file to get this:
{
"req": {
"method": "GET",
"url": "https://developer.api.autodesk.com/oss/v2/buckets/storage.vcs.prod.mevsg.autodesk.com/objects/assets%2FNT5NR9KJU2PH%2Fea02ec77505f2ea2defac93fe231764f2916e4d1aeaac7d92945a08a0086c60667369431361d5aa426d4cccca49b9e4c7cb70bc6ebf700258a3cb37617eacfa0"
},
"header": {
"access-control-allow-credentials": "true",
"access-control-allow-headers": "Authorization, Accept-Encoding, Range, Content-Type",
"access-control-allow-methods": "GET",
"access-control-allow-origin": "*",
"content-disposition": "attachment; filename=\"ea02ec77505f2ea2defac93fe231764f2916e4d1aeaac7d92945a08a0086c60667369431361d5aa426d4cccca49b9e4c7cb70bc6ebf700258a3cb37617eacfa0\"",
"content-encoding": "gzip",
"content-type": "application/octet-stream",
"date": "Thu, 30 Jun 2016 18:03:10 GMT",
"etag": "\"8ad9c59b256cef48798a94c0295023088016d43a\"",
"server": "Apigee Router",
"vary": "Accept-Encoding",
"transfer-encoding": "chunked",
"connection": "Close"
},
"status": 200
}
As you can see, there is no body. But when I use Head on the object, I get the right number of bytes.
Can someone tell me what I'm doing wrong?
I tried hard-coding Content-Type to application/x-www-form-urlencoded and then I could download the file (there were bytes in the body), but the bytes were changed a little. For example, 208 (11010000) became 80 (1010000). As you can see, the first bit was reversed. With that content-type, I could not open the file. Which way should I use?
UPDATE:
With the help of Augusto, I found the problem.
Superagent doesn't seem to work, but Request does.
Not sure if it had an real impact, but I set the encoding for the downloaded buffer to base64
I needed to upload the Blob directly. I didn't have to use a FileReader to read the bytes.
Here's what solved the problem:
For the upload, I needed to only send the Blob. Here's the updated code:
var url = uploadOptions.url;
var xhr = new XMLHttpRequest();
xhr.onreadystatechange = function () {
if (xhr.readyState === 4 && (xhr.status === 200 || xhr.status === 201)) {
console.log(xhr.status);
console.log('UPLOAD FINISHED:', xhr.responseText);
callback();
}
};
xhr.open("PUT", url, true);
xhr.withCredentials = true;
// Send the Blob directly!!
xhr.setRequestHeader('Content-Type', uploadOptions.ContentType);
xhr.send(uploadOptions.Body);
For the download, the library Superagent didn't work, but Request did. I also changed the encoding of the buffer to base64. Here's the code:
request({
url: _autodesk_api_baseurl
+ baseUrl
+ downloadOptions.bucket
+ '/objects/'
+ encodeURIComponent(downloadOptions.key),
method: "GET",
headers: {
'Authorization': 'Bearer ' + token.access_token
},
encoding: null
}, function (error, response, body) {
//Error handling goes here
if (typeof callback === 'function') {
callback(null, new Buffer(body, 'base64'));
}
});
After, that, I can just write the buffer to a file and open it. Thanks to those who helped answer.
This section doesn't seem right:
.query({'response-content-type': 'application/octet-stream'})
It should be
.set('response-content-type', 'application/octet-stream')
Anyway, Augusto is correct - you don't need to provide any additional header other than Authorization
Don't believe you need content-type to download a file, see more here. Can you request the details of the file?
This the curl to download it that should work:
curl -v "https://developer.api.autodesk.com/oss/v2/buckets/storage.vcs.prod.mevsg.autodesk.com/objects/assets%2FNT5NR9KJU2PH%2Fea02ec77505f2ea2defac93fe231764f2916e4d1aeaac7d92945a08a0086c60667369431361d5aa426d4cccca49b9e4c7cb70bc6ebf700258a3cb37617eacfa0"
-X GET
-H "Authorization: Bearer AbCdEfGhIjKlMnOpQrStUvXwYz"
And here is a code I used with NodeJS/Request module. It's in fact quite generic, but if I pass the /oss/ URL resource, it works fine. I'm not sure which library you're using, sorry.
function download(resource, token, onsuccess) {
console.log('Downloading ' + config.baseURL + resource); // debug
request({
url: config.baseURL + resource,
method: "GET",
headers: {
'Authorization': 'Bearer ' + token,
},
encoding: null
}, function (error, response, body) {
onsuccess(new Buffer(body, 'base64'));
});
}

Posting video to facebook from the browser using the graph API

I am trying to post a video from the browser to an edge sing the below code
var url = "https://graph.facebook.com/v2.5/" + this.uid + "/videos" + "?access_token=" + token;
var formData = new FormData();
formData.append("source", file);
formData.append("access_token", token);
return $.ajax({
url: url,
contentType: false,
processData: false,
type : "POST",
data: formData
})
But it gives a 400 bad request error.The response is
{
"error": {
"message": "Bad signature",
"type": "OAuthException",
"code": 1,
"fbtrace_id": "FYc5192NtSs"
}
}
Can you please tell me what am I doing wrong ?
I made the following utility function
var makeApiRequest: function(accessToken, config, successCallback, errorCallback) {
var baseUrl = 'https://graph.facebook.com/v2.5/';
// parse config and defaults
var config = config || {},
url = config.url || 'me',
data = config.data || {},
method = config.method || 'GET';
config.url = baseUrl + url + '&access_token=' + accessToken;
// make the api request
$.ajax(config)
.done(function(data) {
if (!!successCallback) {
successCallback(data);
} else {
console.log(data);
}
}
).error(function(xhr) {
errorCallback(xhr);
});
}
Which can be called like this for a video.
makeApiRequest(
'<token>',
{
url: 'me/videos',
data: {file_url:'http://example.com/path/to/file.mp4', description: 'title'},
method: 'POST'
}, successCb, errorCb);
Please ensure you use a token which was acquired using v2.5 of the API. You need publish_actions, publish_pages (for pages) permission to post
Debug your access token here

Access-Control-Allow-Origin Errors even though the REST Server sets header

I am trying to learn about REST server and hosting a flask server.
running curl on the server url i get:
HTTP/1.1 200 OK
Access-Control-Allow-Methods: POST, OPTIONS, GET, HEAD
Access-Control-Allow-Origin: *
Access-Control-Max-Age: 21600
Content-Type: text/html; charset=utf-8
Date: Sat, 28 Jun 2014 07:08:41 GMT
Server: gunicorn/19.0.0
Content-Length: 36
Connection: keep-alive
But when i try to access data from it from another url i get:
XMLHttpRequest cannot load --server url--. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin --page url-- is therefore not allowed access.
The following codes I have tried so far to get data:
var formData = new FormData();
formData.append("name",username );
formData.append("id", userid);
var request = new XMLHttpRequest();
request.open("POST", "my-server-url");
request.send(formData);
console.log("Running Create user")
console.log("Status: "+request.status);
console.log("error: "+request.error);
console.log("responseText: "+request.responseText);
Returns
Running Create user
Status: 0
error: undefined
responseText:
I have tried with ajax and jquery which also fails with the same error described above
$.ajax({
url:'--server url--',
type:'POST',
data : mydata,
dataType: 'JSON',
success: function(data) {
console.log(data)
}
});
also
$.ajax({
url:'--server url--',
type:'POST',
data : mydata,
dataType: 'JSONP',
async: false,
success: function(data) {
console.log(data)
}
});
I am using crossdomain decorator snippet in the python code.
For a sample of my server route handling:
#app.route("/", methods=['POST', 'GET', 'OPTIONS'])
#crossdomain(origin='*')
def create():
if request.method == 'POST':
name = request.form['name']
id = request.form['id']
#duplicate = collection.find_one({'name': name, 'token': token})
duplicate = collection.find_one({'id': id})
if not duplicate:
data = {'name': name,
'id': id}
collection.insert(data, safe=True)
response= make_response({'status': 'created'}, 201)
response.headers['Access-Control-Allow-Origin'] = "*"
return response
else:
response= make_response({'status': 'already exists'}, 302)
response.headers['Access-Control-Allow-Origin'] = "*"
return response
I have finally managed to solve the problem, the following changes I have made to the ajax code
var formData = new FormData();
formData.append("id", userid);
$.ajax({
url: '--server--',
type: 'POST',
data: formData,
processData: false,
contentType: false,
success: function(data){
//do something with data
console.log(data)
},
error: function(e) {
//handle error
console.log(e)
}
})
I had to make this changes on the server too:
#app.route("/", methods=['POST', 'GET', 'OPTIONS'])
#crossdomain(origin='*')
def create():
if request.method == 'POST':
name = request.form['name']
id = request.form['id']
#duplicate = collection.find_one({'name': name, 'token': token})
duplicate = collection.find_one({'id': id})
if not duplicate:
data = {'name': name,
'id': id}
collection.insert(data, safe=True)
return jsonify({'status': 'created'}), 201
else:
return jsonify({'status': 'already exits'}), 302

AJAX request failing in jQuery but not in NodeJS

I have a RESTful web service (hosted on a different server via IIS) that returns JSON. The strange thing is the following NodeJS command line test application (not via the web browser, but via the command line) is working fine and returning the JSON:
Working NodeJS App:
var request = require("request");
var btoa = require("btoa");
var uname = "corp\\user.name";
var pword = "password123"
var options = {
url: "http://192.168.3.142/v1/foo?format=json",
headers: {
"Authorization": "Basic " + btoa(uname + ":" + pword)
}
};
request(options, function(err, response, body) {
console.log(body);
});
However the following AJAX request fails with:
OPTIONS http://192.168.3.142/v1/foo?format=json 401 (Unauthorized) jquery-1.11.0.min.js:4
XMLHttpRequest cannot load http://192.168.3.142/v1/foo?format=json. Invalid HTTP status code 401
This is the response header from the server:
Response Headers:
Access-Control-Allow-Headers:Authorization
Access-Control-Allow-Methods:GET, POST, PUT, DELETE, OPTIONS
Access-Control-Allow-Origin:*
Content-Length:1293
Content-Type:text/html
Date:Thu, 06 Mar 2014 05:41:24 GMT
Server:Microsoft-IIS/7.5
WWW-Authenticate:Basic realm="192.168.3.142"
X-Powered-By:ASP.NET
AJAX code:
$.ajaxSetup({
beforeSend: function (xhr, settings) {
var creds = {
username: "corp\\user.name",
password: "password123"
};
xhr.setRequestHeader("Authorization", "Basic " + btoa(creds.username + ":" + creds.password));
return true;
}
});
$.ajax({
type: "GET",
url: "http://192.168.3.142/v1/foo?format=json",
success: function (data, text) {
console.log(data);
}
});
UPDATE:
Throws the same 401 (Unauthorized):
var creds = {
username: "corp\\user.name",
password: "password123"
};
var credentials = btoa(creds.username + ":" + creds.password);
$.ajax({
type: "GET",
dataType: "text/json",
url: "http://192.168.3.142/v1/foo?format=json",
beforeSend: function (xhr) {
xhr.setRequestHeader("Authorization", "Basic " + credentials);
return true;
},
success: function (data, text) {
console.log(data);
}
});
Once I added xhrFields: { withCredentials: true } to the $.ajaxSetup({}); the error was returning:
Credentials flag is 'true', but the 'Access-Control-Allow-Credentials' header is ''. It must be 'true' to allow credentials.
I added Access-Control-Allow-Credentials: true on the server-side and it's now working correctly.
var creds = {
username: "username",
password: "password"
};
var credentials = btoa(creds.username + ":" + creds.password);
$.ajaxSetup({
xhrFields: { withCredentials: true },
beforeSend: function (xhr, settings) {
xhr.setRequestHeader("Authorization", "Basic " + credentials);
return true;
}
});
$.ajax({
type: "GET",
url: "http://localhost/v1/service",
async: true,
success: function (data, text) {
console.log(data);
}
});

Categories