I am creating a simple POST API for an ASP.NET Core MVC Razor app, which currently does not do much except returning a view:
public class CartController : Controller
{
public IActionResult Add()
{
return this.View();
}
[HttpPost("Add"), ActionName("Add")]
public IActionResult PostAdd()
{
return this.View();
}
}
It is registered like this in Startup.cs
:
public void ConfigureServices(IServiceCollection services)
{
services.AddRazorPages();
services.AddControllers();
}
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
//...
app.UseRouting();
app.UseEndpoints(builder => {
builder.MapRazorPages();
builder.MapControllers();
});
}
When trying to GET /Cart/Add, everything works fine and the Add.cshtml view is returned. However, a POST request fails, returning a "400 Bad request" HTTP status code:
$.ajax( {
method:"GET",
success: console.log,
url: "/Cart/Add"}) // works, HTML is logged to the console
$.ajax( {
method:"POST",
success: console.log,
url: "/Cart/Add"}) //Fails: XHR POST http://localhost:5265/Cart/Add [HTTP/1.1 400 Bad Request 0ms]
Is there something obvious i am missing here? I believe it is probably a configuration issue, however i could not find any answers neither on stackoverflow nor elsewhere (in almost all other questions about this topic, the issue was caused by parameters passed to the controller or other attributes, which could hardly be the cause here, like this one)
CodePudding user response:
Easy solution:
Decorate your action PostAdd with the below attribute:
[Route("Cart/Add")]
Reason: You are using MapControllers for routing in your configure method. MapControllers doesn't make any assumptions about routing and will rely on the user doing attribute routing.
Another approach:
In your current code, you can consider below changes:
- The second attribute ActionName is redundant.
- You need to add the [Route("[controller]")] attribute on the top of your controller.
The below example is from MSDN.
[Route("Store")]
[Route("[controller]")]
public class ProductsController : Controller
{
[HttpPost("Buy")] // Matches 'Products/Buy' and 'Store/Buy'
[HttpPost("Checkout")] // Matches 'Products/Checkout' and 'Store/Checkout'
public IActionResult Buy()
{
return ControllerContext.MyDisplayRouteInfo();
}
}
Note: in this case you might need to add the route attribute to all the action methods.
CodePudding user response:
Since you add [HttpPost("Add"), ActionName("Add")]
to the PostAdd action,the route of the action will be /Add
,try to change your ajax like:
$.ajax( {
method:"POST",
success: console.log,
url: "/Add"})