Ajax POST 适用于 [FromForm] 但不适用于 [FromBody]

Ajax POST works with [FromForm] but not with [FromBody]

在我看来,我传递了 BookViewModel 并且我有一个表单,我正试图用它来创建 Book。如果我使用 [FromForm] 属性,我可以执行此操作,但我试图了解它与 [FromBody] 有何不同。这是我的模型:

public class Book
{
    public int Id { get; set; }
    public string Title { get; set; }
    public int GenreId { get; set; }    //foreign key from Genre

    public virtual Genre Genre { get; set; }
}

public class BookViewModel
{
    public ICollection<Book> Books { get; set; }
    public Book Book { get; set; }
}

这是我的视图和控制器:

[HttpGet]
public IActionResult Index()
{
    BookViewModel books = new BookViewModel
    {
        Books = _context.Books.Include(x => x.Genre).ToList()
    };  // _context.Books is my database context and table

    return View();
}

[HttpPost]
[ValidateAntiForgeryToken]
public IActionResult Index([FromForm] BookViewModel b)  //works without
{                                                       //[FromForm] too
    //code to perform tasks
    //etc
    //return Json(true);      The parameters work fine but I would like [FromBody]
}

查看:

<form id="formid" method="post">
    <div asp-validation-summary="ModelOnly"></div>

    <label>Title</label>
    <input asp-for="Book.Title" class="form-control" />
    <span asp-validation-for="Book.Title"></span>

    <label>Genre</label>
    <input asp-for="Book.GenreId" class="form-control" />
    <span asp-validation-for="Book.GenreId"></span>

    <button type="button" onclick="SaveData()">Submit</button>
</form>

<script>
    function SaveData(){
        event.preventDefault();
        var formData = $("#formid").serialize();

        $.ajax({
            url: "/",
            type: "POST",
            data: formData,
            beforeSend: function(request){
                  request.setRequestHeader(
                  "RequestVerificationToken", 
                       $("[name=__RequestVerificationToken']").val());
            }
         });
     }
</script>

所有这些代码都可以正常工作,但我想改用 [FromBody]

我已将 contentType: "application/json" 添加到我的 ajax,并将 [FromBody] 添加到我的操作方法,但是当我提交表单时,操作中的 BookViewModel 为空方法。我想知道如何使用 [FromBody]contentType: "application/json" 而不是 application/x-www-url-formencoded?

提交我的表单

[FromBody] 将执行默认模型绑定,这正是我在这里想要的。我假设 [FromBody] 不起作用的原因是因为我序列化表单的方式,但我不确定。

[FromForm][FromBody]的区别如下:

[FromForm] : 从发布的表单字段中获取值。
[FromBody] : 从请求体中获取值。

要使用[FromBody]属性,可以通过JQuery获取输入的值,然后创建JavaScript对象,并将其发送给控制器方法,代码如下:

<script>
    function SaveData() {
        event.preventDefault();
        //var formData = $("#formid").serialize();

        var bookvm = {};
        var book = {};
        book.Title = "hello"; //use jquery to get the entered value 
        book.GenreId = "1001";
        var genre = {};
        genre.Id = 1001;
        genre.Name = "Type A";
        book.Genre = genre;
        bookvm.Book = book;

        $.ajax({
            url: "/Home/BookIndex",  //change the url to yours
            type: "POST",
            data: JSON.stringify(bookvm),
            contentType: "application/json; charset=utf-8",
            dataType: "json",
            beforeSend: function (request) {
                request.setRequestHeader(
                    "RequestVerificationToken",
                    $("[name='__RequestVerificationToken']").val());
            }
        });
    }
</script>

结果如下: