AngularJS $http post fails - angularjs

I am new to AngularJS, I am from SAP background and as part of my PoC I built my REST services using SAP NW Gateway,I am facing an issue to POST data from Angularjs to my REST services.Please find the below detailed error log
***1. Remote Address:
10.xxx.xx.xx:8000
2. Request URL:
//host:port/sap/opu/odata/sap/USERS/Users
3. Request Method:
POST
4. Status Code:
400 Bad Request
5. Request Headersview source
1. Accept:
application/json, text/plain, */*
2. Accept-Encoding:
gzip,deflate
3. Accept-Language:
en,te;q=0.8
4. Authorization:
Basic a2VsYW1yOmoyZDEwMA==
5. Connection:
keep-alive
6. Content-Length:
146
7. Content-Type:
application/json;charset=UTF-8
8. Cookie:
sap-usercontext=sap-client=100; SAP_SESSIONID_J2D_100=R_60WyUyNG2nV1MbhC9QAcKPzyBwwxHkmwsAUFaDBqQ%3d
9. Host:
abcdefgh:8000
10. Origin:
file://
11. User-Agent:
Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/38.0.2125.111 Safari/537.36
12. X-CSRF-Token:
_jXDnt2Cdpplpj5zvK3iPA==
6. Request Payloadview source
{UserID:555, FirstName:rajesh555, LastName:kelam555, Email:rajesh555#gmail.com, Phone:9876554433,…}
1. Country: "UK"
2. Email: "rajesh555#gmail.com"
3. FirstName: "rajesh555"
4. LastName: "kelam555"
5. Phone: 9876554433
6. Postcode: "TW18 4BL"
7. UserID: 555
7. Response Headersview source
1. content-length:
535
2. content-type:
application/json
3. dataserviceversion:
1.0****
Angular Code for Post :
$scope.addRow = function () {
var config = {};
var pushdata = {'UserID':$scope.UserID, 'FirstName':$scope.FirstName, 'LastName':$scope.LastName, 'Email':$scope.Email, 'Phone':$scope.Phone, 'Country':$scope.Country, 'Postcode':$scope.Postcode};
// Sending Notification to User
growl.addSuccessMessage("User Created", config);
/* $http.post(url,pushdata, {'Content-Type':'application/json'}).success(function(pushdata) {
$scope.resultSet = pushdata.d.results;
alret("Data Posted");
}) */
$http.post(url,pushdata, {headers:{'Content-Type':'application/json'}}).success(function(data){alert(data);});
$scope.resultSet.push(pushdata);
$scope.createMessage();
$scope.UserID='';
$scope.FirstName='';
$scope.LastName='';
$scope.Email='';
$scope.Phone='';
$scope.Country='';
};
it would be great if some one help me to sort.
*Note: I am a kid in AngularJS...please ignore me and feel free to thought me.
I request to suggest the best URl/Site to learn Angularjs in a better and consistent way.
I thought, if I share the format(XML/JSON) of payload expecting for the POST to perform by my SAP Gateway service which will helps me to quickly resolve this.Below are the formats of XML/JSON works for POST.
XML Format:
host:port/sap/opu/odata/sap/USERS/Users('123')
Users('123')
2014-11-21T15:21:52Z
123
RAJESH
KELAM
RAJESHKUMAR.KELAM#ABG.CO.UK
123456789
UK
RG4 6SA
JSON Format:
{
d:
{
__metadata:
{
id: "host:port/sap/opu/odata/sap/USERS/Users('123')"
uri: "host:port/sap/opu/odata/sap/USERS/Users('123')"
type: "USERS.User"
}
-
UserID: "123"
FirstName: "RAJESH"
LastName: "KELAM"
Email: "RAJESHKUMAR.KELAM#ABG.CO.UK"
Phone: "123456789"
Country: "UK"
Postcode: "RG4 6SA"
}
-
}

You sure that the url you posting is expecting this data you want to post? You can use POSTMAN extension (in google chrome) and test if you service are ready to receive any data from http.post

Finally I could able to sort out my problem, it is all about formatting the data passing to REST service..
below is the peice of code which works is my case
$scope.addRow = function () {
var StrUId = ($scope.UserID).toString();
var StrPh = ($scope.Phone).toString();
var pushdata = {"UserID":StrUId, "FirstName":$scope.FirstName, "LastName":$scope.LastName, "Email":$scope.Email, "Phone":StrPh, "Country":$scope.Country, "Postcode":$scope.Postcode};
// Posting data
$http({
method: "post",
url:url,
data:pushdata,
headers: {
"X-CSRF-Token": "0XGo8HzpzrhaZxxX83QH9g==",
},
dataType : "json",
async: false,
contentType: 'application/json',
success: function(data){
alert(data);
}
});
Thanks for the support given
Rajesh

Related

React fetch POST request not working in only safari

For some reason trying to do a POST request on safari doesn't work despite it working on chrome for me. https://caniuse.com/#search=fetch suggests that fetch should work on safari, and the GET requests do work just fine.
My code looks like
putData() {
let data = {
title: this.state.tempTitle,
lat: this.state.tempLat,
lng: this.state.tempLng,
insta: this.state.tempInsta,
icon: this.state.tempType,
approved: false,
};
let options = {
method: "POST",
headers: {
"Content-Type": "application/json",
},
mode: 'cors',
body: JSON.stringify(data),
};
fetch("/items/", options);
}
Other similar/same questions on stack overflow suggested adding the mode: 'cors' line as well as changing /items to /items/ but, I have tried without those two changes to my code as well.
Response preview on safari says An error occurred when trying to load resource and the request headers page for items/ shows
Summary
URL: http://localhost:3000/items/
Status: —
Source: —
Initiator:
Suggest.js:62
Request
Content-Type: application/json
Referer: http://localhost:3000/suggest
Accept: */*
Origin: http://localhost:3000
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_4) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/13.1 Safari/605.1.15
Response
No response headers
Confused as to why this might be happening, didn't even notice till I uploaded the site to AWS and someone using it noticed on their iPhone.

AngularJS WebApi Authorization header does not appear to be getting passed

I am trying to create a call with AngularJS v1.3.15 into ASP.NET WebAPI (latest from Nuget) to get a list of customers. I can successfully authenticate and get back a token. I add the token to an Authentication header but when I make the call it gets kicked back saying the Authentication header is missing.
The Angular call after I get the token looks like this
$scope.baseUrl = "http://localhost:7800/";
$http({
method: 'GET',
url: $scope.baseUrl + 'customer',
headers: {
'Authorization': $scope.token
}})
I have also tried to utilize the angularjs $resourse
return $resource($scope.baseUrl + 'customer', { }, { 'get': { method: 'GET', isArray: true, headers: { 'Authorization': $scope.token } } });
In the WebApiConfig Register method I have the following setup
var cors = new EnableCorsAttribute("*","*","*");
config.EnableCors(cors);
in a DelegatingHandler I check for the Authorization header like so
var authHeader = request.Headers.Authorization;
From the Angular app it is always null. If I run a check from Fiddler and PostMan I get the Authorization header just fine.
When I press F12 from Chrome and look at the request header these are the results
OPTIONS /customer HTTP/1.1
Host: localhost:7800
Connection: keep-alive
Access-Control-Request-Method: GET
Origin: http://localhost:63342
User-Agent: Mozilla/5.0 (Windows NT 6.3; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/44.0.2376.0 Safari/537.36
Access-Control-Request-Headers: accept, authorization
Accept: */*
Referer: http://localhost:63342/Test/index.html
Accept-Encoding: gzip, deflate, sdch
Accept-Language: en-US,en;q=0.8
Fixed my issue, after some searches I found that OPTIONS does not seem to be supported out of the box. I found that if I add NuGet package Microsoft.Owin.Cors and then add
app.UseCors(Microsoft.Owin.Cors.CorsOptions.AllowAll);
to the startup.cs file

CSRF mismatch when POSTing to sails backend from Angular JS

In angular, I obtain a CSRF token like this:
// Get CSRF token and set as header
var csrfRequest = Auth.getCSRF().then(function(data){
console.log(data.data._csrf);
$rootScope.csrf = data.data._csrf;
});
Which logs the new token to the console (this works fine).
Then, I try to login to a sails.js api. Here's the request:
POST /auth/login HTTP/1.1
Host: localhost:1337
Connection: keep-alive
Content-Length: 108
Pragma: no-cache
Cache-Control: no-cache
Accept: application/json, text/plain, */*
Origin: http://localhost
User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.99 Safari/537.36
Content-Type: application/json;charset=UTF-8
Referer: http://localhost/sails-front/src/login/
Accept-Encoding: gzip, deflate
Accept-Language: en-GB,en-US;q=0.8,en;q=0.6
Request Payloadview parsed
{"email":"myemail#email.com","password":"mypass","_csrf":"PIlVO7S362OroPGBSG0X1vW2FydkP9VhK8cMk="}
The _csrf field is the same as that which was received in the getCSRF call.
Yet I get the response 'CSRF mismatch'. However, when I try the exact same thing with Postman, it works fine (so I don't think it's a problem with the sails server).
Here's the login code in angular. In the controller:
$scope.login = function() {
Auth.login({
email: $scope.email,
password: $scope.password,
_csrf: $rootScope.csrf
},
function(res) {
$state.go('app.home');
},
function(err) {
$rootScope.error = "Failed to login";
});
};
And the Auth service:
/*********************************
* login
******************************** */
function login(user, success, error) {
$http.post(API_BASE_URL + 'auth/login', user).success(function(user){
changeUser(user);
success(user);
}).error(error);
}
You posted your full request, and the answer is hidden there in plain sight--not by looking at what is being sent, but what is being omitted: namely, the cookie. The CSRF token is valid for a single Sails session, but you are neglecting to send the cookie with your AJAX request, so Sails has no idea which session the CSRF token you're sending is for.
To tell Angular to send cookies with your request, use the withCredentials setting:
$http.post(API_BASE_URL + 'auth/login', user, {withCredentials: true})

Angular POST to Web API doesn't pass data

I've been writing code against ASP.NET Web API for a while now with jQuery and I'm starting something new in Angular (writing against the same Web API backend.)
I'm POSTing to a method that will return some search results for an entity in the system. It looks like this:
public IEnumerable<dynamic> Post(string entity, FormDataCollection parameters)
{
// entity is passed on the route.
// parameters contains all the stuff I'm trying to get here.
}
If I call the method using jQuery.post:
$.post('api/search/child', {where : 'ParentID = 1'}, function(d){ foo = d });
it works just right and returns what I would expect.
I've made a service in my angular application that makes a similar call:
$http.post('api/search/child', { where: 'parentID = ' + parent.ID })
.success(function (data, status, headers, config) {
// etc.
})
But when it hits my "Post" method on the server, "paramters" is null.
After some googling I've tried adding a content-type header to ensure it's passed as JSON, and trying JSON.stringify-ing and $.param()-ing the "data" argument, but that didn't do anything (and from what I've read that shouldn't be necessary.) What am I doing wrong here? Thanks for your help!
UPDATE:
Here's the raw request from the (working) jQuery example:
POST http://localhost:51383/api/search/child HTTP/1.1
Accept: */*
Content-Type: application/x-www-form-urlencoded; charset=UTF-8
X-Requested-With: XMLHttpRequest
Referer: http://localhost:51383/mypage.aspx
Accept-Language: en-US
Accept-Encoding: gzip, deflate
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; Trident/7.0; rv:11.0) like Gecko
Host: localhost:51383
Content-Length: 23
DNT: 1
Connection: Keep-Alive
Pragma: no-cache
Cookie: (etc)
Authorization: (etc)
where=ParentID+%3D+1
And the raw request from the (failing) Angular sample:
POST http://localhost:51383/api/search/parent HTTP/1.1
Content-Type: application/json;charset=utf-8
Accept: application/json, text/plain, */*
Referer: http://localhost:51383/mypage.aspx
Accept-Language: en-US
Accept-Encoding: gzip, deflate
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; Trident/7.0; rv:11.0) like Gecko
Connection: Keep-Alive
Content-Length: 27
DNT: 1
Host: localhost:51383
Pragma: no-cache
Cookie: (etc)
{"where":"ScorecardID = 1"}
Very weird. Even when I add the 'json' data type parameter to the end of the jQuery call, it still creates the www-form-urlencoded request. And that's the one that works. My Web API application is already set up for JSON (but thank-you Dalorzo).
Check if you have included the JSON Formatter in your configuration. It should be something like :
System.Web.Http.GlobalConfiguration.Configuration.Formatters.XmlFormatter.SupportedMediaTypes.Clear();
config.Formatters.Insert(0, new System.Net.Http.Formatting.JsonMediaTypeFormatter());
The Content-Type=application/json only will work if you set the proper formatter.
You can also try using [FromBody] next to your parameter type.
Solved! Discovered this question:
AngularJs $http.post() does not send data
Pointing to this lovely article:
http://victorblog.com/2012/12/20/make-angularjs-http-service-behave-like-jquery-ajax/
Turns out Angular doesn't post data the same way jQuery does but you can override it with some tweaking.
I solved this by below codes:
Client Side:
$http({
url: me.serverPath,
method: 'POST',
data: data,
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
}).
success(function (serverData) {
console.log("ServerData:", serverData);
......
Notice that data is an object.
On the server (ASP.NET MVC):
[AllowCrossSiteJson]
public string Api()
{
var data = JsonConvert.DeserializeObject<AgentRequest>(Request.Form[0]);
if (data == null) return "Null Request";
var bl = Page.Bl = new Core(this);
return data.methodName;
}
and 'AllowCrossSiteJsonAttribute' is needed for cross domain requests:
public class AllowCrossSiteJsonAttribute : ActionFilterAttribute
{
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
filterContext.RequestContext.HttpContext.Response.AddHeader("Access-Control-Allow-Origin", "*");
base.OnActionExecuting(filterContext);
}
}

Post login form in Sencha Touch

I want to login to an external site (not my own) using Sencha Touch.
Here's some of my code:
Login controller
Ext.define('Myapp.controller.Login', {
extend: 'Ext.app.Controller',
config: {
refs: {
loginForm: '#login-form'
},
control: {
'#login-button': {
tap: 'onLoginHandler'
}
}
},
onLoginHandler: function() {
var form = this.getLoginForm();
Ext.Ajax.request({
url: 'https://www.site.com/login.html',
headers: { 'Content-Type': 'application/x-www-form-urlencoded'},
method: 'POST',
params: form.getValues(),
callback: function(options, success, response){
console.log(options);
console.log(response);
}
});
}
});
Login view
Ext.define('Myapp.view.Login', {
extend: 'Ext.form.Panel',
alias: 'widget.loginview',
xtype: 'loginform',
id: 'login-form',
requires: [
'Ext.form.FieldSet'
],
config: {
title: 'Log in',
iconCls: 'user',
html: 'Login View',
method: 'POST',
items: [
{
xtype: 'fieldset',
title: 'Log in',
items: [
bunch of fields
]
},
{
xtype: 'button',
text: 'Login',
ui: 'action',
id: 'login-button'
}
]
}
});
The result i see in my browser debugger is not what I'm expecting:
Request URL:https://www.site.com/login.html?_dc=1375705385394
Request Headers
Access-Control-Request-Headers:origin, x-requested-with, content-type
Access-Control-Request-Method:POST
Origin:http://localhost
Referer:http://localhost/~me/non/
User-Agent:Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/28.0.1500.95 Safari/537.36
Query String Parameters URL encoded
_dc:1375705385394
The form data isn't even there. But it shows up in the console.log from "console.log(response)" (see controller) so it should be sent
The request module for node seems works as I want it to..
var request = require('request');
var form = require('form-data');
var r = request.post('https://www.site.com/login.html', function(err, resp, body){
});
var frm = r.form();
frm.append(...// same fields as in my View, values are hardcoded for testing
The difference between these two is that the form is appended after the request...?
Here's the headers when i login manually:
Request URL:https://www.site.com/login.html
Request Method:POST
Status Code:302 Found
Request Headers
Accept:text/html,application/xhtml+xml,application/xml;q=0.9,*/ *;q=0.8
Accept-Encoding:gzip,deflate,sdch
Accept-Language:en-US,en;q=0.8,sv;q=0.6
Cache-Control:max-age=0
Connection:keep-alive
Content-Length:53
Content-Type:application/x-www-form-urlencoded
Cookie:NOW=4b21bf97818dd91f28732aec2b12344e28ac4aef; TUX-COOKIE=R2414511234; /=; /firsttimeload=0; s_cc=true; s_sq=%5B%5BB%5D%5D
Host:www.site.com
Origin:https://www.site.com
Referer:https://www.site.com/
User-Agent:Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/28.0.1500.95 Safari/537.36
Form Data URL encoded
...my secret form data shows up here
Response Headersview source
Connection:Keep-Alive
Content-Encoding:gzip
Content-Length:184
Content-Type:text/html; charset=iso-8859-1
Date:Mon, 05 Aug 2013 12:57:09 GMT
Keep-Alive:timeout=5, max=100
Location:../redirect/location
Server:Apache
Set-Cookie:TUX-COOKIE=R2414511234; path=/
Set-Cookie:NOW=none; path=/; expires=Fri, 08-Aug-2003 12:57:09 GMT; secure
Set-Cookie:NOW=e555573f3e21a1f008f4be34c7c61234b1014b6; path=/; secure
Vary:Accept-Encoding,User-Agent
Any thoughts or ideas are welcome! THANKS!
Ordinarily how I would take care of this problem is create a proxy service on my local server using NodeJS or PHP. This process would allow me to submit my ajax request to the same-origin and then I'd use a backend post/fetch to interact with the third party service.
In addition to the added security provided by complying with the same-origin policy; this has a couple of extra benefits. Your Ext app can do a lot less hand wrangling and you are able to support more than one service endpoint in your proxy. If the service changes you'll have server code that you can test without a UI and this can simplify debugging.
It may be possible to submit your request using JSONP but that would be highly ill-advised if you're transmitting login credentials.

Resources