AngularJS $Http not triggered on Edge/IE - angularjs

I have the following code, which works perfectly fine on Mozilla, Chrome, but not on Microsoft Edge or Internet Explorer. Here is what happens.
When user loads a webpage I trigger the following code:
$http.get("/api/items")
.then(function (response) {
angular.copy(response.data, $scope.items);
}, function (error) {
$scope.errorMessage = error.statusText;
})
.finally(function () {
$scope.isBusy = false;
});
which pulls all the values into the <ul>. This part works normally on all browsers. However when I trigger the following one:
$scope.interval = $interval(function () {
$http.get("/api/items")
.then(function (response) {
//success
//loop through the response
angular.forEach(response.data, function (value, key) { ... more code here}
then suddenly the response is no longer from my web api. What I mean is, that when I was debugging my application and placed breakpoint in my GET api (I mean under Visual Studio in my MVC Controller) I could not see the get call being triggered from Microsoft Edge.
Here is what network inspector looks like from Chrome:
and this one is from Edge:
As far as I understand, Edge has only made one real XHR call towards my GET, and all the remaining ones are just cached from memory?
How can one solve this problem? Why is this even happening?

In the end I found out, that the problem is with Angular with storing Cache. There are two options one can use (taken from other StackOverflow posts):
1) Angular Method (which for unknown reason did not work for me):
myModule.config(['$httpProvider', function($httpProvider) {
//initialize get if not there
if (!$httpProvider.defaults.headers.get) {
$httpProvider.defaults.headers.get = {};
}
// Answer edited to include suggestions from comments
// because previous version of code introduced browser-related errors
//disable IE ajax request caching
$httpProvider.defaults.headers.get['If-Modified-Since'] = 'Mon, 26 Jul 1997 05:00:00 GMT';
// extra
$httpProvider.defaults.headers.get['Cache-Control'] = 'no-cache';
$httpProvider.defaults.headers.get['Pragma'] = 'no-cache';
}]);
2) The ASP.NET way of decorating GET method:
[ResponseCache(NoStore = true, Duration = 0)]

Related

how to write get method using ng resource

hi in my requirement i tried to write post method using ngresource but now i want to change that into get method. can anyone help me to solve this problem. i am new to angularjs thanks in advance
$scope.clickresult = {};
var Call = $resource('../api/Home', {}, { query: { method: 'POST', isArray: true} });
$scope.click = function () {
//alert("hi");
$scope.selected = "";
var x = $('#txtSearch').val();
var _ReqObj = new Object();
_ReqObj.id = x;
_ReqObj.Meth = "CD";
// alert(x);
Call.query({}, _ReqObj,
function (response) {
if (response == '') {
// alert('no data');
window.location.replace("#/");
}
else {
//alert("daata");
$scope.message = response;
}
},
function (error) {
window.location.replace("#/");
}
);
};
Here is some initial help so you can solve your future problems on your own.
1. Use developer tools to see errors, requests and responses: https://developers.google.com/web/tools/chrome-devtools/
Open the tools from the menu or use cmd+alt+I on Mac or ctrl+shift+I on Windows.
In the "Network" tab of the developer tools you can see the communication with your server (E.g. request method = GET, response from the server). In the "Preview" tab you can see the json the server sent you. Tell me if you have problems finding this, because it is very important to find bugs in your code.
2. Use logging!
In angular you can add $log to your code and with $log.log("message", object) you can output debug messages and the current state of objects from your code. You can see the logging messages in the developer tools in the "Console" tab.
3. Read the documentation
Angular provides documentation and examples for their functions. Read this about the $resource service https://docs.angularjs.org/api/ngResource/service/$resource
Read about the difference between GET and POST method.
4. Try a simple example from a tutorial and try to adapt it to your needs
Copy a simple resource example from the internet and make it work. If that works change it step by step until it is what you need.
5. For your example:
How does your server side script work? In your question I can only see the angular code. If you want to use the GET method the server has to provide a function that reacts to GET.
The $resource service already provides a query method:
{ 'get': {method:'GET'},
'save': {method:'POST'},
'query': {method:'GET', isArray:true},
'remove': {method:'DELETE'},
'delete': {method:'DELETE'} };
Normally you don't need to add "{ query: { method: 'POST', isArray: true}" to your code. The query function is already there!
To send a GET request with the query function you just need:
var Call = $resource('../api/Home', {});
Now open your developer tools, go to the Network tab and then execute the function $scope.click in your website. What do you see in the Network tab? The request should be fired with "request method: GET". What is the answer from the server? The problem is maybe not in your angular code but in your server code.
Try these things and tell me if you need more help.

PUT and POST Angularjs

I have an Ionic project with a WCF RESTful service, I want to be able to Insert and Update data. I can already view data with GET method but can't find anything on the internet for PUT and POST. How would I be able to accomplish this?
GET Method
$scope.selectedDist= function() {
$http.get("http://192.168.1.113/Service1.svc/GetAllComp")
.success(function(data) {
var obj = data;
var ar = [];
angular.forEach(obj, function(index, element) {
angular.forEach(index, function(indexN, elementN) {
ar.push({CompID: indexN.CompID, CompName: indexN.CompName});
$scope.districts = ar;
});
});
})
.error(function(data) {
console.log("failure");})
};
Post methods I tried
#1
$scope.insertdata = function() {
var ar = [{'M1':$scope.M1, 'M2':$scope.M2,'M3':$scope.M3,'M4':$scope.M4,'M5':$scope.M5,'M6':$scope.M6,'M7':$scope.M7,'M8':$scope.M8,'M9':$scope.M9,'M10':$scope.M10,}]
$http.post("http://192.168.1.113/Service1.svc/GetAllComp", ar)
.success(function(data)
{
console.log("data inserted successfully")
})
.error(function(data)
{
console.log("Error")
})
#2
$scope.insertdata = function() {
var ar = [{'M1':$scope.M1, 'M2':$scope.M2,'M3':$scope.M3,'M4':$scope.M4,'M5':$scope.M5,'M6':$scope.M6,'M7':$scope.M7,'M8':$scope.M8,'M9':$scope.M9,'M10':$scope.M10,}]
$http ({
url : "localhost:15021/Service1.svc/TruckDetails" ,
Method : "POST" ,
headers : {
'Content-Type' : 'Application / json; charset = utf-8'
},
Data : ar
})
Also Would I need to make a POST or PUT method on my Service as well or can I use the GET methods?
You can use a get method, in combination with a querystring to post and put data but that is not what it was designed for and should be avoided for several reasons such as security.
That being said, it is not that difficult to use post and put in angular and in the following , rather naive service , you can see all that is required to do is passing your data in the service function you're invoking.
.service('MyService', function($http) {
this.postMethod = function(data) {
return $http.post('http://my.url', data);
};
this.putMethod = function(id, data) {
return $http.put('http://my.url/' + id, data);
};
}
So that in your controller you can inject and invoke the service methods with the $scope data that needs to be stored.
After taking a look at your attempts you seem to be using the same url for both get and post: "http://192.168.1.113/Service1.svc/GetAllComp" which actually leads me to believe you haven't thought about implementing these methods on your server. Can you confirm this?
Apart from that, it is always usefull to look at statuscodes when trying to send requests because they provide a great deal of information about the nature of the error that occurs. You can investigate that in either your console or an external program such as Fiddler.
P.S.
Deprecation Notice The $http legacy promise methods success and error
have been deprecated. Use the standard then method instead. If
$httpProvider.useLegacyPromiseExtensions is set to false then these
methods will throw $http/legacy error.

AngularJS $broadcast $on doesn't work at first time - intermittent issue

There is a strange behaviour in my AngularJS application. The use case it to create a user at "usercreate.html" and after successfully creating (over Backend REST- Service -> HTTP POST) a redirect to "usercreateresponse.html" is made.
I have two controllers:
usercreate.html -> CreateUserController
usercreateresponse.html -> CreateUserResponseController
and I share the data between CreateUserController and CreateUserResponseController over $rootScope.$broadcast and $rootScope.$on.
My problem now is, that when I have changed something in the code (AngularJS code) and I refresh the browser page and afterwards I will create a user, the user creation works fine and I am also redirected to usercreateresponse.html but no values are shown -> but this is only the first time -> if i navigate back to usercreate.html and create a user once again everything works fine.
I found out that in case if it is not working, a HTTP GET is made to get the HTML- Code from the back end. In case it works than only HTTP POST is made an everything works fine.
Does anybody know how to prevent the first user creation -> redirect problem?
Here the controller/services:
function CreateUserController($scope, CreateUserService) {
$scope.createUser = function(data) {
CreateUserService.createUser($scope.usernameCreate, $scope.passwordCreate, $scope.role);
}
}
services.factory('CreateUserService', function($rootScope, $location, $http) {
...
var res = $http.post('/users/createUser', dataObj);
res.success(function(data, status, headers, config) {
$rootScope.$broadcast('handleCreatedUser', {usernameCreate: data.username, passwordCreate: data.password, role: data.roles});
$location.path("usercreateresponse");
});
res.error(function(data, status, headers, config) {
...
});
}
return sharedCreateUserService;
});
function CreateUserResponseController($rootScope) {
$rootScope.$on('handleCreatedUser', function(event, args) {
$rootScope.usernameCreated = args.usernameCreate;
$rootScope.passwordCreated = args.passwordCreate;
$rootScope.role = args.role[0];
});
}
Instead of a broadcast, you can use a service which will store the response of the Creation of user. Then you can share it using the service with the CreateUserResponseController. With broadcast event, what might be happening is, you are broadcasting an event before the controller which handles it is instantiated. So, the $on may not have registered till then. And hence the issue you face.

angularjs $http post not working with Chrome browser

I'm trying to post an object to my rest service using angularjs.
Unfortunately it isn't working with Google's Chrome browser. Firefox and Internet Explorer work perfectly fine!
Does anyone have an idea what could be the problem?
Heres my Frontend -call:
$scope.saveAssignment = function (cap, aId, wId, hId) {
//all the parameters are strings
var postData = {
assignmentId: aId,
status: "CLOSED",
startDate: new Date(),
endDate: new Date(),
captionText: cap,
workerId: wId,
segment_Id: hId
};
var header ={
'Content-Type': 'application/json; charset=utf-8'
};
$http.post("https://localhost:8443/rest/v1/saveAssignment", postData, header)
.success(function (data, status, headers, config) {
console.log("IN SAVE ASSIGNMENTS - SUCCESS");
console.log(status);
})
.error(function (data, status, headers, config) {
console.log("ERROR!");
//As a response I get data = '' and status = 0
})
}
I have the same problem if I deploy it (independent of localhost or not).
On the server-side (JPA), I'm accepting the call with:
#Path("saveAssignment")
public class SaveAssignment{
#POST
#Consumes(MediaType.APPLICATION_JSON)
public Response saveAss(String assJson) {
System.out.println("TEST");
......
......
}
But not even the print statement "TEST" gets executed...
UPDATE
It looks like it has to be a CORS issue...
Chrome is only sending an OPTION request instead of an POST...
Idea how to fix this?
I already tried
$httpProvider.defaults.useXDomain = true;
delete $httpProvider.defaults.headers.common['X-Requested-With'];
but without succes... :(
UPDATE 2
Unfortunately I still don't manage to get it working. So I did a workaround by consciously excluding users with a Chrome browser from doing this post on my page (i.e. seeing the entire page)... (I used it for Amazon's Mechanical Turk, so it's not that severe). But it's not a solution for the origin problem... :-(
To exclude users with Google's Chrome browser I added the following:
$scope.chrome;
$scope.setIsChrome = function(){
var chromium = window.chrome;
var vendorName = window.navigator.vendor;
if(chromium !== null && vendorName === "Google Inc.") {
$scope.chrome = true;
} else {
$scope.chrome = false;
}
}
You have to check additionaly for the vendor name, since the Opera browser return true for "window.chrome" as well...
Is your angular app served via same HTTPS server? If localhost:8433 has self-signed or not matching certificate then that may be your problem as Chrome usually displays security exception page in such case.
Just open any URL starting with https://localhost:8443/ as normal page an then confirm security exceptions. That should help.
Update:
If you use iframe then the embedded page may be restricted by sandbox: http://msdn.microsoft.com/en-us/hh563496.aspx

angularjs not caching resource data . ( even after using cacheFactory )

I am trying to cache the response with angularjs but its not happening .
code #1
var app = angular.module("jsonService", ["ngResource"]);
app.factory("JsonFactory", function($resource,$cacheFactory) {
var cache = $cacheFactory('JsonFactory');
var url = "myurl?domain=:tabUrl";
var data = cache.get(url);
if (data==undefined) {
var retObj = $resource(url, {}, {
list: {
method: "GET",
cache: true
}
});
data = retObj;
cache.put(url, data);
};
return cache.get(url);
});
code #2
var app = angular.module("jsonService", ["ngResource"]);
app.factory("JsonFactory", function($resource) {
var url = "myurl?domain=:tabUrl";
console.log(url);
var retObj = $resource(url, {}, {
list: {
method: "GET",
cache: true
}
});
return retObj;
});
after both the code i wrote . when looking in to dev tools there always goes a XHR request in Network tab.
obviously : date does not changes . ( that's the whole point of caching )
After reading some of your responses, I think that what you are asking, is why does the network tab show a 200 response from your server, while using angular caching.
There are two caches. The first cache is angular's cache. If you see an xhr request in the network tab at all, then that means angular has decided that the url does not exist in its cache, and has asked the browser for a copy of the resource. Furthermore, the browser has looked in it's own cache, and decided that the file in its cache does not exist, or is too old.
Angular's cache is not an offline cache. Every time you refresh the browser page, angular's caching mechanism is reset to empty.
Once you see a request in the network tab, angular has no say in the server response at all. If you're looking for a 304 response from the server, and the server is not providing one, then the problem exists within the server and browser communication, not the client javascript framework.
A 304 response means that the browser has found an old file in its cache and would like the server to validate it. The browser has provided a date, or an etag, and the server has validated the information provided as still valid.
A 200 response means that either the client did not provide any information for the server to validate, or that the information provided has failed validation.
Also, if you use the refresh button in the browser, the browser will send information to the server that is guaranteed to fail (max-age=0), so you will always get a 200 response on a page refresh.
According to the documentation for the version of angular that you are using, ngResource does not support caching yet.
http://code.angularjs.org/1.0.8/docs/api/ngResource.$resource
If you are unable to upgrade your angular version, you may have luck configuring the http service manually before you use $resource.
I'm not exactly sure of syntax, but something like this:
yourModule.run(function($http)
{
$http.cache=true;
});
$cacheFactory can help you cache the response. Try to implement the "JsonFactory" this way:
app.factory("JsonFactory",function($resource,$cacheFactory){
$cacheFactory("JsonFactory");
var url="myurl?domain=:tabUrl";
return{
getResponse:function(tabUrl){
var retObj=$resource(url,{},{list:{method:"GET",cache:true}});
var response=cache.get(tabUrl);
//if response is not cached
if(!response){
//send GET request to fetch response
response=retObj.list({tabUrl:tabUrl});
//add response to cache
cache.put(tabUrl,response);
}
return cache.get(tabUrl);
}
};
});
And use this service in controller:
app.controller("myCtrl",function($scope,$location,JsonFactory){
$scope.clickCount=0;
$scope.jsonpTest = function(){
$scope.result = JsonFactory.getResponse("myTab");
$scope.clickCount++;
}
});
HTML:
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.0.8/angular.min.js"></script>
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.0.8/angular-resource.js"></script>
<script src="js/ngResource.js"></script>
<body ng-app="app">
<div ng-controller="myCtrl">
<div>Clicked: {{clickCount}}</div>
<div>Response: {{result}}</div>
<input type="button" ng-click="jsonpTest()" value="JSONP"/>
</div>
</body>
Screenshot:
[EDIT] for html5 localStorage solution
JSBin Demo
.factory("JsonFactory",function($resource){
var url="ur/URL/:tabUrl";
var liveTime=60*1000; //1 min
var response = "";
return{
getResponse:function(tabUrl){
var retObj=$resource(url,{},{list:{method:"GET",cache:true}});
if(('localStorage' in window) && window.localStorage !== null){
//no cached data
if(!localStorage[tabUrl] || new Date().getTime()>localStorage[tabUrl+"_expires"]) {
console.log("no cache");
//send GET request to fetch response
response=retObj.list({tabUrl:tabUrl});
//add response to cache
localStorage[tabUrl] = response;
localStorage[tabUrl+"_expires"] = new Date().getTime()+liveTime;
}
//console.log(localStorage.tabUrl.expires+"..."+new Date().getTime());
return localStorage[tabUrl];
}
//client doesn't support local cache, send request to fetch response
response=retObj.list({tabUrl:tabUrl});
return response;
}
};
});
Hope this is helpful for you.

Resources