You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.08 06:44:53