Cross Domain AJAX Post using easyXdm - asp.net

I am trying to get a cross domain AJAX post to work using the easyXdm library.
In my local development environment I have two sites:
1. http://localhost/MySite/ws/easyXDM/cors/index.html (EasyXdm file)
2. http://localhost/MyClientSite/TestPage.html (AJAX post from here)
TestPage.html (AJAX Post)
var rpc = new easyXDM.Rpc({
remote: "http://localhost/MySite/ws/easyXDM/cors/index.html"
},
{
remote: {
request: {}
}
});
rpc.request({
url: "http://localhost/MySite/ws/MyService.asmx/DoSomething",
method: "POST",
data: jsonData
}, function(response) {
console.log(JSON.parse(response.data));
$('#thanksDiv').fadeIn(2000, function () {
$('#thanksDiv').fadeOut(4000);
});
});
When I do the AJAX post I get the following in my browser's console:
easyXDM present on 'http://localhost/MySite/ws/easyXDM/cors/index.html?xdm_e=http%3A%2F%2Flocalhost%2FMyClientSite%2FTestPage.html&xdm_c=default884&xdm_p=4
native JSON found
easyXDM.Rpc: constructor
{Private}: preparing transport stack
{Private}: using parameters from query
easyXDM.stack.SameOriginTransport: constructor
easyXDM.stack.QueueBehavior: constructor
easyXDM.stack.RpcBehavior: init
{Private}: firing dom_onReady
... deferred messages ...
easyXDM.Rpc: constructor
{Private}: preparing transport stack
{Private}: using parameters from query
easyXDM.stack.SameOriginTransport: constructor
easyXDM.stack.QueueBehavior: constructor
easyXDM.stack.RpcBehavior: init
... end of deferred messages ...
easyXDM.stack.SameOriginTransport: init
easyXDM.stack.RpcBehavior: received request to execute method request using callback id 1
easyXDM.stack.RpcBehavior: requested to execute procedure request
easyXDM.stack.QueueBehavior: removing myself from the stack
Problem: The web service never actually receives the data. This is obvious as my AJAX post success function should show a thanksDiv and also a record should be created in the *database.
Note: I am replacing my existing AJAX post code as I need to use easyXdm to overcome an issue with Internet Explorer 6 and 7 on a client's site.
Additional Information:
The file-structure where my easyXdm files are located is as follows:
/ws/easyXDM/easyXDM.debug.js
/ws/easyXDM/easyXdm.swf
/ws/easyXDM/json2.js
/ws/easyXDM/name.html
/ws/easyXDM/cors/index.html

My web service was throwing a HTTP 500 server error as jsonData was not being sent correctly via easyXdm.
The json data looks like this before it was posted:
{ "param1": "value1", "param2": "value2"...... }
However, the web service was receiving the data one character per line e.g.
{
"
p
a
r
a
m
"
....
I was not serialising the json data prior to my post. So, based on the original code I posted in the original question:
To get it working I changed the line
data: jsonData
to
data: JSON.parse(jsonData)

Related

How to call server api decorated with ValidateAntiForgeryToken using Httpclientfactory Typed clients?

I am trying to incorporate a Edit Form page using GetAsync and PostAsync using typed httpclient. Everything works except my code doesn't call API actions with ValidateAntiForgeryToken. Most of the examples online do not address httpcontent used by httpclientfactory and instead use httpresponse. I am aware that the antiforgery token is missing on my request. How do I attach it to the request header? How do I retrieve it from the view? I want to use as less Javascript as possible. Here's a snippet of my Post request service.
Edit: For what it's worth, my api is dot net core and client is dot net core mvc.
var response = await _httpclient.PostAsync("api/edit/" + id, httpcontent);
response.EnsureSuccessStatusCode(); ```
In the MVC Edit view page, it will use a hidden file (named __RequestVerificationToken) to store the ValidateAntiForgeryToken, you can use F12 developer tools to check it.
<input name="__RequestVerificationToken" type="hidden" value="CfDJ8NrAkS ... s2-m9Yw">
After modifying the data, you could use JQuery to get the updated data, then use JQuery ajax to call the API method with the ValidateAntiForgeryToken. You can refer the sample code in my reply:
if we customize antiforgery options in Startup.ConfigureServices, such as: custom the Header Name for the RequestVerificationToken.
services.AddAntiforgery(o => o.HeaderName = "XSRF-TOKEN"); //configure the antiforgery service to look for the X-CSRF-TOKEN header. To prevent the cross-site request forgery.
Then, we could use the following script:
$.ajax({
type: "POST",
url: "/Survey/Create",
beforeSend: function (xhr) {
xhr.setRequestHeader("XSRF-TOKEN",
$('input:hidden[name="__RequestVerificationToken"]').val());
},
data: { "CategoryName": $("#CategoryName").val(), "CategoryID": $("#CategoryID").val() },
success: function (response) {
alert(response);
},
failure: function (response) {
alert(response.responseText);
},
error: function (response) {
alert(response.responseText);
}
});
Besides, you can also refer Prevent Cross-Site Request Forgery (XSRF/CSRF) attacks in ASP.NET Core.

Flutter HTTP request with JSON data to a Firebase function

I am currently trying to set up our Firestore database for a Flutter mobile app to take data from a Firebase function and store it into the database. Currently, we are trying to pass an HTTP request to our URI and attach some JSON data to it.
My function is as follows:
exports.testFunction = functions.https.onRequest((request, response) => {
var data = {
name: request.body.name,
age: request.body.age
};
var setDoc = db.collection('users').add(data);
response.json({result: `User ${data.name} at age ${data.age} added.`});
return;
});
Currently, the data can be retrieved when using a web browser and requesting from https://us-central1-[project-name].cloudfunctions.net/testFunction?name=[string]&age=[int]. This also works within our Flutter app, using the entire URL as a single argument with no body. However, when trying a cURL request from the command line:
curl -H 'Content-Type: application/json' -d '{"name": "[string]", "age": [int]}' https://us-central1-[project-name].cloudfunctions.net/testFunction
Hypothetically, the data should be in request.body, but I am getting an error saying the request could not be handled. What exactly is going wrong here?
Later, we want to implement this request in a Dart/Flutter app by attaching the JSON object to the body of the http.post. Is there a missing link in between this process that I'm missing?
The error Request body is missing data means that the payload that's being sent in the request needs to be mapped inside data. It's mentioned here in the docs that the Request body should have a data field.
var data = {
'data':{
name: request.body.name,
age: request.body.age
}
}

How to call node.js REST API from .NET

If I put the jquery code below within the script tag within a html page and drag the html page into a web browser the call to the API specified in the URL is made and I get back a response in JSON format. So this works good.
The reason I want to use .NET for calling the rest API that is made in node.js is because I want to use the unit test utility that exist in visual studio.
So when I start the unit test the call to the REST API made in node.js should be made and then I can check whatever I want in the returned json format by using the assert.AreEqual.
I have googled a lot and there is several example about
Unit Testing Controllers in ASP.NET Web API 2 but I don't want to unit test controller. I only want to call the REST API(made in node.js) when I start my unit test.
I assume to use .NET in the way I want is probably quite rare.
If it's not possible to use .NET and unit test in the way that I want here
I will use another test framework.
I hope to get some help from here.
Hope you understand what I mean.
$.ajax({
type: 'GET',
url: 'http://10.1.23.168:3000/api/v1/users/1',
dataType: 'json',
async: false,
headers: {
'Authorization': 'Basic ' + btoa('DEFAULT/user:password')
},
success: function(response) {
//your success code
console.log(response);
},
error: function (err) {
//your error code
console.log(err);
}
});
Many thanks
Basically what you need to do is to call node.js' API from your C# test code in a same way you call it using jQuery. There are several ways to do it:
Use HttpWebRequest class https://msdn.microsoft.com/en-us/library/system.net.httpwebrequest%28v=vs.110%29.aspx
Use HttpClient class https://msdn.microsoft.com/en-us/library/system.net.http.httpclient%28v=vs.118%29.aspx It's more "RESTable" since it exposes methods to call HTTP methods like GET, PUT, POST and DELETE methods directly.
3rd party software http://restsharp.org/
Generally I recommend approach #2.
Here's the example source with all the rest of the code.
Another resource is the docs.
This code snippet should be enough to get you where you need.
using(var client = newHttpClient())
{
client.BaseAddress = newUri("http://localhost:55587/");
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(newMediaTypeWithQualityHeaderValue("application/json"));
//GET Method
HttpResponseMessage response = awaitclient.GetAsync("api/Department/1");
if (response.IsSuccessStatusCode)
{
Departmentdepartment = awaitresponse.Content.ReadAsAsync < Department > ();
Console.WriteLine("Id:{0}\tName:{1}", department.DepartmentId, department.DepartmentName);
Console.WriteLine("No of Employee in Department: {0}", department.Employees.Count);
}
else
{
Console.WriteLine("Internal server Error");
}
}

jQuery Ajax Stop is not invoked (No error; 200 OK)

I have a working ASP.Net 2.0 code in my development server that uses jQuery Ajax. The result of the ajax call is used to load dropdown values.
But when this code is deployed to a new DMZ server, the result is not getting populated in dropdown – though I am getting 200 OK as response. One obvious thing is that the Type is different in the response. It is expected as application/json but coming as text/plain.
I have success call back and error callback codes. Along with this I have handlers for ajax start and stop. But none of these events are getting fired. What is the reason error/stop handlers are not getting fired? How can we make it work?
Note: The behavior is same in both IE and Chrome.
Update
Also observed that there is an error logged in console, as shown below. Is it related to the "Type"? How can we address this?
Note: Also note that the Content-Length is 0 in the response headers shown below.
Success Callback
jQuery
function loadASN()
{
var receiveScanParameter = getContainerParameters();
// console.log(receiveScanParameter);
$.ajax({
type: "POST",
url: "rcvScanTXAdd.aspx/GetASNForPlant",
contentType: "application/json; charset=utf-8",
dataType: "json",
data: JSON.stringify({ receiveScanParameter: receiveScanParameter }),
success: successPopulateASN,
error: errorFunction
});
}
Global jQuery Code
//Global Ajax Error handling Function
function errorFunction(xhr, status, error)
{
if(xhr == 'undefined' || xhr == undefined)
{
alert('xhr undefined');
}
alert(status);
alert(error);
}
$(document).ready(function ()
{
//Ajax Start
$('body').ajaxStart(function()
{
//Change cursor to waiting
$(this).css({'cursor':'wait'})
});
//Ajax End
$('body').ajaxStop(function() {
//Reset the cursor
$(this).css({'cursor':'default'})
});
});
Screenshots
I figured it out.
Step 1: Observed that there is an error logged in browser’s console (saying result is null). [This screenshot is updated in the question]
Step 2: Observed that the content length of the response is zero. Also observed that there is a gzip compression happened on the response (by reading the response headers).
Step 3: Analyzed the server's web.config. It was uisng a C# httpModule for compression. In that httpModule added bypassing logic for json. [I don’t want json to be compressed with this custom module. Later I will consider adding compression to JSON when I use IIS for compression instead of custom module]. Following is the C# code segment for by-passing JSON compression
request.ContentType.ToLower(CultureInfo.InvariantCulture).StartsWith("application/json")
WHen in doubt, read the API docs:
As of jQuery 1.8, the .ajaxStop() method should only be attached to document.
http://api.jquery.com/ajaxStop/
Same note can be found in $.ajaxStart docs

Meteor http calls limitations

Currently, I use the built-in meteor http method (see http://docs.meteor.com/#http) for issuing http calls, on both my client and my server.
However, I'm experiencing two issues:
is it possible to cancel a request?
is it possible to have multiple query parameters which share the same key?
Are these just Meteor limitations, or are there ways to get both to work using Meteor?
I know I could you jquery on the clientside, and there must be a server-side solution which supports both as wel, but I'd prefer sticking with meteor code here.
"is it possible to cancel a request?"
HTTP.call() does not appear to return an object on which we could call something like a stop() method. Perhaps a solution would be to prevent execution of your callback based on a Session variable?
HTTP.call("GET", url, function(error, result) {
if (!Session.get("stopHTTP")) {
// Callback code here
}
});
Then when you reach a point where you want to cancel the request, do this:
Session.set("stopHTTP", true);
On the server, instead of Session perhaps you could use an environment variable?
Note that the HTTP.call() options object does accept a timeout key, so if you're just worried about the request never timing out, you can set this to whatever millisecond integer you want.
"is it possible to have multiple query parameters which share the same key?"
Yes, this appears to be possible. Here's a simple test I used:
Meteor code:
HTTP.call("GET", "http://localhost:1337", {
query: "id=foo&id=bar"
}, function(error, result) {
// ...
});
Separate Node.js server: (just the basic example on the Node.js homepage, with a console.log line to output the request URL with query string)
var http = require('http');
http.createServer(function(req, res) {
console.log(req.url); // Here I log the request URL, with the query string
res.writeHead(200, {
'Content-Type': 'text/plain'
});
res.end('Hello World\n');
}).listen(1337, '127.0.0.1');
console.log('Server running at http://127.0.0.1:1337/');
When the Meteor server is run, the Node.js server logged:
/?id=foo&id=bar
Of course, this is only for GET URL query parameters. If you need to do this for POST params, perhaps you could store the separate values as a serialized array string with EJSON.stringify?

Resources