How to get responsecode from store callback? - extjs

I'm trying to handle session timeout server-side.
When getting session timeout, my server sends back a response with json
{success: false}, ContentType: 'application/json', ResponseNo: 408
store:
var storeAssets = Ext.create('Ext.data.Store', {
model : 'modCombo',
autoLoad : false,
proxy : { limitParam : undefined,
startParam : undefined,
paramName : undefined,
pageParam : undefined,
noCache : false,
type : 'ajax',
url : '/caricaAssets.json',
reader : { root : 'data' }
}
});
And on the client side, I handle callback loading store like this:
storeAssets.load({
scope: this,
callback: function(records, operation, success) {
if (!success) { Ext.Msg.alert('Error'); }
}
});
To perform different responses, I'd like to change alert.
So, if response no. is 408, I can alert session expired (and so on, managing response numbers).
But I didn't find any way to get response no. in store callback!
Any suggestions?

Unfortunately, the callback method does not have the server response passed in as a parameter. This is likely since there are many ways to load data into a store, and not all of them will have a server response.
You can override the proxy's processResponse function to store the server's response with the operation object, then access it in your callback.
Ext.define('Ext.data.proxy.ServerOverride', {
override: 'Ext.data.proxy.Server',
processResponse: function (success, operation, request, response, callback, scope) {
operation.serverResponse = response;
this.callParent(arguments);
}
});
Then, to get the status:
storeAssets.load({
scope: this,
callback: function(records, operation, success) {
if (operation.serverResponse.status === 408) {
Ext.Msg.alert('Session expired');
}
}
});

