Angular - function in service not recognizing $resource - angularjs

I'm working with Angular factory and trying to make a webservice call, but looks like it is not recognizing $resource.
.factory('User', function($resource) {
function login() {
// THIS IS NOT WORKING, how do I make a webservice call from here?
$resource('/api/user.json', {}, {
method: 'POST',
isArray: false
});
return true;
}
function logout() {
return false;
}
return {
login : function() { return login(); },
logout: function() { return logout(); }
};
Thanks,
Tee

i assume you have the resource module file somewhere :
https://raw.github.com/angular/angular.js/master/src/ngResource/resource.js
you need to import the proper module in your app :
var App = angular.module("App",["ngResource"]);
then use it in a "sane" way :
var User = App.factory("User",function($resource){
var User = $resource('/api/user.json',{},{
login:{method:"POST",isArray:true},
logout:{method:"POST"}
});
return User;
// use User in your controller or another service.
});
the doc is here : http://docs.angularjs.org/api/ngResource.$resource

Related

Model passed to Web Api 2 method is null - AngualrJs

I'm calling a method inside my Web Api 2 controller, passing in a model called login which consists of EmailAddress and Password. However it hits the method but the model passed in is always null...
My call from AngularJs function :
var login = { "EmailAddress": emailAddress, "Password": password };
$http.post("/api/Login/", { headers: { 'RequestVerificationToken': $scope.antiForgeryToken } }, login).success(function () {
alert('succes');
}).error(function () {
alert('Unable to login at present, please try again later');
});
My method:
[ValidateAntiForgeryToken]
public void Post([FromBody]Login login)
{
var t = login.EmailAddress;
}
I think its something to do with how I've structure my actual Angular $http.post method but again I'm not sure, can anyone suggest would could potentially be wrong with it?
Can you use ajax and Razor?
var login = { "EmailAddress": emailAddress, "Password": password };
$.ajax({
url: "#Url.Action("api/login", "Controller", login)",
type: "GET",
data: {},
success: fCheckBoxes
});
Why cannot add the token to every request by configuring your app.js
// Set header for every request
app.factory('httpRequestInterceptor', function ($localStorage) {
return {
request: function (config) {
if ($localStorage.token != null)
config.headers['myAppToken'] = $localStorage.token;
return config;
}
};
});
app.config(function ($httpProvider) {
$httpProvider.interceptors.push('httpRequestInterceptor');
});

Injecting service with $http messes up controller

I made a service that's using $http to post login data and get authentication token, but whenever i inject it into the controller, it breaks (looks like html doesnt see it). When I remove the service injection, or inject one using $resource instead, everything works fine.
Here's the code for the service:
MyApp.service('LoginSrv', ['$http', function User($http) {
var userData = {
isAuthenticated: false,
username: '',
bearerToken: '',
expirationDate: null,
};
function setHttpAuthHeader() {
$http.defaults.headers.common.Authorization = 'Bearer ' + userData.bearerToken;
}
this.getUserData = function(){
return userData;
};
this.authenticate = function(username, password, successCallback, errorCallback) {
var config = {
method: 'POST',
url: '/accounts/login',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
},
data: 'grant_type=password&username=' + username + '&password=' + password,
};
$http(config)
.success(function(data) {
userData.isAuthenticated = true;
userData.username = data.userName;
userData.bearerToken = data.access_token;
userData.expirationDate = new Date(data['.expires']);
setHttpAuthHeader();
if (typeof successCallback === 'function') {
successCallback();
}
})
.error(function(data) {
if (typeof errorCallback === 'function') {
if (data.error_description) {
errorCallback(data.error_description);
} else {
errorCallback('Unable to contact server; please, try again later.');
}
}
});
};
}]);
And here is the controller code:
MyApp.controller('mainCtrl', function ($scope, LoginSrv)
{
$scope.loginUsername = 'Jan';
$scope.loginPassword = 'Maria';
$scope.userLogin = new LoginSrv();
$scope.loginError = false;
function onSuccesfulLogin () {};
function onFailedLogin(error) {};
$scope.login = function () {
userLogin.authenticate($scope.loginUsername, $scope.loginPassword, onSuccesfulLogin, onFailedLogin);
};
});
Services are singleton so you need not give a "new",
I Made a brief example of the same flow you need and worked well, I hope to help:
The Service
angular.module("yourapp").factory('LoginSrv', function User($http) {
var _authenticate = function(username, password) {
console.log('logged')
};
return {
authenticate: _authenticate
};
});
The Controller
angular.module("yourapp").controller('mainCtrl', function ($scope, $http, LoginSrv)
{
$scope.loginUsername = 'Jan';
$scope.loginPassword = 'Maria';
$scope.userLogin = LoginSrv;
$scope.loginError = false;
$scope.login = function () {
userLogin.authenticate($scope.loginUsername, $scope.loginPassword);
};
});
The other answer does a good job of explaining your LoginSrv related exception and explains how implement a service/factory. However what it fails to note is the differences between the two.
Factory
When injecting a factory you will be provided with the return value as a result of invoking the factory function.
Service
When injecting a service you will be provided with an instance of the service function. That is akin to new serviceFunction();. It is important to note angular will do this the first time the service is injected, all others times it is injected you will receive the same instance.
So Factories are meant for object creation (hence the name) and services are meant, well, for services. So shared logic.
So in my opinion (that's all it is) your existing service is trying to do both. You appear to have a user object that your wanting to create but also methods for authenticating a user. It would be best to put that user object in a factory which returns a create method to create a new user. Then put the authentication logic in a service. Then your authentication is not directly coupled to your user implementation.
Possible Implementation (pseudo code)
.factory('userFactory', function () {
return {
create: function (details) {
return Object.create({}, {
username: {
value: details.username
},
password: {
value: details.password
},
isAuthenticated: {
value: false
}
});
}
}
});
.service('auth', function ($http) {
this.authenticate = function (username, password) {
//Build config
return $http();
}
});
.controller('test', function ($scope, userFactory, auth) {
var user = userFactory.create({
username: 'hiya',
password: 'epic secrets'
});
auth.authenticate(user.username, user.password)
.then(function (d) {
user.isAuthenticated = d.isAuthenticated;
})
.catch(SomeGenericErrorHandler);
});
any questions just ask

incercept $http request to modify api call urls

var app = angular.module('app');
// register the interceptor as a service
app.factory('myHttpInterceptor', function($q ) {
return {
'request': function(config) {
return config;
}
};
});
I am trying to modify the urls of api calls and append the api url to the start of the ajax calls in the interceptor insted of each service function like
function getAssesmentResults(params) {
return $http.get(url.api + '/results', {params: params})
.then(function(response) {
return response.data;
});
}
However the interceptor intercepts all http requests like .css or .html or .json files. What is a good way to modify the urls in the interceptor without modifying other http requests?
$http has a facility to intercept and rewrite URLs that is configured on the $httpProvider. When I run in production, I have an extra token: '/rest/' compared with development mode and I detect production mode ( prefix packing ) in the interceptor. This is in my app.js
var rest_srvr = 'http://dev-pc.example.com:8000'
app.factory('REST_Interceptor',[
'$location',
function($location) {
var request = function(config) {
if (RegExp('packing','i').test(window.location.host)) {
return config
}
var rest_request_regex = new RegExp('^.*?/rest/(.*)$')
//console.log('config.url=%s',config.url)
config.url = config.url.replace(rest_request_regex,rest_srvr+'/$1')
var files_request_regex = new RegExp('^/(files/(.*))$')
config.url = config.url.replace(files_request_regex,rest_srvr+'/$1')
//console.log(' is now config.url=%s',config.url)
return config
}
var translate_subpath = function(subpath) {
return request({url:'https://'+$location.host()+subpath}).url
}
return {
request: request,
translate_subpath: translate_subpath
}
}])
app.config([
'$httpProvider','$cookiesProvider',
function($httpProvider, $cookiesProvider) {
if (!RegExp('packing','i').test(window.location.host)) {
$httpProvider.interceptors.push('REST_Interceptor')
}
}])
I would create a service that wraps the $http. Then in your code you'll always call this wrap instead of $http and will be able to do whatever you want with the request before it is sent. Just a simple example:
module.factory('myHttp', function($http){
return {
get: function(url, params){
var newUrl = "base-api-url/" + url;
return $http.get(newUrl, params);
}
}
})
Use the generic service for this:
Generic service
appCless.factory("$comum", function($http, $q, $injector) {
function ajax(url, parametros, metodo) {
var requisicao = $http({
method: metodo,
url: url,
data:parametros
});
var promessa = requisicao.then(
function(resposta) {
return(resposta.data);
},
function(resposta) {
return($q.reject("Something went wrong"));
}
);
return promessa;
}
return({
ajax:ajax
});
});
Service
app.factory("$categoriaproduto", function($comum) {
var categoria;
return {
buscar : function(neoId) {
var promessa = $comum.ajax("/fusion/services/roi/category/product/search", "", "POST");
promessa.then(function(req) {
categoria = req.data;
});
return promessa;
},
cache : function() {
return categoria;
}
};
});

POST to nested RESTful resources with $resource parameter mismatch - AngularJS

I'm trying to using the $resource library of angular, to POST data to a nested resource.
My following nested resource of event looks like so
events/:eventId/match - POST
events/:eventId/match - GET
events/:eventId/match/:matchId - GET
I set up a service with angular
app.factory('EventService', ['$resource', function ($resource) {
var Event = $resource('/events/:eventId', {eventId: '#id'},
{
createMatches: {
url: '/events/:eventId/match',
method: 'POST'
}
);
return {
createMatches: function(data,event_id) {
var data.eventId = event_id;
return Event.createMatches(data).$promise;
}
}
});
Controller where it has been called:
app.controller('EventController', ['$scope','EventService', function($scope,EventService) {
$scope.create = function(event_id,title,description) {
EventService.createMatches({
title:title,
description: description
},event_id).then(function(result) {
console.log('event_created', result);
})
}
}]);
Problem
When I send the request to the server I expect the url that looks like so: /events/10/match
But instead the resource doesn't add the eventId as a parameter of the url but add it as a parameter of the request, for this reason my call fail because the url looks like so: /events/match.
I can't understand why it doesn't bind the :eventId to the url. Any suggest will be appreciated.
I believe that you are missing your second parameter decalaration, as per this link for the actions you are defining:
app.factory('EventService', ['$resource', function ($resource) {
var Event = $resource('/events/:eventId', {eventId: '#id'},
{
createMatches: {
url: '/events/:eventId/match',
method: 'POST',
params: {eventId: '#id'}
}
);
return {
createMatches: function(data,event_id) {
var data.eventId = event_id;
return Event.createMatches(data).$promise;
}
}
});

Error when accessing a AngularJs service method which uses $resource

i'm new to angularjs and trying to access a service method which uses $resource to make a call to my rest api. But when i'm trying to access its giving a error. also when i try to access a method which does not use $resource it works fine.
here's my code.
app.factory('userService', ['$resource',
function($resource) {
var factory = {};
factory.authenticatedUser;
factory.test = function(){
return "Test";
};
factory.getLoggedInUser = function(){
$resource('api/user', {}, {
query: {method: 'GET'}
});
};
factory.getAuthenticatedUser = function(){
return factory.authenticatedUser;
};
factory.setAuthenticatedUser = function(user){
factory.authenticatedUser = user;
};
return factory;
}]);
here's how i'm trying to access the method.
userService.getLoggedInUser.query(function(loggedInUser) {
});
this throws the following error.
TypeError: userService.getLoggedInUser.query is not a function
but this works fine.
var text = userService.test();
What am i doing wrong here?
You need to add a $ sign. And return the $resource object from your function
factory.getLoggedInUser = function(){
return $resource('api/user', {}, {
query: {method: 'GET'}
});
};
userService.getLoggedInUser().$query(function(loggedInUser) {
});

Resources