ASP.NET Core中Fetch API提交数据报404(api/saveData未找到)
ASP.NET Core Web应用POST请求404错误排查
我正在开发一个ASP.NET Core Web应用,需要将页面输入的数据提交到服务器。页面里有个表格,第一行包含三个下拉选择框和一个复选框。用Fetch API发起POST请求时,一直提示api/saveData未找到(404错误)。
测试提交到第三方接口https://reqres.in/api/users/23是成功的,响应如下:
Success: { "column1": "Option 1", "column2": "Option B", "column3": "Choice X", "isChecked": true, "id": "17", "createdAt": "2023-10-22T09:30:31.259Z" }
我的代码
CSHTML代码
<table class="table"> <thead> <tr> <th>Column 1</th> <th>Column 2</th> <th>Column 3</th> <th>Checkbox</th> </tr> </thead> <tbody> <tr> <td> <select class="form-control" id="column1Select"> <option>Option 1</option> <option>Option 2</option> <option>Option 3</option> </select> </td> <td> <select class="form-control" id="column2Select"> <option>Option A</option> <option>Option B</option> <option>Option C</option> </select> </td> <td> <select class="form-control" id="column3Select"> <option>Choice X</option> <option>Choice Y</option> <option>Choice Z</option> </select> </td> <td> <input type="checkbox" id="checkboxInput" /> </td> </tr> <!-- 可按需添加更多行 --> </tbody> </table> <button onclick="postData()">Submit</button> <script> function postData() { var column1Value = document.getElementById("column1Select").value; var column2Value = document.getElementById("column2Select").value; var column3Value = document.getElementById("column3Select").value; var isChecked = document.getElementById("checkboxInput").checked; var data = { column1: column1Value, column2: column2Value, column3: column3Value, isChecked: isChecked }; fetch('api/saveData', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(data) }) .then(response => response.json()) .then(responseData => { console.log('Success:', responseData); }) .catch(error => { console.error('Error:', error); }); } </script>
C#代码
public class splitModel : PageModel { [ApiController] [Route("api/[controller]")] public class DataController : ControllerBase { private readonly ApplicationDbContext _context; public DataController(ApplicationDbContext context) { _context = context; } [HttpPost] [Route("SaveData")] public async Task<IActionResult> SaveData([FromBody] StockTable data) { if (data == null) { return BadRequest("Invalid data received"); } Console.Write(data.Column1); var newStockTable = new ApplicationDbContext.StockTable { Column1 = data.Column1, Column2 = data.Column2, Column3 = data.Column3, IsChecked = data.IsChecked, }; try { _context.StockTables.Add(newStockTable); await _context.SaveChangesAsync(); return Ok("Data saved successfully"); } catch (DbUpdateException ex) { // 记录异常用于排查 Console.WriteLine(ex.ToString()); return BadRequest("Error saving data: " + ex.Message); } } public class StockTable { public int Id { get; set; } // 假设这是主键列(整数类型) public string Column1 { get; set; } // 示例:数据库中的字符串列 public string Column2 { get; set; } // 另一个字符串列 public string Column3 { get; set; } // 另一个字符串列 public bool IsChecked { get; set; } // 假设这是数据库中的布尔列 } public class StockDataModel { public string Column1 { get; set; } public string Column2 { get; set; } public string Column3 { get; set; } public bool IsChecked { get; set; } } }
问题原因及修复方案
1. 控制器嵌套问题
API控制器不能嵌套在PageModel类中,ASP.NET Core无法识别嵌套的控制器。必须将DataController作为顶级独立类:
public class splitModel : PageModel { // PageModel相关代码(如有) } [ApiController] [Route("api/[controller]")] public class DataController : ControllerBase { private readonly ApplicationDbContext _context; public DataController(ApplicationDbContext context) { _context = context; } [HttpPost("SaveData")] // 合并路由简化写法 public async Task<IActionResult> SaveData([FromBody] StockTable data) { // 原有逻辑保持不变 } public class StockTable { // 原有属性保持不变 } }
2. 路由不匹配
当前控制器路由为api/Data,加上SaveData的路由后缀,完整路径是api/Data/SaveData,但Fetch请求用的是api/saveData,路径不匹配。两种修复方式:
- 调整Fetch请求路径:
fetch('/api/Data/SaveData', { // 原有配置保持不变 }) - 或者修改控制器路由规则,直接匹配
api/saveData:[ApiController] [Route("api/[action]")] // 用Action名作为路由 public class DataController : ControllerBase { [HttpPost] public async Task<IActionResult> SaveData([FromBody] StockTable data) { // 原有逻辑保持不变 } }
3. 模型绑定大小写问题
请求数据的属性是小写(column1、isChecked),但StockTable类的属性是大写开头(Column1、IsChecked)。虽然默认序列化会自动处理大小写映射,但显式添加特性可确保匹配:
using System.Text.Json.Serialization; public class StockTable { public int Id { get; set; } [JsonPropertyName("column1")] public string Column1 { get; set; } [JsonPropertyName("column2")] public string Column2 { get; set; } [JsonPropertyName("column3")] public string Column3 { get; set; } [JsonPropertyName("isChecked")] public bool IsChecked { get; set; } }
4. 其他检查项
- 确保
Program.cs中添加了API路由映射:app.MapControllers(); // 必须添加此行才能启用API控制器 - 修正
StockTable实例化方式:通常直接new StockTable()即可,无需new ApplicationDbContext.StockTable()(除非StockTable是ApplicationDbContext的嵌套类)。
内容的提问来源于stack exchange,提问作者Katie Lou
相关产品推荐
相关产品推荐

