ASP.NET API Controller POST/Redirect/Get - angularjs

I would like to use the P/R/G design with this API, using AngularJS on the client side. Here is my API method:
[HttpPost]
public HttpResponseMessage UpdateRaw(HttpRequestMessage request)
{
//do stuff...
var res = request.CreateResponse(HttpStatusCode.Redirect);
var authority = request.RequestUri.Authority;
var uri = string.Concat(authority, "/api/DataApi/GetRaw");
res.Headers.Location = new Uri(uri);
res.Headers.Add("Access-Control-Allow-Origin", "*");
return res;
}
I have another method in this controller (DataApiController) which is called GetRaw(). Basically I want the client to issue a POST, call this method, then get redirected to the GET method. Here is my JS code:
//get the data and build the js rep
$http({
method: 'POST',
url: '/api/DataApi/UpdateRaw',
headers: {
'Content-Type': undefined
},
data: {
test: "test"
}
}).then(function (result) {
console.log("RAW--------------");
console.log(result.data);
// do stuff...
}, function () { console.log("DIDN'T WORK"); });
When I issue the POST, however, my browser console says "The request was redirected to a URL ('localhost:25498/api/DataApi/GetRaw') which has a disallowed scheme for cross-origin requests." I am aware of this answer, but that had the same result.
I found another website somewhere which suggested adding the line
res.Headers.Add("Access-Control-Allow-Origin", "*");
but that does not seem to work either.
I am new to ASP.NET and Web Dev in general, so any ideas would be appreciated. Thanks.

Related

How to set request part for POST request with angular-file-upload and Spring?

Unfortunately this answer does not help me. The problem appears to be that the request parameter file is not present in my POST request for some reason.
I am trying to upload a file, any file whether it's a binary file or a text file, in a POST request. The REST controller reveals:
#PostMapping(WordEmbeddingApiPaths.UPLOAD_MODEL)
#RequestMapping(method=RequestMethod.POST, headers={"Content-Type=multipart/form-data"})
public ResponseEntity<WordVectorListDto> uploadModel(
#RequestParam("file") MultipartFile file,
RedirectAttributes redirectAttributes) {
LOGGER.debug("POST uploadModel");
return new ResponseEntity<WordVectorListDto>((WordVectorListDto)null, HttpStatus.OK);
}
and on the client I am running:
var uploader = $scope.uploader = new FileUploader({
url: 'http://localhost:8080/rest-api/dl4j/we/uploadModel'
});
uploader.onAfterAddingFile = function($modelFile) {
console.info('onAfterAddingFile', $modelFile);
var fd = new FormData();
fd.append('file', $modelFile.file);
$http.post($modelFile.url, fd, {
headers: {
'Content-Type': 'multipart/form-data'
},
params: {'file' : $modelFile.file}
})
.then(
function (data) {
alert("upload success");
},
function (data, status) {
alert("upload error");
}
);
};
However, I am getting 400 Bad Request as server response.
Any idea what the problem is?
Update:
I saw that an internal exception got thrown on the server side stating:
org.springframework.web.multipart.support.MissingServletRequestPartException: Required request part 'file' is not present
I thought that I am setting this already - how can I make this right?
Posting FormData with AngularJS
When doing a POST with a FormData API object, it is important to set the Content-Type header to undefined.
var fd = new FormData();
fd.append('file', $modelFile.file);
$http.post($modelFile.url, fd, {
headers: {
//'Content-Type': 'multipart/form-data'
'Content-Type': undefined
},
//params: {'file' : $modelFile.file}
})
When the XHR send() method gets a FormData object created by the FormData API it automatically sets the content type to multipart/form-data and includes the proper boundary.
By having the AngularJS framework override the content type, the boundary is not set properly.
Debugging Small Programs
This question is an example of putting several things together without debugging each part.
This question has several unknown code components:
An undebugged AngularJS POST method
An undebugged Spring Backend
An undebugged mysterious AngularJS service
This answer pointed out errors with the AngularJS POST method but there are a couple of other unknowns. Is the Spring backend working properly? Is the mysterious FileUploader service being used correctly?
Debugging involves isolating unknowns and testing them separately.
Does the Angular POST method work with a known backend such as HTTP BIN - HTTP Request & Response Service?
Does the Spring backend work with an uploader that has been tested?
For more information, see How to debug small programs.
if you are using #EnableAutoConfiguration then you need to do the following as discussed here https://github.com/spring-projects/spring-boot/issues/2958
#EnableAutoConfiguration(exclude = {MultipartAutoConfiguration.class})
define the following beans
#Bean(name = "multipartResolver")
public CommonsMultipartResolver commonsMultipartResolver(){
CommonsMultipartResolver resolver = new CommonsMultipartResolver();
resolver.setMaxUploadSize(50*1024*1024);
return resolver ;
}
#Bean
#Order(0)
public MultipartFilter multipartFilter(){
MultipartFilter multipartFilter = new MultipartFilter();
multipartFilter.setMultipartResolverBeanName("multipartResolver");
return multipartFilter;
}

