.NET 6中如何将HttpClient请求体提取为键值对集合?
解决方案
1. 先处理请求体流的重置问题
读取请求体后必须重置流位置,否则后续请求会因流已耗尽而失败:
var bodyString = await request.Content.ReadAsStringAsync(); // 重置流,保证后续请求能正常读取 var contentBytes = Encoding.UTF8.GetBytes(bodyString); request.Content = new ByteArrayContent(contentBytes); request.Content.Headers.ContentType = request.Content.Headers.ContentType;
2. 解析请求体为键值对集合
根据请求体的Content-Type分场景处理:
场景一:表单编码(application/x-www-form-urlencoded)
直接利用FormUrlEncodedContent的原生方法解析:
if (request.Content.Headers.ContentType?.MediaType == "application/x-www-form-urlencoded") { var formContent = request.Content as FormUrlEncodedContent; if (formContent != null) { var bodyKvp = await formContent.ReadAsNameValueCollectionAsync(); // 转换为List<KeyValuePair>方便后续排序 var bodyPairs = bodyKvp.AllKeys.Select(key => new KeyValuePair<string, string>(key, bodyKvp[key])).ToList(); } }
场景二:JSON格式(application/json)
用JSON解析库将字符串转成字典,再转成键值对集合:
if (request.Content.Headers.ContentType?.MediaType == "application/json") { // 使用System.Text.Json var bodyDict = JsonSerializer.Deserialize<Dictionary<string, object>>(bodyString); var bodyPairs = bodyDict?.ToList() ?? new List<KeyValuePair<string, object>>(); // 若API要求展开嵌套JSON,需递归处理字段(示例) // var flattenedPairs = FlattenJson(bodyDict); } // 若使用Newtonsoft.Json,替换为: // var bodyDict = JsonConvert.DeserializeObject<Dictionary<string, object>>(bodyString);
场景三:表单上传(multipart/form-data)
仅提取非文件的文本字段(一般API签名不包含文件内容):
if (request.Content.Headers.ContentType?.MediaType == "multipart/form-data") { var multipartContent = request.Content as MultipartFormDataContent; if (multipartContent != null) { var bodyPairs = new List<KeyValuePair<string, string>>(); foreach (var content in multipartContent) { var fieldName = content.Headers.ContentDisposition?.Name?.Trim('"'); if (fieldName != null && content is StringContent stringContent) { var fieldValue = await stringContent.ReadAsStringAsync(); bodyPairs.Add(new KeyValuePair<string, string>(fieldName, fieldValue)); } } } }
3. 合并头部与请求体并生成签名串
统一处理头部和请求体的键值对,按ASCII排序后拼接:
// 处理头部:将多值表头转为单个字符串(按API要求选择拼接规则) var processedHeaders = headers.Select(h => new KeyValuePair<string, string>(h.Key, string.Join(",", h.Value))).ToList(); // 合并头部与请求体的键值对 var allPairs = processedHeaders.Concat(bodyPairs).ToList(); // 按键的ASCII顺序排序 var sortedPairs = allPairs.OrderBy(p => p.Key, StringComparer.Ordinal).ToList(); // 拼接成签名字符串(示例格式:key1=value1&key2=value2) var signatureString = string.Join("&", sortedPairs.Select(p => $"{p.Key}={p.Value}"));
注意:需根据对接API的要求,排除不需要参与签名的头部字段(如Authorization、Content-Length),或对值做URL编码等额外处理。
内容的提问来源于stack exchange,提问作者Ramy.is.here
相关产品推荐
相关产品推荐

