Я пытаюсь отправить данные в метод контроллера, чтобы добавить элемент в репо.
Я делаю это со страницы HTML (бритвы), используя AJAX jQuery.
Форма сериализует данные и может читать элементы. Однако, поскольку эти данные отправляются в метод, аргумент, передаваемый в метод, имеет значение null.
Я просмотрел несколько сообщений здесь, на stackoverflow и в Интернете.
Изначально у меня была функция контроллера, возвращающая результат IActionResult
и Action
. Однако, вернув View();
, аргумент все равно был нулевым.
Я пытался доказать, что аргументом является сам объект, что бытие (книга-книга) и есть модель. Но безрезультатно.
Форма сериализуется и будет отображаться в консоли:
"ISBN=9780132350884&Title=gg&Author=gg&AvailabilityStatus=true&AvailabilityStatus=false"
Я явно что-то здесь упускаю.
Заранее спасибо.
.cshtml
/jQuery:
@model Library.Models.Book
@{
ViewData["Title"] = "BookAddView";
}
<h1>BookAddView</h1>
<h4>Book</h4>
<hr />
<div class = "row">
<div class = "col-md-4">
<form id = "frm_newBook">
<div class = "mb-3 form-group">
<label asp-for = "ISBN" class = "control-label"></label>
<input asp-for = "ISBN" class = "form-control" id = "input_isbn"/>
</div>
<div class = "mb-3 form-group">
<label asp-for = "Title" class = "control-label"></label>
<input asp-for = "Title" class = "form-control" id = "input_title" />
</div>
<div class = "mb-3 form-group">
<label asp-for = "Author" class = "control-label"></label>
<input asp-for = "Author" class = "form-control" id = "input_author" />
</div>
<div class = "form-group form-check mb-3">
<label class = "form-check-label">
<input class = "form-check-input" asp-for = "AvailabilityStatus" id = "input_avail" /> @Html.DisplayNameFor(model => model.AvailabilityStatus)
</label>
</div>
<div class = "form-group">
<button id = "btn_SubmitBook" class = "btn btn-primary">Submit</button>
</div>
</form>
</div>
</div>
<div>
<a asp-action = "Index">Back to List</a>
</div>
<script type = "text/javascript">
$('#btn_SubmitBook').click(
function () {
var data = $("#frm_newBook").serialize();
$.ajax({
url: '@Url.Action("BookAdd", "Library")',
type: 'POST',
dataType: 'json',
content: "application/json; charset=utf-8",
data: data
});
}
);
</script>
Контроллер С#:
// POST : Book/Create and AddBook
[HttpPost]
public JsonResult BookAdd(string jsonInput)
{
if (String.IsNullOrEmpty(jsonInput))
{
return Json(0);
};
Book book = JsonConvert.DeserializeObject<Book>(jsonInput);
_bookRepository.AddBook(book);
return Json(1);
}
Значение, которое вы опубликовали:
ISBN=9780132350884&Title=gg&Author=gg&AvailabilityStatus=true&AvailabilityStatus=false
не похоже на действительный JSON, и я думаю, что это может быть так.
Также в вашем методе C# не указано, откуда брать значение параметра jsonInput
. Попробуйте добавить атрибут FromBody
к параметру:
public JsonResult BookAdd([FromBody] string jsonInput)
Чтобы проверить значение, отправляемое на серверную часть, перейдите в инструменты разработчика браузера и посмотрите на вкладке Netowrk, какие значения отправляются в запросе:
Я могу предложить что-то, что создает правильный JSON, если это так:
var data = new FormData($("#frm_newBook"))
var json = JSON.stringify(Object.fromEntries(data))
$.ajax({
url: '@Url.Action("BookAdd", "Library")',
type: 'POST',
dataType: 'json',
content: "application/json; charset=utf-8",
data: json
});
Вы используете .net 8 MVC и пытаетесь отправить данные формы, кстати, вы уже используете taghelpers, например. asp-for
, так что использование отправки формы может быть первым вариантом, по моему скромному мнению. Для этого нам потребуется добавить действие публикации для формы <form id = "frm_newBook" asp-action = "BookAdd" asp-controller = "Comment">
и изменить метод публикации, как показано ниже. Это отправка формы, поэтому нам нужно использовать FromForm
[HttpPost]
public IActionResult BookAdd([FromForm] Book book) {
return Ok("success");
}
При отправке обновится вся страница, и это может быть причиной того, что вы пытаетесь использовать ajax. Затем вы можете использовать код Михала: var data = $("#frm_newBook").serialize();
преобразует данные формы в строку формы, а не в строку Json. Или вы можете использовать этот ajax и по-прежнему использовать мой метод Post. Я тестировал это на своей стороне, и это сработало хорошо.
$("#btn_SubmitBook").click(function(e) {
var data = $("#frm_newBook").serialize();
console.info(data);
e.preventDefault();
$.ajax({
url: 'https://localhost:7064/comment/BookAdd',
type: 'POST',
data: data
});
});
Даже если мы установим тип контента "application/json; charset=utf-8"
в ajax, он все равно будет application/x-www-form-urlencoded
в запросе, так что нам придется использовать FromForm
в методе контроллера.
Это сработало, у меня возникла проблема с наличием конструктора с параметрами в классе Book. Но это было быстро решено, создав для этого еще один конструктор без параметров. Спасибо.
По сути, вы пытаетесь отправить форму, а данные, которые вы пытаетесь опубликовать, не являются JSON. Поэтому мы не смогли отправить его в формате JSON. По поводу того, почему аргумент равен нулю: даже если мы установили тип контента JSON, он все равно будет
application/x-www-form-urlencoded
, тогда нам придется использовать FromForm в контроллере. Так что я боюсь, что использование[FromForm] Book book
вместоstring jsonInput
тоже решит проблему.