I have a WebApi controller that after I invoke it I want it to redirect me to another site
Here is my c# code
public async Task<HttpResponseMessage> Login(LoginParameters parameters, [FromUri]string returnUrl)
{
//same validations
var response = Request.CreateResponse(HttpStatusCode.Moved);
response.Headers.Location = new Uri("Http://www.google.com");
return response;
}
My javascript code goes like this
'user strict'
var login = function ($scope, $http) {
var parameters = {
userName: userName,
password: password
};
var url = '/api/user/Login';
$http.post(url, parameters);
.then(function(response){
/*some random code that i will remove */
});
};
login.$inject = ['$scope', '$http'];
module.exports = login;
Looking at the chrome console i realise that the http POST call returns httpstatus = 302. Then i see 2 more request to requests to google.com, but my page is not redirected. So what am I doing wrong?
Thanks in advance
When you use $http, this uses an XMLHttpRequest object which does not adjust the location for the user. It will even follow redirects. You have a couple options:
You could return the new location as a field, then in the .then callback, assign window.location to cause a redirect.
You could use a standard form to post to the resource, then the browser would follow the redirects appropriately.
I would recommend you look into angular interceptors. You can "intercept" the response, check the status code, and redirect using window.location or $location. This is pretty flexible so you write the logic in one place.
Edit: this doesn't seem to work because it appears you can't catch a 302. According to this post, it appears the request is redirected automatically and the response you'd get back is from the redirected location. In the OP's post - the response was empty because the OP was redirected to a different domain which resulted in a cross-domain request (so keep this in mind if your redirects will do the same), but a proposed solution was to check the response to see if it contained data from the redirected page.
Related
I found this solution here, but it doesn't explain a lot so I can modify it to my needs. He is also mentioning a stack overflow question, but there are so many "different" solutions and I got confused.
The controller:
.controller('AppCtrl', function($scope, $http) {
$scope.data = {};
$scope.submit = function(){
var link = 'http://app.domain.com/api.php';
$http.post(link, {username : $scope.data.username}).then(function (res){
$scope.response = res.data;
});
console($http.post(link, {username : $scope.data.username}));
};
});
I would like modify it and add another field, so it would be username and password. and post the to the server. But the response I need it to be just one field.
Can someone give me an explanation, of the code above so I can modify it?
As NNR said, you can pass some other parameters in your HTTP request and then POST it to the endpoint of your choice (here, the link, generally an API endpoint) by submitting it through an ng-submit. The request contains your parameters and is parsed into json that you can un-parse later in your php file (in order to get params of the request and then use it in your mysql query (generally..). After the request has been sent, it will return you a promise, that will either be a success or an error based on the reply of your server, like this :.then(function success(response) { //do stuff here},
function error(response) {//do stuff here});
You will be able to access that response.data object in your controller by using $scope
I've some hard time being clear but I hope that helps ! I suggest you to have a look at https://docs.angularjs.org/api/ng/service/$http ! :)
I am new to Angularjs and wondering how to check the token's expire date and time before sending any request.
I googled and found there are concepts like interceptors and decorators in angular but I am a bit confused which one to use and how. Or is there any better way to do it.
What am I doing right now?
I have created a service that has GET, POST functions take url, data and config as parameters and there I am checking the token. I know this is not the right approach.
You can use an interceptor that will configure every $http call. enter link description here
You can write interceptor which will cancel invalid token request before it is actually sent:
return {
'request': function(config) {
if (condition) {
var canceler = $q.defer();
config.timeout = canceler.promise;
canceler.resolve();
}
return config;
}
}
Obviously, you can manipulate config before returning it and (for example) change token.
i building an API service in angular and laravel, when i firing a GET call to the API everythings work fine, but when i fire POST call the service still use GET method instead of POST.
that is my service:
function LeadsAPI($http,$q,BASE_URL)
{
this.updateLead = function (lead_data) {
var url = BASE_URL+"/leads/update/";
var deferred = $q.defer();
$http.post(url , lead_data).then(function(response){
deferred.resolve(response.data);
});
return deferred.promise;
}
}
i call to this function from a Controller:
LeadsController.$inject = ['$scope', 'LeadsAPI'];
function LeadsController($scope , LeadsAPI)
{
LeadsAPI.updateLead({'lead_id' : res._id, 'the_lead': {'fist_name' : 'asd asd'}}).then(function (res) {
console.log(res);
});
}
i tried pass the parameters as a string ("a=b&c=d...") and added header :
$http.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded;charset=utf-8';
in the run function at my App module instantiation but yet, i keep getting 405 (Method Not Allowed) error.
any ideas why and how to solve it? thank you very much all! :)
Seems the question is old and unanswered but google led me here. I hope someone will find this answer useful.
I had the same problem. $http was set to POST but server was returning error from GET request.
After checking the headers in a web inspector it shows the browser actually did two requests:
update/ 301 text/html angular.js:11442
update 405 xhr https://test.site/post/update
The first one is the one from $http and the second one is after a redirect.
As you can see the trailing slash URL is redirected to a non trailing one. With this redirect a POST request gets also changed to GET as well.
The solution is to change your request url to not contain trailing slashes:
url: BASE_URL+"/leads/update",
The GET works fine ... good
The POST returns 405 - Method not allowed
It sounds like it is doing a POST and the server you are posting to does not support POST requests to the endpoint in question
Can you please provide more information, such as the HTTP request and response headers when you make a GET request and the same for the POST request
You can access the header information via the NET tab in Firefox's Firebug or in Chrome console
Be sure that your API method is ready to handle a POST request. Maybe Angular is actually firing a POST request, but your method is expecting a GET.
If you are sure Angular is really firing a GET request instead of a POST for some reason, try to explicitly set the HTTP method on the $http object:
$http({
method: 'POST',
url: BASE_URL+"/leads/update/",
data: lead_data
}).then(function (response) {
deferred.resolve(response.data);
});
I'm building an AngularJS (1.2.16) web app with a RESTful API, and I'd like to send 401 Unauthorized responses for requests where authentication information is invalid or not present. When I do so, even with an HTTP interceptor present, I see the browser-presented basic "Authentication Required" dialog when an AJAX request is made via AngularJS. My interceptor runs after that dialog, which is too late to do something useful.
A concrete example:
My backend API returns 401 for /api/things unless an authorization token is present. Nice and simple.
On the AngularJS app side, I've looked at the docs and set up an interceptor like this in the config block:
$httpProvider.interceptors.push(['$q', function ($q) {
return {
'responseError': function (rejection) {
if (rejection.status === 401) {
console.log('Got a 401')
}
return $q.reject(rejection)
}
}
}])
When I load my app, remove the authentication token, and perform an AJAX call to /api/things (to hopefully trigger the above interceptor), I see this:
If I cancel that dialog, I see the console.log output of "Got a 401" that I was hoping to see instead of that dialog:
Clearly, the interceptor is working, but it's intercepting too late!
I see numerous posts on the web regarding authentication with AngularJS in situations just like this, and they all seem to use HTTP interceptors, but none of them mention the basic auth dialog popping up. Some erroneous thoughts I had for its appearance included:
Missing Content-Type: application/json header on the response? Nope, it's there.
Need to return something other than promise rejection? That code always runs after the dialog, no matter what gets returned.
Am I missing some setup step or using the interceptor incorrectly?
Figured it out!
The trick was to send a WWW-Authenticate response header of some value other than Basic. You can then capture the 401 with a basic $http interceptor, or something even more clever like angular-http-auth.
I had this issue together with Spring Boot Security (HTTP basic), and since Angular 1.3 you have to set $httpProvider.defaults.headers.common["X-Requested-With"] = 'XMLHttpRequest'; for the popup not to appear.
For future reference
I've come up with this solution when trying to handle 401 errors.
I didn't have the option to rewrite Basic to x-Basic or anything similar, so I've decided to handle it on client side with Angular.
When initiating a logout, first try making a bad request with a fake user to throw away the currently cached credentials.
I have this function doing the requests (it's using jquery's $.ajax with disabled asynch calls):
function authenticateUser(username, hash) {
var result = false;
var encoded = btoa(username + ':' + hash);
$.ajax({
type: "POST",
beforeSend: function (request) {
request.setRequestHeader("Authorization", 'Basic ' + encoded);
},
url: "user/current",
statusCode: {
401: function () {
result = false;
},
200: function (response) {
result = response;
}
},
async: false
});
return result;
}
So when I try to log a user out, this happens:
//This will send a request with a non-existant user.
//The purpose is to overwrite the cached data with something else
accountServices.authenticateUser('logout','logout');
//Since setting headers.common.Authorization = '' will still send some
//kind of auth data, I've redefined the headers.common object to get
//rid of the Authorization property
$http.defaults.headers.common = {Accept: "application/json, text/plain, */*"};
In my app I have a token mechanism for authentication.
Every API call needs the token, otherwise it returns a 401.
Which I can easily handle with a response interceptor.
Now when I am using regular routes, and say the token expire, and I try to visit a partial that requires authentication, How will I trap 401 that I get while routing ?
In cases where the first thing that the page comes is making an API call, I will come to know of token expiry and will logout the user.
I want to be able to stop the user from visiting a view if the token has expired.
Will response interceptors take care of this scenario also ?
In case you want to do special processing specific to a partial, you can create a resolve function to check for the defined partial and take appropriate action. It would look something like:
function CheckTemplate() {
return {
"TemplateCheck": function ($route, $http) {
var url = $route.current.templateUrl;
$http.get(url)
.error(function(data, status, headers, config) {
if (status===404) {
... // Do what you need to do
}
})
}
}
}
Here is a sample plunker checking for a 404 on a partial:
http://plnkr.co/edit/4tagMIlcH0jC1A0YODRt?p=preview