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

ASP.NET Core中POST接口无法接收Protobuf消息的重复字段

解决ASP.NET Core无法接收Protobuf重复字段的问题

核心原因

Google.Protobuf生成的RepeatedField<string>是只读的get-only集合,ASP.NET Core默认的JSON序列化器(System.Text.Json)无法直接将JSON数组绑定到这个类型——因为序列化器无法向只读集合中添加元素。

解决方法

方法1:启用Protobuf的JSON序列化支持

这是最直接的官方适配方案:

  1. 安装NuGet包:Google.Protobuf.AspNetCore
  2. 在ASP.NET Core的启动配置(Program.cs)中,配置JSON序列化选项:
builder.Services.AddControllers()
    .AddJsonOptions(options =>
    {
        options.JsonSerializerOptions.Converters.Add(new Google.Protobuf.JsonConverter());
    });

配置完成后,System.Text.Json就能正确识别并绑定RepeatedField<T>类型的字段。

方法2:使用DTO中转

如果不想引入额外依赖,可以通过普通DTO接收请求后再转换:

  1. 定义DTO类:
public class TestArrayDto
{
    public List<string> Strs { get; set; }
}
  1. 在接口中接收DTO并映射到Protobuf生成的类型:
[HttpPost]
public IActionResult Post([FromBody] TestArrayDto dto)
{
    var testArray = new TestArray();
    testArray.Strs.AddRange(dto.Strs);
    // 后续业务逻辑处理
    return Ok();
}

方法3:自定义模型绑定器

如果需要更灵活的处理逻辑,可以自定义绑定器解析JSON数组到RepeatedField<T>:

public class RepeatedFieldModelBinder : IModelBinder
{
    public Task BindModelAsync(ModelBindingContext bindingContext)
    {
        if (bindingContext.ModelType.IsGenericType && 
            bindingContext.ModelType.GetGenericTypeDefinition() == typeof(RepeatedField<>))
        {
            var jsonBuffer = bindingContext.HttpContext.Request.BodyReader.ReadAsync().Result.Buffer;
            var jsonStr = Encoding.UTF8.GetString(jsonBuffer.FirstSpan);
            var root = JsonDocument.Parse(jsonStr).RootElement;
            
            var targetProp = root.GetProperty(bindingContext.FieldName);
            var elementType = bindingContext.ModelType.GetGenericArguments()[0];
            var list = JsonSerializer.Deserialize(targetProp.GetRawText(), typeof(List<>).MakeGenericType(elementType));
            
            var repeatedField = Activator.CreateInstance(bindingContext.ModelType);
            var addRangeMethod = bindingContext.ModelType.GetMethod("AddRange");
            addRangeMethod?.Invoke(repeatedField, new[] { list });
            
            bindingContext.Result = ModelBindingResult.Success(repeatedField);
        }
        return Task.CompletedTask;
    }
}

然后在接口参数上标记绑定器:

[HttpPost]
public IActionResult Post([ModelBinder(typeof(RepeatedFieldModelBinder))] TestArray request)
{
    // 业务逻辑处理
    return Ok();
}

额外注意事项

  • 确保请求的Content-Type头设置为application/json,因为你发送的是JSON格式负载,而非二进制Protobuf数据。
  • 检查Google.Protobuf NuGet包版本,尽量使用最新稳定版,避免旧版本的兼容性问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.16 10:25:23