ASP.NET中使用Fetch向Controller传参无接收问题排查
问题:Fetch发送JSON数据到ASP.NET Controller无法接收数据
我通过卡片输入框收集数据,用Fetch API发送到ASP.NET的Controller,但Controller始终无法获取到数据。浏览器DevTools里能看到请求携带了数据,但调试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/bootstrap@5.3.3/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 }); } }
解决方案
1. 修改Controller的参数绑定方式
你用[FromForm]标记参数,但Fetch发送的是JSON格式数据,ASP.NET无法自动将JSON绑定到FromForm参数。把[FromForm]改成[FromBody]:
[HttpPost] [Route("Cards/Create/")] public IActionResult Create([FromBody] CardList list)
2. 调整前端发送的数据结构
你的CardList类包含Cards属性,但前端直接发送了数组,没有包装在Cards字段里。修改saveCardDataToServer函数中的body部分:
body: JSON.stringify({ Cards: cards })
3. 阻止表单默认提交行为
表单提交时会触发默认的POST请求,和你的Fetch请求冲突,导致数据无法正确接收。在submit事件中添加event.preventDefault():
document.querySelector('form.cards').addEventListener('submit', function(event) { event.preventDefault(); // 阻止默认表单提交 saveCardDataToServer(); });
4. 修复Controller中的循环变量错误
Controller里的foreach循环遍历的是未定义的cards变量,应该改成list.Cards,同时要判断list.Cards不为null:
if (list != null && list.Cards != null) { foreach (var card in list.Cards) { if (!string.IsNullOrWhiteSpace(card.Term) && !string.IsNullOrWhiteSpace(card.Definition)) { CardsRepository.AddCard(card); } } }
5. 初始化CardList的Cards属性
为避免list.Cards为null,在CardList类中初始化属性:
public class CardList { public List<Card> Cards { get; set; } = new List<Card>(); }
完成以上修改后,Controller就能正确接收到Fetch发送的卡片数据了。
内容的提问来源于stack exchange,提问作者Egor
相关产品推荐
相关产品推荐

