本文转载自小马家微信公众号「DotnetPlus」。转载本文请联系DotnetPlus公众号。最近重构了认证代码,认证过程比较常规:POST/open-api/v1/user-info?client_id&timstamp&rd=12345&sign=***&method=hmaccontent-type:application/jsonpayload:{"token":"AA2917B0-C23D-40AB-A43A-4C4B61CC7C74"}平台显示:签名验证失败。发现平台收到的PostPayload不符合预期。阅读本文以解锁Content-Type标头的正确使用。1.入坑下面是构造HttpClient对象并发起请求的代码://InitializeHttpClientFactorycontext.Services.AddHttpClient("platform",c=>{c.BaseAddress=newUri("https://alpha-engage.demohost.com/");c.DefaultRequestHeaders.Accept.Add(newMediaTypeWithQualityHeaderValue("application/json"));})...//生成命名的HttpClient并发起请求varclient=_clientFactory.CreateClient("platform");varresponse=等待客户端。PostAsync($"open-api/v1/user-token/info?{req.AuthString()}",newStringContent(req.ReqPayload.ToString(),Encoding.UTF8));平台日志显示收到的requestpayload:{\"token\":\"AA2917B0-C23D-40AB-A43A-4C4B61CC7C74\"}嗯,平台收到的json数据已经转码,无法识别json?明眼人都能看出来,HttpClient请求没有设置Content-Type,接收方没有识别JSON格式的payload,转码生成了错误的签名。①Content-Type是一个EntityHeader,表示资源的mediaType,可以在request/response中使用②代码中newStringContent(req.ReqPayload.ToString(),Encoding.UTF8)没有指定mediaType参数,因此该函数将使用text/plainDefault-----------------------------------------当我尝试添加内容类型(下面的黄色背景线代码)时:context.Services.AddHttpClient("platform",c=>{c.BaseAddress=newUri("https://alpha-engage.demohost.com/");c.DefaultRequestHeaders.Accept.Add(newMediaTypeWithQualityHeaderValue("application/json"));//ACCEPTheaderc.DefaultRequestHeaders.Add("content-type","application/json");})这时候,抛出以下异常:InvalidOperationException:Misusedheadername.MakesurerequestheadersareusedwithHttpRequestMessage,responseheaderswithHttpResponseMessage,andcontentheaderswithHttpContentobjects.Nani,什么是HttpContent标头?Chrome开发工具显示只有两种Headers?Upgrade,Connection---RequestHeader要获取的资源或者客户端自己的信息Accept,AuthorizationHttpRequestHeadersResponseHeader响应信息Location,ETagHttpResponseHeadersEntityHeaderEntityBodyAdditionalinformationContent-Length,ConnectionHttpContentHeadersContent-Type属于EntityHeader一、对应.NET类型的HttpContentHeader;虽然EntityHeader不是requestheader或responseheader,但它们仍然会包含在request/responseheader术语中(此说法来自官方)所以我们在ChromeDevToolsHeaders中看不到Entity是分组的,但是Content-类型标头经常出现在请求/响应标头中。回到上面的异常,.NET严格区分了四个header,所以c.DefaultRequestHeaders.Add("content-type","application/json")尝试在requestheader中添加content-type,姿势不对,.NET提示InvalidOperationException。3.为这个常规的Post请求填上正确的Content-Typeheader。方法①添加Headerusing(varrequest=newHttpRequestMessage()){request.Method=newHttpMethod(method);request.RequestUri=newUri(url);request.Content=newStringContent(payload);request.Content.Headers。ContentType=newMediaTypeHeaderValue("application/json");varresponse=await_httpClient.SendAsync(request);returnresponse;}使用HttpClient.SendAsync(request)方法②写入HttpContent时,传入媒体类型StringContent的重载构造函数:参数3媒体类型可以直接设置,varresponse=awaitclient.PostAsync($"open-api/v1/user-token/info?{req.AuthString()}",newStringContent(req.ReqPayload.ToString(),Encoding.UTF8,"应用程序/json"));
