0

I have my controller action methods as follows,

public class UserController : BaseController<UserController>
{
    [HttpGet]
    public IActionResult Assignment(Guid id)
    {
        return View();
    }

    [HttpPost]
    public IActionResult Assignment(Guid id, [FromBody] List<UserViewModel> assignees)
    {
        return View();
    }
}

The ajax method in Assignment.cshtml page

$("#btn-save").click(function () {
    var url = "/User/Assignment/@Model.SelectedUser.Id";
    $.ajax({
        type: "POST",
        url: url,
        contentType: "application/json",
        data: JSON.stringify({ assignees: assignmentPage.SelectedUsers })
    });
});

So this builds a url like;

http://localhost:8800/User/Assignment/f474fd0c-69cf-47eb-7281-08d6536da99f

This is the only route configuration in my Startup.cs.

app.UseMvc(routes =>
{
    routes.MapRoute(name: "default",
        template: "{controller=Home}/{action=Index}/{id?}");
});

I never hit to Assignment post action, server returns 400, I've searched and couldn't find yet, how am I supposed to configure my route for an action like this?

2
  • error 400 means bad request. Other than, everything seems ok. What's the implementation of BaseController<>? What else do you have in startup? and what's your skd's version? give more information. Commented Nov 29, 2018 at 11:09
  • BaseController has only two injected properties for derived ones. I don't want to fill the whole Startup code irrelevantly, so what part of Startup you need? sdk is indicated in tags Commented Nov 29, 2018 at 11:19

2 Answers 2

1

The data you are sending to your server is invalid. It's expecting a JSON array, but you're sending it a JSON object with a single property that itself is an array. You receive a 400 status-code due to the fact that JSON.NET cannot parse an object as an array.

For further clarification, this is what you're sending:

{
    "assignees": [
        { ... assignee1 ... },
        { ... assignee2 ... },
        ...
    ]
}

However, it's the array that's expected, so it should look like this:

[
    { ... assignee1 ... },
    { ... assignee2 ... },
    ...
]

All you need to do is change your current JSON.stringify line to this:

JSON.stringify(assignmentPage.SelectedUsers)

An alternative option is to create a model class in your ASP.NET Core project and use that instead of a list of strings. Here's what that would look like:

public class AssignmentModel
{
    public List<UserViewModel> Assignees { get; set; }
}

The Assignment action would look like this:

public IActionResult Assignment(Guid id, [FromBody] AssignmentModel thisNameDoesNotMatter)
Sign up to request clarification or add additional context in comments.

Comments

1

The problem for my case is I am using AutoValidateAntiforgeryTokenAttribute configuration

services.AddMvc(options =>{
    // Automatically add antiforgery token valdaiton to all post actions.
    options.Filters.Add(new AutoValidateAntiforgeryTokenAttribute());
}

So, ajax post has not any request verification token with itself, lack of this token server returns bad request.

To overcome this, I followed this link, so my final working code as,

Assignment.cshtml

@inject Microsoft.AspNetCore.Antiforgery.IAntiforgery Xsrf
@functions
{
    public string GetAntiXsrfRequestToken() => Xsrf.GetAndStoreTokens(Context).RequestToken;
}
<input type="hidden" id="RequestVerificationToken" name="RequestVerificationToken" 
       value="@GetAntiXsrfRequestToken()">

<script type="text/javascript">
    $("#btn-saveinspectors").click(function () {
        var url = "/Audit/Assignment/@Model.SelectedUser.Id";
        var assignees = JSON.stringify(assignmentPage.SelectedUsers);

        $.ajax({
            type: "POST",
            url: url,
            beforeSend: function (xhr) {
                xhr.setRequestHeader("XSRF-TOKEN", $('#RequestVerificationToken').val());
            },
            contentType: "application/json",
            data: assignees,
        });
    });
</script>

Startup.cs

public void ConfigureServices(IServiceCollection services)
{
    services.AddAntiforgery(o => o.HeaderName = "XSRF-TOKEN");
}

Note: This is my case that there is not any form inside my page where a request verification token is generated automatically. If you have a form in your page where you make an ajax request then you can follow this post

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.