Nodejs sending external API POST request

i am trying to send a POST request from my angularjs controller to the nodejs server which should then send a full POST request to the external API and this way avoid CORS request as well as make it more secure as i'm sending relatively private data in this POST request.
My angularjs controller function for making the post request to the nodejs server looks like this and it works fine:
var noteData = {
"id":accountNumber,
"notes":[
{
"lId":707414,
"oId":1369944,
"nId":4154191,
"price":23.84
}
]
}
var req = {
method: 'POST',
url: '/note',
data: noteData
}
$http(req).then(function(data){
console.log(data);
});
Now the problem lies in my nodejs server where i just can't seem to figure out how to properly send a POST request with custom headers and pass a JSON data variable..
i've trierd using the nodejs https function since the url i need to access is an https one and not http ,i've also tried the request function with no luck.
I know that the url and data i'm sending is correct since when i plug them into Postman it returns what i expect it to return.
Here are my different attempts on nodejs server:
The data from angularjs request is parsed and retrieved correctly using body-parser
Attempt Using Request:
app.post('/buyNote', function (req, res) {
var options = {
url: 'https://api.lendingclub.com/api/investor/v1/accounts/' + accountNumber + '/trades/buy/',
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': apiKey
},
data = JSON.stringify(req.body);
};
request(options, function (error, response, body) {
if (!error) {
// Print out the response body
// console.log(body)
console.log(response.statusCode);
res.sendStatus(200);
} else {
console.log(error);
}
})
This returns status code 500 for some reason, it's sending the data wrongly and hence why the server error...
Using https
var options = {
url: 'https://api.lendingclub.com/api/investor/v1/accounts/' + accountNumber + '/trades/buy/',
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': apiKey
}
};
var data = JSON.stringify(req.body);
var req = https.request(options, (res) => {
console.log(`STATUS: ${res.statusCode}`);
console.log(`HEADERS: ${JSON.stringify(res.headers)}`);
res.setEncoding('utf8');
res.on('data', (chunk) => {
console.log(`BODY: ${chunk}`);
});
res.on('end', () => {
console.log('No more data in response.');
});
});
req.on('error', (e) => {
console.log(`problem with request: ${e.message}`);
});
req.write(data);
req.end();
Https attempt return a 301 status for some reasons...
Using the same data, headers and the url in Postman returns a successful response 200 with the data i need...
I don't understand how i can make a simple http request...
Please note: this is my first project working with nodejs and angular, i would know how to implement something like this in php or java easily, but this is boggling me..
So after a lot of messing around and trying different things i have finally found the solution that performs well and does exactly what i need without over complicating things:
Using the module called request-promise is what did the trick. Here's the code that i used for it:
const request = require('request-promise');
const options = {
method: 'POST',
uri: 'https://requestedAPIsource.com/api',
body: req.body,
json: true,
headers: {
'Content-Type': 'application/json',
'Authorization': 'bwejjr33333333333'
}
}
request(options).then(function (response){
res.status(200).json(response);
})
.catch(function (err) {
console.log(err);
})

$http.post in angularjs not work to me and $http.get has response errors

