I am trying to add authentication to my mobile app, built using Angular and Breeze.
In my app.js:
app.config(function ($httpProvider) {
$httpProvider.interceptors.push(intercept)
});
//intercept runs on every http request and response
//When there is a 401 error it uses broadcast to send an event to
//the application scope
function intercept($rootScope) {
return {
request: function (config) {
$rootScope.$broadcast('loading:show');
return config;
},
response: function (response) {
$rootScope.$broadcast('loading:hide');
return response;
},
responseError: function (error) {
if (error.status === 401) {
$rootScope.$broadcast('error:401');
}
return error;
}
}
}
app.run(function ($rootScope, $ionicLoading, $state) {
$rootScope.$on('loading:show', function () {
$ionicLoading.show({ template: 'Loading...' });
});
$rootScope.$on('loading:hide', function () {
$ionicLoading.hide();
});
//401 errors mean the user is not authenticated
//display a login dialog
$rootScope.$on('error:401', function () {
$ionicModal
.fromTemplateUrl("app/user/login.html", { focusFirstInput: true })
.then(function (modal) {
modal.show();
});
});
});
And in my dataContext.js:
var properties = [];
function getProperties(refresh) {
if (!refresh && properties.length > 0) {
return common.$q.when(properties);
}
var query = EntityQuery
.from('Properties')
.select('ID, NameNumber, StreetName, ...etc')
.orderBy('StreetName, NameNumber')
.toType("Property")
.using(manager)
.execute()
.then(querySucceeded, queryFailed);
return query;
function querySucceeded(data) {
//set the properties held in memory
properties = map(data.results);
return properties;
}
function queryFailed(error) {
console.log("Error while making http call: " + error.message);
//return the properties held in memory
return properties;
}
}
The logic goes like this:
getProperties()
calledEntityQuery
triggers request to http://.../breeze/breeze/Metadata"Response is 401 (user not authenticated) - as expected
'error:401' event is broadcast and handled and login screen is displayed
This all works fairly well.
Now, if I cancel my login dialog, then refresh, that triggers getProperties
again, but this time I get this error reported in my queryFailed
function:
cannot execute _executeQueryCore until metadataStore is populated
So I guess that Breeze knows that a call was made previously and therefore expects it to be there, even though it failed with a 401. What can I do to get around this problem?
After trying many other things, I finally realised that I needed to resolve the
responseError
with a rejection. Otherwise (I guess) Breeze believes that the MetaData call was successful, and subsequently tries to access it, then generates the error when it is unsuccessful: