Calling WCF service with json output from angularjs with windows authentication - asp.net

I've got a wcf Service which has a method which send its output in jsonformat. The service is hosted in an https-Environment.
i'm calling it with angularjs-resource:
var hrdemo = angular.module('hrdemo', ["ngResource"]);
hrdemo.controller('HrDemoCtrl', function ($scope, hrdbservice) {
$scope.items = hrdbservice.get({ 'Id': 1 });
var a = $scope.items.length;
});
hrdemo.factory('hrdbservice', function ($resource) {
return $resource('http://hrservice/HrService.svc/:Id', { Id: "#Id" }, { get: { method: 'JSONP' } });
});
Angularjs runs in an ASP.Net-Web Application.
When calling the Service I get something like an xhr-problem.
1) How can i authenticate with my Windows authentication over angularjs
2) What can I do to fix the xhr-problem?

May the withCredentials option is what you are searching for $http.post(url, {withCredentials: true, ...}). Also there is a specific shortcut for performing a JSONP request in AngularJS - $http.jsonp()
AngularJS Docs

Related

ajax call status is 200 but it is not successfull

I working on mvc asp.net project. I call my controller function with ajax, the call status is 200 but it is not successful, and goes to error section.
service:
public async Task<IEnumerable<TeamDto>> GetAllTeamsList()
{
var teams = await _teamRepository.GetAll().Include(u => u.Users).ThenInclude(m => m.User).ToListAsync();
return ObjectMapper.Map<IEnumerable<TeamDto>>(teams);
}
Controller:
public async Task<IEnumerable<TeamDto>> GetTeams()
{
var teams = await _teamAppService.GetAllTeamsList();
return teams;
}
js file:
$.ajax(
{
type: "GET",
url: "/App/Team/GetTeams",
success: function (data) {
///
},
error: function (data) { console.log("it went bad " + JSON.stringify(data)); }
});
Error:
TypeError: 'caller', 'callee', and 'arguments' properties may not be accessed on strict mode functions or the arguments objects for calls to them
this is what I get when copy the url in the browser:
{"result":[{"tenantId":1,"name":"admin
team","users":[{"tenantId":1,"userId":2,"teamId":58,"user":{"profilePictureId":null,"shouldChangePasswordOnNextLogin":false,"signInTokenExpireTimeUtc":null,"signInToken":null,"googleAuthenticatorKey":null,"pin":"1234","hourlyRate":0.00,"payrollId":"","warehouseId":1,"tandaUser":null,"normalizedUserName":"ADMIN","normalizedEmailAddress":"ADMIN#DEFAULTTENANT.COM","concurrencyStamp":"bd7ee91e-587b-4ae2-bc97-be2ce7d7789b","tokens":null,"deleterUser":null,"creatorUser":null,"lastModifierUser":null,"authenticationSource":null,"userName":"admin","tenantId":1,"emailAddress":"admin#defaulttenant.com","name":"admin","surname":"admin","fullName":"admin
admin","password":"AQAAAAEAACcQAAAAENfcSE+zBppFKVxKUynGBiy4WZgDU3C3gbbWnQUdEyBb5J/S0uLkcqk+2MwM0DXxjw==","emailConfirmationCode":null,"passwordResetCode":null,"lockoutEndDateUtc":null,"accessFailedCount":1,"isLockoutEnabled":true,"phoneNumber":"","isPhoneNumberConfirmed":false,"securityStamp":"07a4d582-7233-3fbc-f3f7-39f015ee388b","isTwoFactorEnabled":false,"logins":null,"roles":null,"claims":null,"permissions":null,"settings":null,"isEmailConfirmed":true,"isActive":true,"isDeleted":false,"deleterUserId":null,"deletionTime":null,"lastModificationTime":"2020-09-30T02:54:34.402372Z","lastModifierUserId":null,"creationTime":"2019-09-05T23:27:47.8514365Z","creatorUserId":null,"id":2},"team":{"tenantId":1,"name":"admin
team","users":[
Open up the developer tools and look at the URL it is trying to request. Normally in the context of the application, you don't have the /App defined. In fact, you can use ASP.NET MVC Url helper to get the action method, to make sure the path is correct:
$.ajax({
type: "GET",
url: "#Url.Action("GetTeams", "Team")",
Also, normally you would return data via JSON from the controller like:
public async Task<IEnumerable<TeamDto>> GetTeams()
{
var teams = await _teamAppService.GetAllTeamsList();
return Json(teams, JsonRequestBehavior.AllowGet);
}
And maybe that would make a difference, using Json() from the asp.net mvc controller. Note AllowGet ensures that GET requests on an action returning JSON works, otherwise it will be blocked and return an error.

Using DOJO with RESTful web services

I have built a RESTful web service using ASP.NET HttpHandler, when running the web service project im redirected to the default page from which I can choose to download the DOJO code for my Client app.
here is a code snippet from the downloaded file:
function PickrWebService(){ self = this; }
PickrWebService.prototype = {
self: null,
urlString: "http://AYMAN/Handler.ashx",
CreateUser:function(Email,Username,Password,FirstName,Surname,Birth,Gender,Mobile,Picture,Address,successFunction,failFunction,token) {
var data = { 'interface': 'PickrWebService', 'method': 'CreateUser', 'parameters': {'Email':Email,'Username':Username,'Password':Password,'FirstName':FirstName,'Surname':Surname,'Birth':Birth,'Gender':Gender,'Mobile':Mobile,'Picture':Picture,'Address':Address}, 'token': token };
var jsonData = dojo.toJson(data);
var xhrArgs = {
url: self.urlString,
handleAs: 'json',
postData: jsonData,
load: successFunction,
error: failFunction };
var deferred = dojo.xhrPost(xhrArgs);
},
CheckUserExistence:function(Email,successFunction,failFunction,token) {
var data = { 'interface': 'PickrWebService', 'method': 'CheckUserExistence', 'parameters': {'Email':Email}, 'token': token };
var jsonData = dojo.toJson(data);
var xhrArgs = {
url: self.urlString,
handleAs: 'json',
postData: jsonData,
load: successFunction,
error: failFunction };
var deferred = dojo.xhrPost(xhrArgs);
}
}
I need help on how to use this code in my client app, and what does the parameter 'token' refer to?
The code is a javascript object for you service which you can call the webservice, by invoking the methods. token is not the part of dojo.xhrPost, it might be from the ASP.Net for passing authentication token. If you have not setup the security on the service, you could ignore it.
var successFunction = function(args){
//Handle the success response.
}
var failFunction= function(err){
//Handle the failure response.
}
var service = new PickrWebService();
service.createUser(Email,Username,Password,
FirstName,Surname,Birth,Gender,Mobile,Picture,Address,successFunction,failFunction);
Apart from the above code, you need to add the dojo api in you client.

nativescript authenticating at backend web api

I am new to mobile development. My project is build using asp.net. For authentication I am using build it UserManager & User.Identity.
I have bunch of existing web apis and I wish to use them from mobile app.
I know , I could pass a secret hash to web api after authenticating, but that would involve a huge code refactoring.
I been wondering if there other ways to handle authentication & authorization with nativescript & asp.net .
Do you know any useful resources for this topic?
Many thanks for your help!
It depends quite heavily on your API structure, but I would recommend somethign like this:
Firstly you would need to use the Nativescript Http module. An implementation to get a an HTTP GET calls returned header might look like this:
http.request({ url: "https://httpbin.org/get", method: "GET" }).then(function (response) {
//// Argument (response) is HttpResponse!
//for (var header in response.headers) {
// console.log(header + ":" + response.headers[header]);
//}
}, function (e) {
//// Argument (e) is Error!
});
So your backend might return a JSON Web Token as a header. In which case on the success callback you would probably want to store your token in the applications persistent memory. I would use the Application Settings module, which would look something like:
var appSettings = require("application-settings");
appSettings.setString("storedToken", tokenValue);
Then before you make an API call for a new token you can check if there is a stored value:
var tokenValue = appSettings.getString("storedToken");
if (tokenValue === undefined {
//do API call
}
Then with your token, you would want to make an API call, e.g. this POST and add the token as a header:
http.request({
url: "https://httpbin.org/post",
method: "POST",
headers: { "Content-Type": "application/json", "Auth": tokenValue },
content: JSON.stringify({ MyVariableOne: "ValueOne", MyVariableTwo: "ValueTwo" })
}).then(function (response) {
// result = response.content.toJSON();
// console.log(result);
}, function (e) {
// console.log("Error occurred " + e);
});
Your backend would need to check the Auth header and validate the JWT to decide whether to accept or reject the call.
Alternatively, there some nice plugins for various Backends-as-a-Service, e.g. Azure and Firebase

How to create an Angular factory service to access ASP.NET server-side cache

We are creating an ASP.NET MVC application which uses AngularJS framework. This is a multi-lingual application and resource values in each language are stored in the database.
On the server-side, we load all of our resources from the database into HttpRuntimeCache when the user logs in to the application and use it throughout our views.
We want to create an AngularJS factory service which we can use to access the resources in HttpRuntimeCache.
For example:
User clicks login
ASP.NET MVC Application loads resources into HttpRuntimeCache
User is redirected to root of application (Home/Index).
Angular application is initialized
When user views a page which needs these resources from HttpRuntimeCace, we will get the value via the service
When this service is called, it will first check if it has already loaded the resource dictionary
If it has not yet loaded, it will call an MVC action method, which will return the resource dictionary as JSON, and the service will use that response to load the dictionary
If it has already been loaded, it will just return the value from the dictionary based on the key which has been requested
What is the best way to achieve this scenario?
Below is what we have so far. The issue with our current solution is that the service is returning the value before the dictionary has a chance to load.
angular.module("MyApp").factory('cacheService', ['$rootScope', '$http', function ($rootScope, $http, $q) {
var obj = { resourcesLoaded: false };
obj.loadResourceDictionary = function () {
obj.resourcesLoaded = false;
$http.get("/MyApp/Cache/GetResourceDictionary")
.success(function (data) {
obj.resourceDictionary = data;
obj.resourcesLoaded = true;
});
}
obj.getResourceValue = function (resourceKeyName) {
if (!obj.resourcesLoaded) {
obj.loadResourceDictionary();
}
return obj.resourceDictionary[resourceKeyName];
}
return obj;
}]);
EDIT w/ Usage example in Angular controller (we also want to use this service in a directive):
angular.module("MyApp").controller("MyAppCtrl", ['cacheService', function (cacheService) {
var self = this;
self.test = function () {
var value = cacheService.getResourceValue('Err_lbl_UserExist');
}
}]);
<div ng-controller="MyAppCtrl as myAppCtrl">
<button ng-click="myAppCtrl.test()">Test Angular CacheService</button>
</div>
There you go:
angular.module("MyApp").factory('cacheService', ['$rootScope', '$http', function ($rootScope, $http, $q) {
var service = {
obj.getResourceValue = function () {
return $http.get("/MyApp/Cache/GetResourceDictionary")
.success(function (data) {
return data
});
}
}
return service;
}]);
And for your controller method:
angular.module("MyApp").controller("MyAppCtrl", ['cacheService', function (cacheService) {
var self = this;
self.test = function () {
var value = null;
cacheService.getResourceValue().then(function (data){
value = data['Err_lbl_UserExist'];
}
}
}]);
<div ng-controller="MyAppCtrl as myAppCtrl">
<button ng-click="myAppCtrl.test()">Test Angular CacheService</button>
</div>
$http.get is an asynch function , therefore will block until data is received. All you have to do is handle errors which is not implemented.

Detecting SignalR authorize failures from web client

I'm experimenting with SignalR hosted in an asp.net MVC5 application and am having an issue detecting authorization failures from a web client.
I have a simple hub as follows:
public class ChitChat : Hub
{
[Authorize]
public string Hi(string incoming)
{
Clients.All.echo(incoming);
return "Echoed " + incoming;
}
}
And on the web page:
$(function() {
var hub = $.connection.chitChat;
hub.client.echo = function(msg) {
console.log(msg);
}
$.connection.hub.start().done(function() {
console.log("Done starting hub");
hub.server.hi("Client message")
.done(function() {
console.log(arguments);
})
.fail(function() {
console.log(arguments);
});
})
.fail(function() {
console.log("Fail hub" + arguments);
});
});
When I enable detailed errors in the hub configuration, I get this in the promise rejection for hi
Error: Caller is not authorized to invoke the Hi method on ChitChat.
Without detailed errors, I just get
Error: There was an error invoking Hub method 'chitchat.Hi'.
I'd like to keep detailed errors off, but still get some dependable way of identifying auth failures (I'd assumed I would get a 401/403 code somewhere). Is there a way to achieve this?
SignalR uses jQuery under the hood, so detecting the 401 status code could be achieved by following:
$.ajaxSetup({
statusCode: {
401: function() {
// your code is here
}
}
});
Given a rejection r, check r.source.status. This should give you a 401/403 when it is an authorization problem.

Resources