I am new to angularjs am tying to learn it but some problems faced me, actually they are two problems:
First Problem: $http.post never works as there is no action and there is no response. However, $http.get is able to work.
Second Problem: Because of the first problem I call my restful webservice by $http.get, but the web service response status always is -1. Though the web service is able to do its work successfully and always response data null, can any one help me.
this my angular part:
var app = angular.module('myLogin',[]);
app.controller('loginController',function($scope,$http){
$scope.login=function(){
var username = $scope.username;
var password = $scope.pass;
$http.get("http://localhost:8080/spring/webservice/login/"+username+"/"+password)
.success(function(data,status){
alert("data : "+data);
alert("Data Inserted Successfully");
window.location.href = "chatScreen.html";
})
.error(function(data,status){
alert("Status: "+status);
window.location.href = "login.html";
});
}
});
and this my web service:
/**
* web service part
*/
#RequestMapping(value="webservice/login/{name}/{pass}", method=RequestMethod.GET)
#ResponseStatus(value = HttpStatus.OK)
public ResponseEntity<String> weblogin(#PathVariable("name") String name, #PathVariable("pass") String pass)
{
System.out.print("username : "+name);
System.out.print(pass);
UserService service = new UserService();
List<UserBean> users = service.getUsers();
if(users!=null)
{
for(UserBean user : users)
if( ( user.getUsername().equals(name) ) && ( user.getPassword().equals(pass) ) )
{
System.out.print("success");
username = name;
//model.addAttribute("result", "Welcome to chat..");
MessageService messageService = new MessageService();
List<MessageBean> messages = messageService.getMessage(username);
String userMessages="";
if(messages != null)
{
for(MessageBean msg : messages)
userMessages +="\n"+msg.getSender() + ": " + msg.getMessage()+" \n";
}
else
userMessages +="You have no Messages !";
//model.addAttribute("whoSendToMe", userMessages);
return new ResponseEntity(HttpStatus.OK);
}
}
return new ResponseEntity<String>("faild", HttpStatus.NOT_FOUND);
}
refer this may be this will give you idea how to approach your problem:-
$http({
method: 'GET',
url: '/someUrl'
}).then(function successCallback(response) {
// this is asynchronous call back
// you will get your data here comming from rest
}, function errorCallback(response) {
// called asynchronously if an error occurs
});
share your code so we will try to solve it
If you use method GET and you receive a -1 returned, it means normally that you are giving a wrong URL.
As for then POST method you should use this syntax:
return $http({
method: 'POST',
url: 'index.php/email/createDeliverable',
data: $.param({
csrfTokenName: --your token--,
userName: user.name,
password: password
}),
headers: { 'Content-Type': 'application/x-www-form-urlencoded' }
});
Remember to add the headers part.
Your server may need a CSRF token validation, in this case you need to pass it, see un my example: csrfTokenName: --your token--,

how to use response.redirect in webapi+asp.net?

I want to redirect to another .aspx page from WebAPI. I have used this code but it is not working:
string url = "http://localhost:61884/UserList.aspx";
System.Uri uri = new System.Uri(url);
return Redirect(uri).ToString();
You don't. (or your description of the problem is not accurate)
Web API is meant to retrieve data or persist data, it is a way to interact with the server from the client without having to do the traditional form post or page request calls. The caller (javascript based on your question tag angularJs) needs to execute the redirect once the results from the call to the Web API are retrieved.
This is good SOC (separation of concerns), the business logic in the Web API should not care about routes (angularjs) / web pages.
Even if you wanted to the Web API, because of how its called, can't redirect the client.
Summary: The Web API code itself should not any type of redirecting of the client. The client should handle this.
Sample call to web api and redirect from angular code:
$http({
url: "/api/SomeWebApiUrl",
data: {},
method: "POST",
headers: { 'Content-Type': "application/json" },
responseType: "json"
}).then(function (response) {
if(response.data.somethingToCheck === someConditionThatWarrentsRedirect)
$window.location.href = "~/someOtherUrl/";
});
try something like this:
var response = Request.CreateResponse(HttpStatusCode.Moved);
string fullyQualifiedUrl = Request.RequestUri.GetLeftPart(UriPartial.Authority);
response.Headers.Location = new Uri(fullyQualifiedUrl);
Hope that helps.
Redirect from asp.net web api post action
public HttpResponseMessage Post()
{
// ... do the job
// now redirect
var response = Request.CreateResponse(HttpStatusCode.Moved);
response.Headers.Location = new Uri("http://www.abcmvc.com");
return response;
}

web api 2 post with parameter - must use json.stringyfi

I'm using angularjs and I'm trying to make a HttpPost call to my web api.
My api method:
[HttpPost]
[Route("authentication/getkey")]
public IHttpActionResult GetKey([FromBody]string password) {
//Do stuff
}
my call:
service.getKey = function (password) {
return $http.post('api/authentication/getkey', JSON.stringify(password))
.then(function(result) {
return result.data;
});
}
Now this works fine, but do I really need to use JSON.stringify? I tried sending it like below, but all of them get password = null. Do I have to use JSON.stringify or am I doing it wrong in my other examples?
//Doesnt work
service.getKey = function (password) {
return $http.post('api/authentication/getkey', password)
.then(function(result) {
return result.data;
});
}
//Doesnt work
service.getKey = function (password) {
return $http.post('api/authentication/getkey', {password})
.then(function(result) {
return result.data;
});
}
If you don't want to use JSON.stringify, the other option will be to send the data as application/x-www-form-urlencoded as pointed in other answer as well. This way you are sending the data as form data. I'm not sure about the syntax of the $http.post Shortcut method but the idea is the same.
service.getKey = function (password) {
$http({
method: 'POST',
url: 'api/authentication/getkey',
data: $.param({ '': password }),
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
}
})
.then(function(result) {
return result.data;
});
From Microsoft's Web API official documentation about Parameter Binding in ASP.NET Web API:
When a parameter has [FromBody], Web API uses the Content-Type header to select a formatter. In this example, the content type is "application/json" and the request body is a raw JSON string (not a JSON object).
Angular $http service sends Content-Type: application/json as header by default in POST requests, as you can see from the official docs, so Web API is trying to bind your request body using his JsonFormatter. Because of this you have to provide him a well formatted Json string (not a Json Object with a string inside) to correctly bind his raw string parameter.
As a side note, you could also send a request using application/x-www-form-urlencoded as Content-Type header, but then you will have to format your body as form parameters (using something similar to jQuery $.param( .. ))

Resources