0

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)

0

2 Answers 2

2

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.

Sign up to request clarification or add additional context in comments.

Comments

1

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"})

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.