I am building a web application with django-rest-framework and extjs5.
Obviously i faced problems with django's csrf token, which i had to inlude in Extjs's Ajax requests.
But while i implemented POST method successfully, it seems that my implementation doesn't work for PUT and DELETE method.
My POST method code:
onSaveRecordBtnClick: function(){
Job_Name = this.lookupReference('Job_Name').getValue();
var csrf = Ext.util.Cookies.get('csrftoken');
Ext.Ajax.request({
url: '/jobs_api/job/',
method: "POST",
params: {
Job_Name: Job_Name,
'csrfmiddlewaretoken': csrf
},
success: function(conn, response, options, eOpts) {
var result = MyApp.util.Util.decodeJSON(conn.responseText);
if (result.success) {
alert('Job Submission Successfull');
}
else {
MyApp.util.Util.showErrorMsg(conn.responseText);
}
},
failure: function(conn, response, options, eOpts) {
MyApp.util.Util.showErrorMsg(conn.responseText);
}
});
}
This works perfectly, but when i try PUT or DELETE method i keep getting:
Request Method:DELETE
Status Code:403 FORBIDDEN
{"detail":"CSRF Failed: CSRF token missing or incorrect."}
My DELETE method:
onJobDblClick : function(grid, record, index, eOpts) {
var job_id = record.id;
var csrf = Ext.util.Cookies.get('csrftoken');
Ext.Ajax.request({
url: '/jobs_api/job/' + job_id + '/',
method: "DELETE",
params: {
'id': job_id,
'csrfmiddlewaretoken': csrf
},
success: function(conn, response, options, eOpts) {
var result = MyApp.util.Util.decodeJSON(conn.responseText);
if (result.success) {
alert('Job Deleted Successfully');
}
else {
MyApp.util.Util.showErrorMsg(conn.responseText);
}
},
failure: function(conn, response, options, eOpts) {
MyApp.util.Util.showErrorMsg(conn.responseText);
}
});
}
My job model is:
Ext.define('MyApp.model.Job', {
extend: 'MyApp.model.Base',
fields: [
{ name: 'id', type: 'int' },
{ name: 'Job_Name', type: 'string' },
],
proxy: {
type: 'rest',
url: '/jobs_api/job/',
reader: {
type: 'json',
rootProperty: 'data'
}
}
});
I don't know why this is happening. Please help!!
Related
I have the handleDownload method which starts a file download. The function posts to the backend, which gives back a response, based on that a new request posts to the server where the files are. I saw that I can use mockjax to mock the requests, but how to handle the different paths like success, error, etc. How should I know which response triggers which path (success,error, complete, ...). What would be a great startegy to test the handleDownload function, and how? For mocking I use Sinon.js I don't have a really deep understanding yet. I should also check either the handleDownloadFinal function is called.
handleDownload: function(data, url) {
$.ajax({
type: "POST",
url: url,
data: {},
success: function(response) {
if (response.success) {
var start_token = response.token;
$.ajax({
type: start_token.method,
url: start_token.url,
beforeSend: function(xhr) {
xhr.setRequestHeader('Authorization', start_token.header);
},
success: function(start_response) {
handleDownloadFinal(start_response.status_token);
},
error: function(start_response) {
$.ajax({
type: "POST",
url: url + 'proxy/',
success: function(fallback_response) {
if (fallback_response.success) {
handleDownloadFinal(fallback_response.status_token, true, fallback_response.job_uuid);
} else {
errorDownload(response.error);
}
},
error: function(fallback_response) {
// Now this is some real error
generalErrorDownload();
},
dataType: 'json'
});
},
dataType: 'json',
xhrFields: {
withCredentials: true
}
});
} else {
errorDownload(response.error);
}
},
error: function(response) {
generalErrorDownload();
},
complete: function() {
},
dataType: "json"
});
}
You should use the fake server coming with sinon.
before(function(){
//create the server
this.server = sinon.fakeServer.create();
// let the server automatically respond for every request
server.autoRespond = true;
})
it('test something', function(){
//let the server respond for specific url with 200-ok
this.server.respondWith("POST", "/some/article/comments.json", [200, {
"Content-Type": "application/json"
}, '[{ "id": 12, "comment": "Hey there" }]']);
})
As you have a bunch of requests and you have to check all combinations I would suggest to have helper function for every request fail success so you could test the cases like this:
function letFirstRequestSucceed() {
this.server.respondWith("POST", "urlForFirstRequest", [200, {
"Content-Type": "application/json"
}, '[{ "id": 12, "comment": "Hey there" }]']);
}
function letSecondRequestFail() {
this.server.respondWith("POST", "urlForSecondRequest", [404, {
"Content-Type": "application/json"
}, '{error: "some error message"}');
}
function letThirdRequestFail() {
this.server.respondWith("POST", "urlForThirdRequest", [404, {
"Content-Type": "application/json"
}, '{error: "some error message"}');
}
it("should to something when the second and third request fails", function () {
sinon.spy(window, 'generalErrorDownload');
letFirstRequestSucceed();
letSecondRequestFail();
letThirdRequestFail();
handleDownload('someDate', 'aUrl');
expect(generalErrorDownload)
})
Btw you should think about to refactor you code using jquerys deferred which is supported by api ajax calls, this would make your could much more readable.
I am trying to pass knockout object as below,
When i pass the data using // ko.utils.postJson only without any the AJAx the data is passed to my controller to the "task", but when i try to post by Ajax I get a null value for task
function TaskListViewModel() {
var self = this;
self.availableMeals = [
{ UserName: "Standard", UserId: 0 },
{ UserName: "Premium", UserId: 34 },
{ UserName: "Ultimate", UserId: 290 }
];
self.save = function () {
// ko.utils.postJson(location.href, { task: this.availableMeals });
$.ajax(location.href,{
data: ko.toJSON({ task: this.availableMeals });,
type: 'POST',
dataType:'json',
contentType: 'application/json',
success: function (result) { alert(result) }
});
};
}
ko.applyBindings(new TaskListViewModel());
To the Controller as below,
[HttpPost]
public ActionResult About([FromJson] IEnumerable<UserProfile> task)
{
return RedirectToAction("Login","Account");
}
I would try changing your code to call the stored self reference in your Ajax call as follows:
$.ajax(location.href,{
data: ko.toJSON({ task: self.availableMeals });,
type: 'POST',
dataType:'json',
contentType: 'application/json',
success: function (result) { alert(result) }
});
};
I'm guessing that you are having a scope issues where this is losing it's reference in your Ajax call.
I'm making an ajax request to retrieve json data from webtrends - a service that requires a login. I'm passing the username and password in my ajax request, but still gives me a 401 unauthorized error. I've tried 3 different methods - but no luck. Can someone pls help me find a solution?
1. $.getJSON('https://ws.webtrends.com/..?jsoncallback=?', { format: 'jsonp', suppress_error_codes: 'true', username: 'xxx', password: 'xxx', cache: 'false' }, function(json) {
console.log(json);
alert(json);
});
2. $.ajax({
url: "https://ws.webtrends.com/../?callback=?",
type: 'GET',
cache: false,
dataType: 'jsonp',
processData: false,
data: 'get=login',
username: "xxx",
password: "xxx",
beforeSend: function (req) {
req.setRequestHeader('Authorization', "xxx:xxx");
},
success: function (response) {
alert("success");
},
error: function(error) {
alert("error");
}
});
3. window.onload=function() {
var url = "https://ws.webtrends.com/...?username=xxx&password=xxx&callback=?";
var script = document.createElement('script');
script.setAttribute('src', url);
document.getElementsByTagName('head')[0].appendChild(script);
}
function parseRequest(response) {
try {
alert(response);
}
catch(an_exception) {
alert('error');
}
}
Method 3 might work when you use a named callback function and use basic authentication in the url. Mind though that a lot of browsers don't accept url-authentication (or whatever the name is). If you want to try it, you can rewrite it like this:
window.onload = function() {
var url = "https://xxx:xxx#ws.webtrends.com/...?callback=parseRequest";
var script = document.createElement('script');
script.setAttribute('src', url);
document.getElementsByTagName('head')[0].appendChild(script);
}
function parseRequest(response) {
try {
alert(response);
}
catch(an_exception) {
alert('error');
}
}
I'm trying to make a simple AJAX call to jsFiddle's JSON echo api using Ext.Ajax. It makes the request successfully, but the object returned is empty, not the JSON object I send (which it should be).
Code:
Ext.Ajax.request({
url: '/echo/json/',
jsonData: { foo: 'bar' },
success: function(resp) {
console.log('success!');
console.log(Ext.decode(resp.responseText)); //empty object..? why?
},
failure: function(resp) {
console.log('failure!');
},
});
Fiddle: http://jsfiddle.net/nANE7/
How come the response is just an empty object? Where's the foobar JSON information that it's meant to echo back?
Try this:
Ext.Ajax.request({
url: '/echo/json/',
params: {
json: Ext.encode(
{
param1:'bar'
}
)
},
success: function(resp) {
console.log('success!');
console.log( resp );
console.log(Ext.decode(resp.responseText)); //empty object..? why?
},
failure: function(resp) {
console.log('failure!');
},
});
Below is my ajax call to the server which loads the store:
function setUpStore(Id){
store = Ext.create('Ext.data.TreeStore', {
storeId:'jsonStore',
proxy: {
type: 'ajax',
url: 'fetchData.action?ID='+Id,
reader: {
type: 'json'
},
success : function(resp){
alert("success!!!");
}
}
});
}
which calls the below java method which returns a JSON object:
public String fetchJSONObj(){
HttpServletResponse res = ServletActionContext.getResponse();
HttpServletRequest req = ServletActionContext.getRequest();
ID = (String) req.getParameter("ID");
res.setHeader("Content-Type", "application/json");
VendorVO root= ServiceHelper.getInstance().getService().getData(ID);
Data = new ExtJsTreeWrapper();
Data.setText(ID);
Data.setId(ID);
Data.getChildren().add(convertVOToExtJSWrapper(root));
return SUCCESS;
}
After I get the response from the server, I do not get the alert mentioned in the success handler. Am I declaring it correctly?
Thanks
proxy hasn't got a config option called success.
Given your code you can hook on the store's load event:
function setUpStore(Id){
store = Ext.create('Ext.data.TreeStore', {
storeId:'jsonStore',
proxy: {
type: 'ajax',
url: 'fetchData.action?ID='+Id,
reader: {
type: 'json'
},
},
listeners: {
load: {
fn: function() {
// Do something here.
},
},
scope: this
}
}
});
If you do manual load, you can also pass a callback as a parameter to the load function.