如何配置Refit客户端以正常支持解析BSON格式响应
问题场景
使用Refit客户端调用ASP.NET 6接口时,接口返回BSON格式数据,客户端响应的Content字段为null,无法正常获取返回值;将接口返回格式切换为JSON后,客户端可正常解析。
服务端接口定义如下:
[Produces("application/bson", Type=typeof(MyDto))] public async Task<IActionResult> GetBinaryDataAsBson(Guid id)
服务端已实现自定义BSON输出格式化器,基于Newtonsoft的BsonDataWriter完成BSON写入,核心代码:
public override Task WriteResponseBodyAsync(OutputFormatterWriteContext context) { var response = context.HttpContext.Response; using (var ms = new MemoryStream()) { using (var bsonWriter = new BsonDataWriter(ms) { CloseOutput = false }) { var jsonSerializer = JsonSerializer.Create(_jsonSerializerSettings); jsonSerializer.Serialize(bsonWriter, context.Object); bsonWriter.Flush(); } return response.Body.WriteAsync(ms.GetBuffer(), 0, (int)ms.Length); } }
解决方案
Refit默认仅内置JSON、XML等通用格式的解析逻辑,无法自动识别application/bson类型的响应,需要手动添加自定义BSON解析支持,配置步骤如下:
- 实现Refit提供的
IContentSerializer接口,编写BSON反序列化逻辑
using Newtonsoft.Json; using Newtonsoft.Json.Bson; using Refit; using System.IO; using System.Net.Http; using System.Text; using System.Threading.Tasks; public class BsonContentSerializer : IContentSerializer { private readonly JsonSerializerSettings _jsonSerializerSettings; public BsonContentSerializer(JsonSerializerSettings? serializerSettings = null) { _jsonSerializerSettings = serializerSettings ?? new JsonSerializerSettings(); } public async Task<T?> DeserializeAsync<T>(HttpContent content) { using var responseStream = await content.ReadAsStreamAsync(); using var bsonReader = new BsonDataReader(responseStream); var serializer = JsonSerializer.Create(_jsonSerializerSettings); return serializer.Deserialize<T>(bsonReader); } public Task<HttpContent> SerializeAsync<T>(T item) { // 若不需要向服务端发送BSON格式请求,保留默认JSON序列化逻辑即可;如有需求可自行实现BSON请求序列化 var jsonContent = JsonConvert.SerializeObject(item, _jsonSerializerSettings); return Task.FromResult<HttpContent>(new StringContent(jsonContent, Encoding.UTF8, "application/json")); } }
- 初始化Refit客户端时,传入配置了自定义BSON序列化器的RefitSettings
var refitSettings = new RefitSettings { ContentSerializer = new BsonContentSerializer(/* 可传入与服务端一致的Json序列化配置,保证字段匹配 */) }; var apiClient = RestService.For<IDataApi>("你的服务端根地址", refitSettings);
- 在Refit对应的接口方法上添加请求头,声明客户端接受BSON格式响应,避免服务端内容协商阶段返回非预期格式
public interface IDataApi { [Headers("Accept: application/bson")] [Get("/api/your-route/{id}")] Task<MyDto> GetBinaryDataAsBson(Guid id); }
补充校验项:需确认服务端自定义的BsonMediaTypeFormatter已将
application/bson加入SupportedMediaTypes集合,否则服务端不会执行BSON序列化逻辑。
内容的提问来源于stack exchange,提问作者Guitarman1024
相关产品推荐
相关产品推荐

