In my View I pass BookViewModel
and I have a form which I am trying to create a Book
with. I can perform this if I use the [FromForm]
attribute but I am trying to understand how that differs from [FromBody]
. Here are my models:
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; }
}
Here is my View and Controller:
[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]
}
View:
<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>
All of this code works fine but I would like to use [FromBody]
instead.
I have added contentType: "application/json"
to my ajax, and added [FromBody]
to my action method, but when I submit my form, BookViewModel
is null in the action method. I would like to know how I could submit my form with [FromBody]
with contentType: "application/json"
instead of application/x-www-url-formencoded
?
[FromBody]
will perform default model binding which is what I want here. I am assuming that the reason [FromBody]
has not worked is because of the way I am serializing the form but I am not sure.
The difference between [FromForm]
and [FromBody]
as below:
[FromForm] : Gets values from posted form fields.
[FromBody] : Gets values from the request body.
To use the [FromBody]
attribute, you could get the entered value via JQuery, then create JavaScript object, and send it to controller method, code as below:
<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>
The result as below: