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

C# WebAPI接收嵌套JSON数据时出现400验证错误排查

问题排查与解决

核心原因

  • 请求JSON结构与WebAPI参数接收逻辑不匹配:你的请求是外层包含RawJson嵌套对象的JSON,但接口方法SubmitNewActivity接收的是string类型参数,ASP.NET自动模型绑定会尝试将整个JSON对象转换为字符串,直接触发类型转换错误,导致400响应。
  • 职责混乱:ActivitySubmissionService既是依赖注入的业务服务类(注入了GPSAPIContext),又被当作JSON反序列化的DTO使用,同时你还试图将单个对象的JSON反序列化为List<ActivitySubmissionService>,完全不符合请求数据结构。
  • 反序列化逻辑错误:请求中的RawJson是单个对象,而非数组,但你强行反序列化为列表,后续取FirstOrDefault的逻辑从根源上不成立。

解决步骤

1. 拆分职责,创建独立DTO类

创建专门用于接收请求数据的DTO,避免用业务服务类承担DTO的职责:

// 对应RawJson内部的结构
public class ActivityDataDto
{
    [JsonProperty("ParkSys_ID")]
    public int ParkSys_ID { get; set; }

    [JsonProperty("Route_ID")]
    public int Route_ID { get; set; }

    [JsonProperty("TrailName")]
    public string TrailName { get; set; }

    [JsonProperty("GPXData")]
    public List<GpxPointDto> GPXData { get; set; }
}

// 对应GPXData数组中的单个点
public class GpxPointDto
{
    public DateTime Timestamp { get; set; }
    public double Latitude { get; set; }
    public double Longitude { get; set; }
    public double Altitude { get; set; }
    public double Accuracy { get; set; }
    public double VerticalAccuracy { get; set; }
    public double? Speed { get; set; }
    public double? Course { get; set; }
    public bool IsFromMockProvider { get; set; }
    public int AltitudeReferenceSystem { get; set; }
}

// 对应整个请求的外层结构
public class ActivitySubmissionRequestDto
{
    [JsonProperty("RawJson")]
    public ActivityDataDto RawJson { get; set; }
}

2. 修改WebAPI控制器接口

调整接口参数,直接接收匹配请求结构的DTO(假设你有一个控制器调用该服务):

[ApiController]
[Route("api/activities")]
public class ActivityController : ControllerBase
{
    private readonly IActivitySubmission _activitySubmissionService;

    public ActivityController(IActivitySubmission activitySubmissionService)
    {
        _activitySubmissionService = activitySubmissionService;
    }

    [HttpPost]
    public async Task<IActionResult> SubmitActivity([FromBody] ActivitySubmissionRequestDto request)
    {
        if (!ModelState.IsValid)
        {
            return BadRequest(ModelState);
        }

        var result = await _activitySubmissionService.SubmitNewActivity(request.RawJson);
        return Ok(result);
    }
}

3. 修正业务服务类的逻辑

重构ActivitySubmissionService,去掉错误的反序列化逻辑,直接接收DTO:

public class ActivitySubmissionService : IActivitySubmission
{
    private readonly GPSAPIContext _gpsapiContext;

    public ActivitySubmissionService(GPSAPIContext gpsapiContext)
    {
        _gpsapiContext = gpsapiContext;
    }

    public async Task<object> SubmitNewActivity(ActivityDataDto activityData)
    {
        // 这里可以添加你的业务逻辑,比如保存到数据库
        // 示例:返回GPXData,你可以根据需求修改
        return activityData.GPXData;
    }
}

4. 验证请求

确保你的请求JSON结构不变(和你之前提交的一致),此时ASP.NET会自动完成模型绑定,不会再出现400错误。

额外说明

  • 避免将业务服务类与DTO混用,这会导致代码耦合、职责不清,后续维护困难。
  • 尽量使用强类型DTO而非object类型,这样可以获得编译时类型检查,减少运行时错误。
  • 如果需要接收原始JSON字符串,可以在控制器中用[FromBody] string rawJson,但此时前端需要将整个JSON序列化为字符串(即请求体是带引号的字符串),这通常不是最优方案。

内容的提问来源于stack exchange,提问作者tlf

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.17 17:31:05