I am trying to call a controller method marked with [ValidateAntiForgeryToken] from my UI using Axios.
I have successfully called the same action by using Jquery ajax
Working AJAX Code.
First i get the token from my form
var addAntiForgeryToken = function (data) {
data.__RequestVerificationToken = $("[name='__RequestVerificationToken']").val();
return data;
};
amd then i call my method
$.ajax({
type: "POST",
url: "http://localhost:40428/controller/action",
data: addAntiForgeryToken({ }),
success: function (response) {
}
});
The above successfully calls the following method in my controller
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Test_Get()
{
ViewBag.Search = true;
return View("Index");
}
What i have already tried with axios is the following
axios({
method: 'post',
url: 'http://localhost:40428/Meeting_Notes/Test_Get',
data: addAntiForgeryToken({})
});
I have also tried setting the headers manually but I still cannot get it to work.
After searching around for a bit I found a simple solution. First create the controller and decorate it with HttpPost and ValidateAntiForgeryToken
[HttpPost]
[ValidateAntiForgeryToken]
public void Test_Axios(int id) { }
Then before calling the controller using axios add the following interceptor for the headers. This will define the header as default for all axios api calls
axios.defaults.headers.common['X-Requested-With'] = 'XMLHttpRequest';
then retreive the token
var token = document.querySelector('token, input').getAttribute('value');
then use the qs library to stringify the call with the token (Be careful! it's Qs and not qs!)
var request = Qs.stringify({ id: 22, __RequestVerificationToken: token });
if you don't wanna pass any parameters then you can just use the following
var request = Qs.stringify({ __RequestVerificationToken: token });
then just call the controller method
axios({
method: 'post',
url: "/controller/Test_Axios",
data: request
});
And you are done! You can now start calling mvc 5 controller, decorated with the [ValidateAntiForgeryToken] attribute.
Related
I am working on a web application using Asp.Net Core 3.1, i make ajax call(using axios library, method is POST):
<script>
axios({
url: '/home/test', // HomeController/Test Action
method: 'post',
data: {
abc: 123
},
})
.then(function (response) {
console.log(response);
})
.catch(function (error) {
console.log(error);
});
</script>
in my HomeController i have appropriate action:
[HttpPost]
public IActionResult Test(string abc)
{
return Json(new { abc });
}
in this case binding doesn't work well even if i add [FromBody] attribute like:
[HttpPost]
public IActionResult Test([FromBody]string abc)
{
return Json(new { abc });
}
what is a solution in this case?
You can use FormData() to pass axios data to controller:
<script>
var bodyFormData = new FormData();
bodyFormData.set('abc', 123);
axios({
url: '/Home/test', // HomeController/Test Action
method: 'post',
data: bodyFormData,
})
.then(function (response) {
console.log(response);
})
.catch(function (error) {
console.log(error);
});
</script>
Here is the test result:
Sometimes the binding FromBody can't parse the html content from the body. Try to change the parameter type from string to dynamic. It should hit your controller.
You can wrap your parameter into a class that has only that field and there the binding works.
Also you can take advantage of the action constraints and try that as well
HttpPost("{abc:string}")
Hope this help
I could use some guidens, sending an object from my angular 2 application to the Web API.
I know how to GET objects from the Web Api, to my angular 2 application, but can't seem to figure out how the post method works or even if I should use the http.post methodd.
My angular 2 application has the following method:
sendUpdatdReservation(updatedReservation: Reservation) {
var result;
var objectToSend = JSON.stringify(updatedReservation);
this.http.post('http://localhost:52262/api/postbookings', objectToSend)
.map((res: Response) => res.json()).subscribe(res => result = res);
console.log(result);
}
The "updatedReservation" is an object, which I convert to JSON.
The Web api can be reached by the following address:
httl://localhost:52262/api/postbookings
Web Api controller:
[EnableCors(origins: "*", headers: "*", methods: "*")]
public class PostBookingsController : ApiController
{
[AcceptVerbs()]
public bool ConfirmBooking(Booking booking)
{
return true;
}
}
What I'm trying to do is to send the object, update my database based on the changes values that the object has. Then send back true or false if this is a confirmation or not so I can redirect to confirmation page.
Do any know the unsupported media type error?, is that related to that the object i send is not what the api method expects?
Hope someone can help.
You need to set the Content-Type header when sending the request:
sendUpdatdReservation(updatedReservation: Reservation) {
var result;
var objectToSend = JSON.stringify(updatedReservation);
var headers = new Headers();
headers.append('Content-Type', 'application/json');
this.http.post('http://localhost:52262/api/postbookings', objectToSend, { headers: headers })
.map((res: Response) => res.json()).subscribe(res => {
this.result = res;
console.log(this.result);
});
}
Don't forget to import this class:
import {Http,Headers} from 'angular2/http';
I am using Web API in a MVC Website. This is my Update action in the API controller:
public HttpResponseMessage PutProduct(int Id, ProductModel model)
{
HttpResponseMessage response = null;
if (ModelState.IsValid)
{
model.ProductId = Id;
if (model.Update())
response = Request.CreateResponse(HttpStatusCode.Created);
}
return response;
}
I call it using JQ AJAX from a partial view which is loaded in the Index.cshtml page. The code works fine and the index page does not get called again, instead, the new list is populated in the partial view itself. I am not calling Index page again. But after the response, the page url changes to show like this:
http://localhost:54820/Products/Index?ProdName=Chicken+Soup&Category=Chinese&Price=20
This is my AJAX:
function updateprod(product) {
$.ajax({
url: uri + '/' + product.ProductId,
type: 'put',
contentType: 'application/json; charset=utf-8',
data: JSON.stringify(product),
statusCode: {
201: function (data) { //accepted
loadlist();
}
}
})
.fail(function (xhr, textStatus, err) {
alert(err);
});
}
I want the URL to be like this, like what it was initially:
http://localhost:54820/Products/Index
Can anyone help ?
You should look at the response headers.
It seems that your response has a location header used by the user-agent to redirect to URL indicated in the response.
Besides that you should use 201 status-code for created resources, for update is better to use 200 (OK), how you can read in the w3c docs.
Hope it helps.
I have following code in the controller, here I want to return Partial View or Json Result to jquery. My problem is when this controller is hit jquery blocks the UI with some progress bar and waiting for response until it return. But when ModelState is false it return partial view which bypass jquery unblock UI. So this makes UI block forever.
[HttpPost]
public ActionResult Edit(Form form)
{
...
if (!ModelState.IsValid)
{
return PartialView("EditPartial", model);
}
return Json(new
{
Success = true,
Id = ID
});
}
How can I solve this problem?
Your controller method is behaving properly. You just need to modify your ajax call:
$.ajax({
url: '<your url>',
dataType: 'json',
success: function(data, textStatus, jqXHR) {
// You have the json result.
},
error: function(jqXHR, textStatus, errorThrown) {
// You have the partial view
}
});
An empty response is also is considered to be a failed json parse. Your controller method should either return a response of null or {} instead.
See the below url for more details of dataType and error
http://api.jquery.com/jQuery.ajax/
I have an API Controller and call action from JS:
$('#create-se').on('click', function () {
var data = {};
$.ajax({
url: 'api/registration',
type: 'POST',
data: data,
dataType: 'json',
contentType: 'application/json',
success: function () {
}
});
});
public bool Post(UserRegistrationViewModel model)
{
if (!ModelState.IsValid) { return false; }
return true;
}
Model has few required properties and few StringLength. When I send data from js to controller ModelState.IsValid always returns true. I can't figure out how to solve it. Even if posted model is null, Model.IsValid is true anyway
http://codebetter.com/johnvpetersen/2012/04/02/making-your-asp-net-web-apis-secure/
This website has a better way of doing validation and using headers to send the token across and if it invalid it will return validation failed.