I want pass data from inputs of cards.I am passing data with fetch
to the controller and there is no data in the controller.
script.js
var currentCardNumber = 1;
function addCard() {
currentCardNumber++;
let newCardHTML = `
<div class="header d-flex justify-content-between p-3">
<h4 class="card-counter">${currentCardNumber}</h4>
</div>
<div class="card-body row">
<div class="term col">
<h3>Term</h3>
<input class="form-control w-100" name = "term" >
</div>
<div class="definition col">
<h3>Definition </h3>
<input class="form-control w-100" name="definition" >
</div>
</div>
</div> `;
let newCard = document.createElement('div');
newCard.classList.add('card');
newCard.classList.add('mt-3');
newCard.innerHTML = newCardHTML;
let addNewCard = document.querySelector('.cards');
let referenceNode = document.getElementById('create-cards');
addNewCard.insertBefore(newCard, referenceNode);
}
function saveCardDataToServer() {
let cards = [];
document.querySelectorAll('.card').forEach((card) => {
let term = card.querySelector('input[name="term"]').value.trim();
let definition = card.querySelector('input[name="definition"]').value.trim();
if (term && definition) {
cards.push({
Term: term,
Definition: definition
});
}
})
fetch('/Cards/Create/', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(cards)
})
.then(response => response.json())
.then((data => {
if (data.success) {
console.log("Data successfully saved: ", data);
window.location.href = "/Cards/Learning";
} else {
console.error("Error saving card: ", data.message);
}
}))
}
document.addEventListener('DOMContentLoaded', function() {
let newCard = document.querySelector('.new-card');
newCard.addEventListener('click', function() {
addCard();
});
document.querySelector('form.cards').addEventListener('submit', function() {
saveCardDataToServer();
});
});
View
@model CardList
<!DOCTYPE html>
<html lang="en">
<head>
<script src="~/js/script.js">
</script>
<link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" rel="stylesheet"
integrity="sha384-QWTKZyjpPEjISv5WaRU9OFeRpok6YctnYmDr5pNlyT2bRjXh0JMhjY6hW+ALEwIH" crossorigin="anonymous" asp-append-version="true">
</head>
<body>
<main class="main">
<div class="container">
<div class="new-module d-flex justify-content-between mt-5">
<h1>Create new module</h1>
<a class="btn btn-primary" asp-controller="Cards" asp-action="learning" type="submit">Создать</a>
</div>
<div class="card mt-5 p-2 pb-3">
<h3>Title</h3>
<input class="form-control w-100" placeholder="Enter a name">
</div>
<form asp-controller="Cards" asp-action="Create" method="post" class="cards">
<div class="card mt-6" id="card">
<div class="header d-flex justify-content-between p-3">
<h4 class="card-counter">1</h4>
</div>
<div class="card-body row">
<div class="term col">
<h3>Term</h3>
<input class="form-control w-100" name = "term" >
</div>
<div class="definition col">
<h3>Definition </h3>
<input class="form-control w-100" name = "definition" >
</div>
</div>
</div>
<input type="submit" value="Create" id="create-cards" class="btn btn-primary mt-2"/>
</form>
<button class="new-card w-100 d-flex justify-content-center align-items-center mt-4 mt-s rounded-2" style="height: 5rem" type="button">
<h3>+ Add card</h3>
</button>
</div>
</main>
</body>
</html>
Models
public class Card
{
public int CardId { get; set; }
[Required]
public string Term { get; set; } = string.Empty;
public string Definition { get; set; } = string.Empty;
}
public class CardList
{
public List<Card> Cards { get; set; }
}
Controller
public class CardsController : Controller
{
public IActionResult Learning()
{
var cards = CardsRepository.GetCards();
return View(cards);
}
public IActionResult Create()
{
return View();
}
[HttpPost]
[Route("Cards/Create/")]
public IActionResult Create([FromForm] CardList list)
{
if (list != null)
{
foreach (var card in cards)
{
if (!string.IsNullOrWhiteSpace(card.Term) && !string.IsNullOrWhiteSpace(card.Definition))
{
CardsRepository.AddCard(card);
}
}
return Json(new { success = true, message = "Card saved successfully " });
}
var errors = ModelState.Values.SelectMany(v => v.Errors).Select(e => e.ErrorMessage);
return Json(new { success = false, message = "Validation error", errors = errors });
}
}
I see data in DevTools from fetch, however I don’t see data in controller through debugger.
2
Answers
change [FromForm] to [FromBody] in your controller method:
public IActionResult Create([FromBody] CardList list)
Based on your shared code and description it seems, your issue seems to stem from the method of binding data in the controller.
The FromForm attribute expects form-encoded data, but you are sending JSON data from your fetch request. To handle this correctly, you should either modify your client side code so that it can deal with
[FromForm]
data binding or change the attribute to FromBody to allow the controller to correctly parse the incoming JSON payload.I would suggest you to use FromBody in controller so that you need minimum change or modification because your client code is currently designed for FromBody jason data interation.
In order to do that, modify following code:
Note: Above method within your snippet would cause glitch because, If any
.card
element does not contain an input element with the nameterm
ordefinition
, querySelector returnsnull
. The linelet term = card.querySelector('input[name="term"]').value.trim();
will cause a TypeError because null does not have a value property. So in order to fix that, I have modified that, so it includes a check (if (termInput && definitionInput)) to ensure that the input elements were found before trying to access their value properties.Modify Request Body:
Controller:
Output: