This is probably something simple, but I just can't see it.
I've got my sencha-touch application posting data to my WebService (asp.net-mvc-3). The Sencha Touch js code looks like this.
var submitCommunicateCard = function () {
console.log(rpc.views.Contact.CommunicateCard.getValues());
Ext.Ajax.request({
url: WebService('GetInTouch', 'CommunicateCard'), //http://webservice.example.com/GetInTouch/CommunicateCard
method: 'post',
params: {
callback: 'foo', //temporary until I can better setup the callback.
name: rpc.views.Contact.CommunicateCard.getValues().name,
city: rpc.views.Contact.CommunicateCard.getValues().city
}
});
};
Since I need to "thwart" my Cross Site Scripting problems, I've had to write an ActionFilter that adds the appropriate headers.
namespace WebService.Attributes
{
public class AllowCrossSiteJsonAttribute : ActionFilterAttribute
{
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
HttpContext.Current.Response.Cache.SetCacheability(HttpCacheability.NoCache);
HttpContext.Current.Response.Cache.SetNoStore();
HttpContext.Current.Response.AppendHeader("Access-Control-Allow-Origin", "*");
string rqstMethod = HttpContext.Current.Request.Headers["Access-Control-Request-Method"];
if (rqstMethod == "OPTIONS" || rqstMethod == "POST")
{
HttpContext.Current.Response.AppendHeader("Access-Control-Allow-Methods", "GET, POST, OPTIONS");
HttpContext.Current.Response.AppendHeader("Access-Control-Allow-Headers", "X-Requested-With, Accept, Access-Control-Allow-Origin");
}
}
}
}
And in my controller, I'm receiving the data from my app as follows.
[AllowCrossSiteJsonAttribute]
public JsonpResult CommunicateCard(CommunicateCardModel communicateCardModel)
{
CommunicateCardModel cc = null;
string rqstMethod = System.Web.HttpContext.Current.Request.Headers["Access-Control-Request-Method"];
if (rqstMethod != "POST")
{
// Do stuff with the model
return this.Jsonp(true);
}
else {
return this.Jsonp(false);
}
}
You'll see that I had to put if (rqstMethod != "POST") because the model from the "POST" is blank, but the model from the "OPTIONS" is not.
Here are the raw headers being passed... (note: these two headers are being passed in pairs... ie: the controller is being called twice.)
FIRST CALL
OPTIONS /GetInTouch/CommunicateCard HTTP/1.1
Host: webservice.example.com
Referer: http://192.168.3.138/
Access-Control-Request-Method: POST
Origin: http://192.168.3.138
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_0) AppleWebKit/534.24 (KHTML, like Gecko) Chrome/11.0.696.71 Safari/534.24
Access-Control-Request-Headers: X-Requested-With, Content-Type
Accept: /
Accept-Encoding: gzip,deflate,sdch
Accept-Language: en-US,en;q=0.8
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.3
SECOND CALL (notice the very bottom line that contains the posted data (which is not contained within the first call) callback=foo&name=Chester&city=Toronto)
POST /GetInTouch/CommunicateCard HTTP/1.1
Host: webservice.example.com
Referer: http://192.168.3.138/
Content-Length: 38
Origin: http://192.168.3.138
X-Requested-With: XMLHttpRequest
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_0) AppleWebKit/534.24 (KHTML, like Gecko) Chrome/11.0.696.71 Safari/534.24
Content-Type: application/x-www-form-urlencoded; charset=UTF-8
Accept: /
Accept-Encoding: gzip,deflate,sdch
Accept-Language: en-US,en;q=0.8
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.3
callback=foo&name=Chester&city=Toronto
Is there any way to prevent multiple calls to my controller? (or why IS my controller being called twice?)
Turns out it was fixed by making a JSONP call from my Sencha Touch app.
Ext.util.JSONP.request
// THIS IS WRONG, DON'T USE THIS CODE TO MAKE JSONP CALLS
var submitCommunicateCard = function () {
console.log(rpc.views.Contact.CommunicateCard.getValues());
Ext.Ajax.request({
url: WebService('GetInTouch', 'CommunicateCard'), //http://webservice.example.com/GetInTouch/CommunicateCard
method: 'post',
params: {
callback: 'foo', //temporary until I can better setup the callback.
name: rpc.views.Contact.CommunicateCard.getValues().name,
city: rpc.views.Contact.CommunicateCard.getValues().city
}
});
// THIS IS RIGHT
var submitCommunicateCard = function () {
console.log("Outbound Data Object:");
console.log(rpc.views.Contact.CommunicateCard.getValues());
Ext.util.JSONP.request({
url: WebService('GetInTouch', 'CommunicateCard'),
method: 'post',
callbackKey: 'callback',
params: {
name: rpc.views.Contact.CommunicateCard.getValues().name,
city: rpc.views.Contact.CommunicateCard.getValues().city
},
callback: function (result) {
console.log("Inbound Data Object:");
console.log(result);
// Handle error logic
if (result.success === true) {
Ext.Msg.alert("Sent!", "Thank you, your message has been sent!", Ext.emptyFn);
rpc.views.Contact.CommunicateCard.reset();
} else {
Ext.Msg.alert("Oops!", "looks like something went wrong, please try again.", Ext.emptyFn);
}
}
});
};
Related
I am trying to make a simple POST request from the client to an MVC controller in my ASP.NET Core application. The problem is that even though I have set the ajax call properly (I think), the payload is always submitted as form url encoded and my model on the server ends up null. Here is my setup:
Controller action definition:
[HttpPost]
public async Task<EmailResponse> SendEmail([FromBody] EmailModel model)
{
EmailResponse response = new EmailResponse();
...
return response;
}
Model:
public class EmailModel
{
[JsonProperty("fistName")]
public string FirstName { get; set; }
[JsonProperty("lastName")]
public string LastName { get; set; }
[JsonProperty("email")]
public string Email { get; set; }
[JsonProperty("company")]
public string Company { get; set; }
[JsonProperty("message")]
public string Message { get; set; }
}
Client ajax call:
$.ajax({
type: "POST",
url: "/Home/SendEmail",
contentType: 'application/json; charset=utf-8',
data: model
}).done(function (result) {
...
}).error(function(error) {
...
});
Here is my request:
POST /Home/SendEmail HTTP/1.1
Host: localhost:5000
Connection: keep-alive
Content-Length: 77
Pragma: no-cache
Cache-Control: no-cache
Accept: */*
Origin: http://localhost:5000
X-Requested-With: XMLHttpRequest
User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/53.0.2785.143 Safari/537.36
Content-Type: application/json; charset=UTF-8
Referer: http://localhost:5000/
Accept-Encoding: gzip, deflate
Accept-Language: en-US,en;q=0.8
Cookie: _ga=GA1.1.116706601.1460641478
firstName=Joe&lastName=Doe&email=test%40test.com&company=Acme%2C+Inc&message=
Notice the payload at the end of the request. It is not in JSON format even though I am passing a plain JS object and specifying the contentType as application/json. I am guessing this is why my model is always null on the server.
I have been staring at this for couple of hours now and cannot see where the problem is. Any input is greatly appreciated.
Thank you.
Your model is not serialized to json. The object is serialized to default media type - key value pairs - what is known as "application/x-www-form-encoded".
Try to enforce the JSON
$.ajax({
type: "POST",
url: "/Home/SendEmail",
contentType: 'application/json; charset=utf-8',
data: JSON.stringify(model) //notice the JSON.stringify call
}).done(function (result) {
...
}).error(function(error) {
...
});
I know there are many questions on SO about this but none of the suggestions have worked for me.
Here is my code:
var restService = "http://wcfrestservice:8004/RADPOCService/WebApp1";
$.ajax({
url: restService,
type: "POST",
data: { PhoneNumber: y },
dataType: "json",
contentType: "application/json; charset=utf-8",
success:
function (data) {
window.open(data.Url, '_blank');
}
});
Fiddler shows my request going across the wire like so (redacted):
POST http://localhost:8004/RADPOCService/WebApp1 HTTP/1.1
Host: localhost:8004
Connection: keep-alive
Content-Length: 22
Accept: application/json, text/javascript; q=0.01
Origin: http://localhost:8000
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/51.0.2704.103 Safari/537.36
Content-Type: application/json; charset=UTF-8
Referer: http://localhost:8000/Default.aspx
Accept-Encoding: gzip, deflate
Accept-Language: en-US,en;q=0.8
Requestor: Me
PhoneNumber=1234567890
I am expecting the payload to look like this:
{ "PhoneNumber": "1234567890"}
When I set the payload as above in the Fiddler Composer tab the service works as expected. What am I doing wrong?
I hate to do this so quickly after posting my question but the answer is to use the JSON.stringify API on the data being sent to the service. So the above should have the following code for 'data' in the ajax call:data: JSON.stringify({ PhoneNumber: y })
I am using ExtJs to create a button that do an ajax post to my django application, but the post is blocked by a FORBIDDEN (403) error.
I tryed to pass the CSRF token in as POST data by setting a custom X-CSRFToken header to the value of the CSRF token (https://docs.djangoproject.com/en/1.3/ref/contrib/csrf/#ajax) without success
ExtJS.js
action = new Ext.Button({
text: 'Ajax Test',
handler: function () {
Ext.Ajax.request({
url: 'test/',
method: 'POST',
headers: { 'Content-Type': 'application/json'},
params: {'test': 'test'},
success: function(response, opts) {
var obj = Ext.decode(response.responseText);
console.dir(obj);
},
failure: function(response, opts) {
console.log('server-side failure');
}
});
},
});
view.py
def test(request):
print "TEST WORKING"
print dict(request.POST.copy().iteritems())
return HttpResponse("")
CHROME NETWORK TAB:
Response:
CSRF verification failed. Request aborted.
Cookies:
Request Cookies:
csrftoken : S7uLgmhqeprWqL4NdH9mznIfpTgyM9RP
djdt : hide
djdttop : 30
sessionid : sx4ukmkitqp39wvuve1a9zed2kjiwfb1
Response Cookies:
(empty)
Headers:
Request URL:http://127.0.0.1:8000/basqui/layer/edit/2/test/
Request Method:POST
Status Code:403 FORBIDDEN
Request Headersview source
Accept:*/*
Accept-Encoding:gzip,deflate,sdch
Accept-Language:fr-FR,fr;q=0.8,en-US;q=0.6,en;q=0.4
Connection:keep-alive
Content-Length:9
Content-Type:application/x-www-form-urlencoded; charset=UTF-8
Cookie:sessionid=sx4ukmkitqp39wvuve1a9zed2kjiwfb1; csrftoken=S7uLgmhqeprWqL4NdH9mznIfpTgyM9RP; djdttop=30; djdt=hide
Host:127.0.0.1:8000
Origin:http://127.0.0.1:8000
Referer:http://127.0.0.1:8000/basqui/layer/edit/2
User-Agent:Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/31.0.1650.63 Safari/537.36
X-Requested-With:XMLHttpRequest
Form Dataview sourceview URL encoded
test:test
Response Headersview source
Content-Type:text/html
Date:Tue, 07 Jan 2014 16:52:15 GMT
Server:WSGIServer/0.1 Python/2.7.5
X-Frame-Options:SAMEORIGIN
action = new Ext.Button({
text: 'Ajax Test',
handler: function () {
var csrf = Ext.util.Cookies.get('csrftoken');
Ext.Ajax.request({
url: 'test/',
method: 'POST',
headers: { 'Content-Type': 'application/json'},
params: {'test': 'test', 'csrfmiddlewaretoken': csrf},
success: function(response, opts) {
var obj = Ext.decode(response.responseText);
console.dir(obj);
},
failure: function(response, opts) {
console.log('server-side failure');
}
});
},
});
https://www.sencha.com/forum/showthread.php?134125-Django-1-3-Login-with-ExtJS-4-and-CSRF
I put this in my Application launch function:
Ext.require(["Ext.util.Cookies", "Ext.Ajax"], function(){
// Add csrf token to every ajax request
var token = Ext.util.Cookies.get('csrftoken');
if(!token){
Ext.Error.raise("Missing csrftoken cookie");
} else {
Ext.Ajax.defaultHeaders = Ext.apply(Ext.Ajax.defaultHeaders || {}, {
'X-CSRFToken': token
});
}
});
I have an action
[HttpPost]
public JsonResult AddLocationsForOrder(List<BuyerOrderLocation> locations, string[] orders)
{
// something here
}
and js code, which sends the request:
data = { locations: serializedLocations, orders: selector.val() };
$.ajax({
url: addLocationUrl,
success: function (responseText) { Core.responceReceived(responseText, null, null); },
error: function () { Core.showErrorNotification("Sorry, some error occured. Please contact administrator"); },
async: false,
type: 'POST',
dataType: 'json',
data: JSON.stringify(data)
});
post details from firebug are here:
locations
"[{"id":225,"country":"United States","countryShort":"US","state":"Iowa","stateShort":"IA","city":null,"zipCode":null,"address":"Douglas, IA, USA","latitude":41.9053851,"longtitude":-93.8349976,"bounds":null,"isDeleted":false,"county":"Boone","radius":0},{"id":226,"country":"United States","countryShort":"US","state":"Iowa","stateShort":"IA","city":null,"zipCode":null,"address":"Iowa, USA","latitude":41.8780025,"longtitude":-93.097702,"bounds":null,"isDeleted":false,"county":null,"radius":0}]"
orders
[ "10440" , "10441" , "10442" ]
0 "10440"
1 "10441"
2 "10442"
And request headers:
Accept application/json, text/javascript, */*; q=0.01
Accept-Encoding gzip, deflate
Accept-Language en-us,en;q=0.5
Connection keep-alive
Content-Length 830
Content-Type application/x-www-form-urlencoded; charset=UTF-8
Cookie ASP.NET_SessionId=ewtvgwleg5or1lqctinpjv2d; .ASPXAUTH=8414A94FE30B8F8D6FE862259398F39D6F6D2EE995C9EE16549987E2E1291851788CAB75425579F61F70EBE4C7B785B07CB36773894A5B2A513966247AA5B670A25D4AE565796B449912D745EBE5E5E4AB8280902C132FC3D97C0C33BA2C2357372CD9C9EA49983DC4A8E875C6E4D653FA049EC7B0F3824666F35D3838226AA19ACEEC1B8C5716E995966787268313FEF90E2ABBAE989CA682D406EBCE361BB7
Host local.attorneyboost
Referer http://local.attorneyboost/Order/OrderInfo/10439
User-Agent Mozilla/5.0 (Windows NT 6.1; WOW64; rv:14.0) Gecko/20100101 Firefox/14.0.1
X-Requested-With XMLHttpRequest
As you can see, request type is "POST", and I'm "Jsoning" data before sending to the server. But in action I got a null values for parameters. What am I doing wrong? I'm already stuck on searching for mistake
In this article they explain how to send complex JSON object to ASP.NET.
Hope this helps
You need to specify the datatype in the request send it to the server. The datatype attribute of your called sets the format of the response of the server, to set the datatype in the format that need to send to the server you need to use the contentType attribute
Modify the ajax called with this
$.ajax({
url: addLocationUrl,
success: function (responseText) { Core.responceReceived(responseText, null, null); },
error: function () { Core.showErrorNotification("Sorry, some error occured. Please contact administrator"); },
async: false,
type: 'POST',
dataType: 'json',
data: JSON.stringify(data),
contentType = 'application/json; charset=utf-8'
});
You need to specify the datatype in the request send it to the server. The datatype attribute of your called sets the format of the response of the server, to set the datatype in the format that need to send to the server you need to use the contentType attribute
I know about error in application running on server and invoked operation disconnect all HTTP clients. I need to invoke this functionality on the server but I'm not able to fix the error.
Here is my server code:
<?php
// file: run_script.php
shell_exec('close_all_HTTP_connections_error '.$_REQUEST['params']);
?>
I'm trying to find workaround via AJAX call, I know that call fails, but user doesn't see error like ERR_EMPTY_RESPONSE. My problem is that I need to do another call to the server (which doesn't fail normaly). The second call is not send to server because previous call fail I guess.
Here is my jQuery AJAX call:
function sendData(url, step) {
$.ajax({
type: 'POST',
async: true,
url: url,
headers: { // I try it without this also
'Connection' : 'close'
},
data: {
'params' : 'bla bla'
},
complete: function(jqXHR, textStatus) {
console.log(jqXHR);
console.log(textStatus);
if (step < 2) {
sendData('another.php', step+1);
}
else {
console.log("done");
// go forward
}
},
dataType: 'html'
});
}
$(document).ready(function() {
sendData('run_script.php', 1);
});
Here is my screen shot from Chrome inspector:
And HTTP Requests:
run_script.php:
POST http://?????.com/test/run_script.php HTTP/1.1
Origin: http://?????.com
X-Requested-With: XMLHttpRequest
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/535.22 (KHTML, like Gecko)
Chrome/19.0.1049.3 Safari/535.22
Content-Type: application/x-www-form-urlencoded
Accept: text/html, */*; q=0.01
Referer: http://?????.com/test/result.php
params:bla bla
another.php:
POST http://?????.com/test/another.php HTTP/1.1
Origin: http://?????.com
X-Requested-With: XMLHttpRequest
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/535.22 (KHTML, like Gecko)
Chrome/19.0.1049.3 Safari/535.22
Content-Type: application/x-www-form-urlencoded
Accept: text/html, */*; q=0.01
Referer: http://?????.com/test/result.php
params:bla bla
There is no HTTP Response of course.
Problem was, that task previously invoked on server restarts server. Then I need to wait before next AJAX call is invoked.
I fact I have to solve problem with server restart first, this is work-around only and not the best solution.