.NET 6 HttpClient调用SOAP接口报错:服务不可用
我需要根据给定规范调用SOAP操作,已创建好SOAP消息并准备发送。配置了HttpClient后,每次发送POST请求都会收到“服务不可用”的响应状态,但通过SOAPUI测试该SOAP服务操作可正常调用。请问我的HttpClient配置中缺少了什么?
服务提供商给出的HTTP头规范
POST https://soap.msg-qa.com
HTTP/1.1
Accept-Encoding: gzip,deflate
Content-Type: application/soap+xml;charset=”UTF8”;action="QuoteRealTime"
Content-Length: 3108
Host: soap.msg-qa.com
Connection: Keep-Alive
User-Agent: Apache-HttpClient/4.1.1 (java 1.5
我的代码
HttpClientHandler handler = new HttpClientHandler(); handler.AutomaticDecompression = DecompressionMethods.Deflate | DecompressionMethods.GZip; using (var client = new HttpClient(handler)) { client.Timeout = new TimeSpan(0, 2, 0); var request = new HttpRequestMessage() { RequestUri = new Uri("https://soap.msg-qa.com"), Method = HttpMethod.Post }; request.Content = new StringContent(soapmessage, Encoding.UTF8, "text/xml"); request.Headers.Clear(); client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("text/xml")); request.Content.Headers.ContentType = new MediaTypeHeaderValue("text/xml"); request.Headers.Add("SOAPAction", "QuoteRealTime"); HttpResponseMessage response = client.SendAsync(request).Result; if (!response.IsSuccessStatusCode) { _logger.LogError($"result = {response.StatusCode}, message = {response.ReasonPhrase}"); return null; } else { _logger.LogInformation($"Success. result = {response.StatusCode}, message = {response.ReasonPhrase}"); return ""; } }
问题排查与修复方案
1. Content-Type 不匹配(核心问题)
服务端要求的Content-Type是application/soap+xml;charset=UTF-8;action="QuoteRealTime",但你的代码中两次将其设置为text/xml——这是SOAP 1.1的格式,而服务端明确要求SOAP 1.2的application/soap+xml类型,这是导致请求被拒绝的主要原因。
2. 移除多余的Accept头
服务端的请求规范中没有Accept: text/xml这个头,你手动添加的该头可能干扰服务端的请求判断,建议移除。
3. 添加指定的User-Agent
服务端示例请求中带有特定的User-Agent,部分服务端会校验该字段,需要手动添加匹配的User-Agent头。
4. 移除冗余的SOAPAction头
对于SOAP 1.2(对应application/soap+xml),SOAPAction头并非必须,服务端已经要求将action参数放在Content-Type中,因此可以移除代码中添加的SOAPAction头。
修改后的代码示例
HttpClientHandler handler = new HttpClientHandler(); handler.AutomaticDecompression = DecompressionMethods.Deflate | DecompressionMethods.GZip; using (var client = new HttpClient(handler)) { client.Timeout = new TimeSpan(0, 2, 0); // 添加指定的User-Agent client.DefaultRequestHeaders.UserAgent.ParseAdd("Apache-HttpClient/4.1.1 (java 1.5)"); var request = new HttpRequestMessage() { RequestUri = new Uri("https://soap.msg-qa.com"), Method = HttpMethod.Post }; // 直接使用正确的Content-Type创建StringContent request.Content = new StringContent(soapmessage, Encoding.UTF8, "application/soap+xml"); // 为Content-Type添加action参数和明确指定charset request.Content.Headers.ContentType.Parameters.Add(new NameValueHeaderValue("action", "QuoteRealTime")); request.Content.Headers.ContentType.CharSet = "UTF-8"; HttpResponseMessage response = client.SendAsync(request).Result; if (!response.IsSuccessStatusCode) { _logger.LogError($"result = {response.StatusCode}, message = {response.ReasonPhrase}"); return null; } else { _logger.LogInformation($"Success. result = {response.StatusCode}, message = {response.ReasonPhrase}"); return ""; } }
内容的提问来源于stack exchange,提问作者cITsecure