I know this is quite old now, but I had a similar problem.
The solution I found was to listen for the exception event in the proxy.
proxy{
type: 'ajax',
reader: {
type: 'json'
,
listeners: {
exception: function(proxy, response, options){
Ext.MessageBox.alert('Error', response.status + ": " + response.statusText);
}
}
}
I also predicated my store load callback to only proceed when success is true.
Hopefully someone else searching will find this helpful.

Try this (on extjs 4.2.2)
callback: function (records, operation, success) {
operation.request.operation.response.status; }

Solved adding following code:
Ext.Ajax.on('requestexception', function(con, resp, op, e){
if (resp.status === 408) {
Ext.Msg.alert('Warning', 'Session expired');
} else {
if (resp.status === 404) {
Ext.Msg.alert('Error', Ext.util.Format.htmlEncode('Server not ready'));
} else {
if (resp.status !== undefined) {
Ext.Msg.alert('Error', Ext.util.Format.htmlEncode('Server not found (') + resp.status + ')');
} else {
Ext.Msg.alert('Error', 'Server not found');
}
}
}
});
When i call ajax request, server gives back information that are catched by this exception. Now I can handle callback code!

I know this question is pretty "old", but in ExtJS 4.2.2, when
callback: function(a,b,c) {}
happens, you can automatically catch the server response using
b.error.status
if (!c) {
if (b.error.status === 401) {
//logout
}
}
I don't know if it was implemented only a few time ago (after this was posted I mean), but still it can help anyone checking this post in the future I guess...

Related

Handling Ajax response with success and without failure

The below code has both success and failure handling
jQuery.ajax({
type:"post",
dataType:"json",
url: myAjax.ajaxurl,
data: {action: 'submit_data', info: info},
success: function(data) {
successmessage = 'Data was succesfully captured';
$("label#successmessage").text(successmessage);
},
error: function(data) {
successmessage = 'Error';
$("label#successmessage").text(successmessage);
},
});
$(":input").val('');
return false;
However we are not following the above...We are following as below
jQuery.ajax({
type:"post",
dataType:"json",
url: myAjax.ajaxurl,
data: {action: 'submit_data', info: info},
success: function(data) {
if(data.responseType == 'success') {
// success
}
if(data.responseType == 'failure') {
// failure
}
}
});
$(":input").val('');
return false;
Is our approach is the correct or wrong approach ??
Basically every response will be success and show error message based on the response type
Please advise. We need to follow the best practice
data. responseType doesn't return a 'success' or 'failure'. It is contains an enumerated value which represents the type of response coming back to you like text, json, arrayBuffer etc..
Hence in the second code block both if statements will be exceuted to be false and nothing will be done with the response received.
I think you should go with the first approach because
Whether you are using raw JS or a library to implement this functionality, you'll have access to the state of the request i.e. whether the request was successful; met with an error and finally whether it has been completed.
Make proper use of these events and their respective callbacks to manipulate the UI for a better user experience. For example, if the request was unsuccessful, you'd want to update the user interface to reflect that their changes weren't successful while if it was successful, you'd want to tell them so. Don't keep the user waiting!
With jQuery, you'd make use of the success and error callbacks. You also get other callbacks such as complete and beforeSend to be invoked for apporopriate use.
$.ajax({
//Other code
success: function(msg)
{
// Update the UI here to reflect that the request was successful.
doSomethingClever();
},
error: function(msg)
{
// Update the UI here to reflect that the request was unsuccessful
doSomethingMoreClever();
},
complete: function(msg)
{
// Update the UI here to reflect completion
doSomethingEvenMoreClever();
}
});
take a look at this

Custom error message with content-type response

I'm trying to implement some error handling into my MCV AngularJS application, but came across this one issue that I'm not sure how to solve.
Structure
In my AngularJS service ticketService I have the following method:
this.downloadFile = function (fileId) {
return $http.get(baseUrl + "/Downloadfile/" + fileId, { responseType: "blob" });
}
And in my controller:
$scope.downloadFile = function (fileId) {
ticketService.downloadFile(fileId)
.then(function (response) {
// Handle correct request and response
}, function (err) {
// Handle error
notify({ message: "Something went wrong: " + err.data.Message, position: "center", duration: 10000 });
})
}
Here's what I return from the backend MVC Web API method:
var error = new HttpError("Failed to find file, bla bla bla.");
return Request.CreateResponse(HttpStatusCode.NotFound, error);
Problem
My issue is that since my responseType is set to be blob, my err object is the same response type. I would believe that it should be possible for my backend service to override this response type, and respond with an object that contains some Message.
From this response, I would've thought that I could get err.data.Message, but perhaps I misunderstood this scenario?
Thank you in advance.
public HttpResponseMessage Get(int id)
{
try
{
return Request.CreateResponse(HttpStatusCode.OK, new { Status =
"OK", Message = this._myContext.GetCustomer(id) });
}
catch(Exception e)
{
return Request.CreateResponse(HttpStatusCode.Conflict, new {
Status = "NO", Message = e.ToString() });
}
}
You can return any message like "Failed to find file, bla bla bla." in Message. Then you just need to check in ajax success method like data.Message,
The $http service uses the XHR API which is not capable of changing the responseType on the fly.
You can set the status message and use that:
public ActionResult Foo()
{
Response.StatusCode = 403;
Response.StatusDescription = "Some custom message";
return View(); // or Content(), Json(), etc
}
Then in AngularJS:
$scope.downloadFile = function (fileId) {
return ticketService.downloadFile(fileId)
.then(function (response) {
// Handle correct request and response
return response.data;
}).catch(function (response) {
// Handle error
console.log(response.status);
console.log(response.statusText);
throw response;
});
};
Alternative approaches are:
Use the Fetch API which has a more powerful and flexible feature set.
Use the FileReader API and JSONparse() method to convert the Blob to a JavaScript Object.

Backbone.js save always triggers error even on success

I've read several of the other posts about this problem and none of the solutions seem to be working for me. I have the following code in my View:
this.model.set({
username: $('#user-username').val(),
role: $('#user-role').val(),
description: $('#user-description').val()
});
this.model.save({ user_id: this.model.get('user_id')}, {
success: function(user, response) {
console.log('success:', response);
$('.flash-message').text("Success").show();
},
error: function(user, response) {
console.log('error:', response);
$('.flash-message').text(response.error).show();
}
});
and this on my server controller (nodejs running express 3):
UserController.prototype.updateAction = function(req, res) {
if (req.route.method != "put") {
res.send({status: "error", error: "update must be put action and must include values"});
return false;
}
var query = {'user_id': req.params.id};
var user = req.body;
var userRepository = this.userRepository
// delete _id to avoid errors
delete user._id;
userRepository.update(query, user, {}, function(err, updated) {
if ((err) || (!updated)) {
res.send({"status": "error", "error": err});
return false;
}
// send updated user back
util.log('updated user ' + user.user_id);
res.setHeader('Content-Type', 'application/json');
res.status(200);
res.send(JSON.stringify({"status": "success", "updated": updated}));
});
}
On save, my model is saved correctly in the server and I have verified the server response with this. So, as far as I can tell the server is returning status 200, valid JSON, with a valid JSON response header. And yet my backbone model.save function always triggers the error callback. Can anyone please tell me why and how to resolve this?
I am able to get this to work if set the dataType to text like so:
this.model.save({ user_id: this.model.get('user_id')}, {
dataType: "text",
success: function(user, response) {
console.log('success:', response);
$('.flash-message').text("Success").show();
},
error: function(user, response) {
console.log('error:', response);
$('.flash-message').text(response.error).show();
}
});
but doing so does not allow me to get the response back from the server. Instead I get this in the response var:
success: {
"_id": "5133b02062e15ed1d2000001",
}
Backbone expects to get back the model that it sent in its PUT or POST request body.
Instead of:
res.send(JSON.stringify({"status": "success", "updated": updated}));
Try this in your server's response:
res.json(user);
There may be a possibility that your call may have got in state 200 connection established which backbone detects as error, Backbone throws success only when the call is 200OK.
What's your server code? You need to make sure you're sending json back to backbone like so:
//In your express POST route
user.save(function(err) {
if(err){
console.log(err);
return res.json(401);
} else {
console.log('user: ' +user.username + ' saved');
return res.json(200);
}
Then in your backbone view you can check for the response and do what you need:
//some function in your view
this.model.save(this.formValues, {
success: function(model, response, options) {
if (response == 200) {
console.log('success :' + response);
//Do stuff
} else {
console.log('error: '+response);
//etc.
Also note that as per the backbone model documentation:
"save accepts success and error callbacks in the options hash, which will be passed the arguments (model, response, options)"

ExstJs Store callback proper error handling

I want to receive a personalized error message when trying to load a store and my connection times out or the DB it's not accessible ... when I do an Ajax Request is very easy because I get "response" as a parameter either in success or failure ...
Ext.Ajax.request({
url: 'ajax_demo/sample.json',
success: function(response, opts) {
var obj = Ext.decode(response.responseText);
console.dir(obj);
},
failure: function(response, opts) {
console.log('server-side failure with status code ' + response.status);
}
});
But I'm facing problems to do the same when trying to load a store, I've defined a callback function but I only receive records, operation and success.
store.load({
callback : function(records, options, success) {
if (!success) {
// what can I do here to show personalized error sent from server
}
}
});
So, what is the proper way to handle a response like this to show it to the user?
{"success": false, "msg": "SomeExceptionFromServer"}
Best regards
When success is false operation never gets a response property instead it gets a getError method, but you should define a messageProperty in the proxyReader in order to work.
Example:
Ext.define("SC.store.SegurosCancelacionStore", {
extend: "Ext.data.Store",
model: "SC.model.PersonaSeguro",
proxy: {
timeout: 90000,
actionMethods: {
read : 'POST'
},
type: "ajax",
url: "../SegurosFinsolCancelacionServlet",
reader: {
type: "json",
root: "seguros",
messageProperty : 'msjError' //without this, it doesn't work
}
},
autoLoad: false
});
Implementation:
storeSegurosCancelacion.load({
params: {
'sucursal':sucursal,
'persona': persona
},
callback:function(records, operation, success){
msg.hide();
if(success == true){
if(records.length == 0){
Ext.Msg.alert('Resultado', 'No se ha encontrado información');
}
}
if(success == false){
try{
Ext.Msg.alert('Error', operation.getError()); // way more elegant than ussing rawData etc ...
}catch(e){
Ext.Msg.alert('Error', 'Error inesperado en el servidor.');
}
}
}
});
Best regards
store.load({
callback : function(records, operation, success) {
console.log(operation.getResponse().msg);//this does the trick
}
});
If there is an error that you want to send, why not pass an empty data property along with the error message? So there are no records to load, but you get the message.
{
"success": false,
"msg": "SomeExceptionFromServer",
"data": {}
}
You might have to change data to your data property name.

Show json returned message in a div after each ajax response , extjs4 grid

I have a gridpanel , a Model, an autosync Store with an ajax proxy with read and update functions and a RowEditing plugin in extjs4 .
Consider the following json:
{ "success": true,"Message":"Grid Data Successfully updated.", "users": {"uname":"jdoe","fname":"John","lname":"Doe","SSN":125874,"mail":"jdoe#example.org"},{"uname":"jsmith","fname":"Jack","lname":"Smith","SSN":987456,"mail":"smith#example.com"}}
I want to know if there is a way to render the value of "Message" to an HTML div tag (my_div for example) after receiving each response?
You can use the DOM Helper, see the sencha api : http://docs.sencha.com/ext-js/4-0/#!/api/Ext.DomHelper
Ext.onReady(function(){
Ext.DomHelper.insertHtml('beforeBegin', Ext.getDom('test'), "Prepend this string");
});​
Above code will get the HTML element with ID test and it will insert the string Prepend this string beforeBegin of the content of this div.
See the fiddle to play around: http://jsfiddle.net/PddU4/Prepend this string
EDIT 2012-02-16:
You need to listen to your proxies success and failure: (you could also implement a listener when loading your store or on update)
listeners: {
success: function( response, options ){
console.log(response);
},
failure: function( response, options ){
console.log(response);
},
}
EDIT BASED ON YOUR COMMENT:
First make sure you configured properly your successProperty and messageProperty in your reader. Then implement the listener where you want it to be, update, remove, add, exception etc. :
(configure the listener within your proxy object)
listeners : {
update : function(thisStore, record, operation ) {
console.log('Update happened');
console.log(record);
console.log(operation);
},
save : function() {
console.log('Save happened');
},
exception : function(dataproxy, type, action, options,response, arg) {
console.log('Error happened');
console.log(response);
doJSON(result.responseText);
},
remove : function() {
console.log("Record removed");
}
}
When you console.log(response), you will see the response object. This would be your actual JSON so you need to parse it (as in doJSON() method):
function doJSON(stringData) {
try {
var jsonData = Ext.util.JSON.decode(stringData);
Ext.MessageBox.alert('Success', 'Your server msg:<br />jsonData.date = ' + jsonData.message);
}
catch (err) {
Ext.MessageBox.alert('ERROR', 'Could not decode ' + stringData);
}
}
Please check out this AJAX tutorial: http://www.sencha.com/learn/legacy/Manual:Core:Ext.Ajax

Resources