.net 使用HttpWebRequest发出超过4KB的SOAP请求会导致500个内部服务器错误
当请求大小很大时,我在访问SOAP服务时遇到了真正的问题。当进行较短的SOAP调用时,所使用的方法(HttpWebRequest)工作得很好,但只要XML的大小超过4KB,我就可以在网络日志中看到请求被截断,最终导致目标服务器出现500个内部服务器错误。我还必须将客户端证书附加到调用,并且在这种情况下无法通过引用连接到web服务,因此使用HttpWebRequest.net 使用HttpWebRequest发出超过4KB的SOAP请求会导致500个内部服务器错误,.net,xml,vb.net,soap,httpwebrequest,.net,Xml,Vb.net,Soap,Httpwebrequest,当请求大小很大时,我在访问SOAP服务时遇到了真正的问题。当进行较短的SOAP调用时,所使用的方法(HttpWebRequest)工作得很好,但只要XML的大小超过4KB,我就可以在网络日志中看到请求被截断,最终导致目标服务器出现500个内部服务器错误。我还必须将客户端证书附加到调用,并且在这种情况下无法通过引用连接到web服务,因此使用HttpWebRequest Private Function GetResponse(ByVal sSoapUri As String, ByVal sSoa
Private Function GetResponse(ByVal sSoapUri As String, ByVal sSoapMessage As String, ByVal sSoapAction As String, ByVal bAttachCert As Boolean, _cert As X509Certificate) As XmlDocument
Try
Dim oHttpReq As HttpWebRequest = DirectCast(WebRequest.CreateDefault(New Uri(sSoapUri)), HttpWebRequest)
oHttpReq.ContentType = "text/xml; charset=utf-8"
oHttpReq.Method = "POST"
oHttpReq.Accept = "text/xml"
oHttpReq.Headers.Add("soapaction", sSoapAction)
oHttpReq.ServicePoint.Expect100Continue = False ' <-- I've tried this both on and off to no avail
If bAttachCert Then oHttpReq.ClientCertificates.Add(_cert)
Dim oReqStream As New StreamWriter(oHttpReq.GetRequestStream(), Encoding.UTF8)
oReqStream.Write(sSoapMessage) '<-- This string is in just over 4K in length
oReqStream.Flush()
oReqStream.Close()
Dim oHttpResp As HttpWebResponse = TryCast(oHttpReq.GetResponse(), HttpWebResponse)
Dim oRespStream As Stream = oHttpResp.GetResponseStream()
oHttpReq = Nothing
Dim oXmlResp As New XmlDocument
oXmlResp.Load(oRespStream)
oRespStream.Flush()
oRespStream.Close()
Return oXmlResp
Catch ex As WebException
Return Nothing
End Try
End Function
这是一个C#实现,我在处理大请求时使用过,没有失败。这种方法在将soap信封放入请求流方面有点不同,因为我构建了一个XDocument来表示soap请求,然后将其保存到请求流中。还要注意request.Timeout设置
您也应该首先考虑,如果您正在调用的服务对其接受的请求大小有限制。
希望这能给你一些想法 public XDocument GetResponse(XDocument soapRequest)
{
//service point manager
ServicePointManager.DefaultConnectionLimit = 5;
ServicePointManager.Expect100Continue = false;
HttpWebRequest request = (HttpWebRequest)WebRequest.Create("your soap endpoint");
request.Headers.Add("SOAPAction", "your soap action");
//set credentials
request.CookieContainer = new CookieContainer();
request.Credentials = "credentials if you need them";
//set compression
request.Headers.Add(HttpRequestHeader.AcceptEncoding, "gzip,deflate");
request.AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate;
request.ContentType = "text/xml;charset=\"utf-8\"";
//set verb
request.Method = "POST";
//set connection properties
request.KeepAlive = true; //15 sec on server side
request.Timeout = Timeout.Infinite;
//insert SOAP envelope into the request
using (Stream stream = request.GetRequestStream())
{
soapRequest.Save(stream);
}
//get response from server
WebResponse response = request.GetResponse();
//read response stream
using (StreamReader reader = new StreamReader(response.GetResponseStream()))
{
if (reader != null)
{
return XDocument.Load(reader);
}
else
{
return null;
}
}
}
得知我的邮件没有被截断 这方面的一个主要问题是,我的日志记录的maxdatasize设置为1024,因此在编写日志时,它们看起来被截断了,但实际上它们都存在。当我将maxdatasize键设置为大于发送的数据时,这一点变得很明显。摘自下面的最终配置部分:
<system.diagnostics>
<sources>
<source name="System.Net" tracemode="includehex" maxdatasize="8192">
<listeners>
<add name="System.Net"/>
</listeners>
</source>
<source name="System.Net.Sockets" tracemode="includehex" maxdatasize="8192">
<listeners>
<add name="System.Net"/>
</listeners>
</source>
</sources>
<switches>
<add name="System.Net" value="Verbose"/>
<add name="System.Net.Sockets" value="Verbose"/>
</switches>
<sharedListeners>
<add name="System.Net" type="System.Diagnostics.TextWriterTraceListener" initializeData="c:\network.log"/>
</sharedListeners>
<trace autoflush="true"/>
</system.diagnostics>
内部服务器500错误是由于服务器端的一个完全不相关的问题造成的。谢谢Doug-我尝试了以上两种方法,即使用所采用的各种技术编辑我的当前版本,而且绝对是这样,它也造成了同样的问题。我确信请求被截断为4KB—当我格式化为XDocument时,截断点会移动,当我再次编辑请求XML时,截断点也会相应移动。我还检查了,服务提供商将接受大于4KB的数据,并且他们的日志也显示了被截断的请求。这让我快发疯了!再次感谢您的帮助。只是好奇:为什么要使用HttpWebRequest来实现这一点,而不是“添加服务引用”?不幸的是,由于它将在最终的实时环境中运行的体系结构,我不能这么做-如果它能做到这一点的话:(我不明白-你为什么不认为“添加服务引用”?)是否有效?为什么您认为需要这样做?您没有该服务的“开发”实例吗?即使您没有,也只需让您的操作人员对生产中的服务运行svcuti命令,并让他们向您提供WSDL或其他元数据。然后您可以使用“添加服务引用”并指定磁盘上的WSDL文件。您将数据发布到哪个web服务器?可能存在限制…尝试使用完全不同的客户端实现(例如soapUI)将数据发布到服务。如果问题仍然存在,则会出现在发布端。谢谢,在我阅读此响应之前,我一直假设我的soap请求也被截断。我想“打印1024个…”应该是一个提示
public XDocument GetResponse(XDocument soapRequest)
{
//service point manager
ServicePointManager.DefaultConnectionLimit = 5;
ServicePointManager.Expect100Continue = false;
HttpWebRequest request = (HttpWebRequest)WebRequest.Create("your soap endpoint");
request.Headers.Add("SOAPAction", "your soap action");
//set credentials
request.CookieContainer = new CookieContainer();
request.Credentials = "credentials if you need them";
//set compression
request.Headers.Add(HttpRequestHeader.AcceptEncoding, "gzip,deflate");
request.AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate;
request.ContentType = "text/xml;charset=\"utf-8\"";
//set verb
request.Method = "POST";
//set connection properties
request.KeepAlive = true; //15 sec on server side
request.Timeout = Timeout.Infinite;
//insert SOAP envelope into the request
using (Stream stream = request.GetRequestStream())
{
soapRequest.Save(stream);
}
//get response from server
WebResponse response = request.GetResponse();
//read response stream
using (StreamReader reader = new StreamReader(response.GetResponseStream()))
{
if (reader != null)
{
return XDocument.Load(reader);
}
else
{
return null;
}
}
}
<system.diagnostics>
<sources>
<source name="System.Net" tracemode="includehex" maxdatasize="8192">
<listeners>
<add name="System.Net"/>
</listeners>
</source>
<source name="System.Net.Sockets" tracemode="includehex" maxdatasize="8192">
<listeners>
<add name="System.Net"/>
</listeners>
</source>
</sources>
<switches>
<add name="System.Net" value="Verbose"/>
<add name="System.Net.Sockets" value="Verbose"/>
</switches>
<sharedListeners>
<add name="System.Net" type="System.Diagnostics.TextWriterTraceListener" initializeData="c:\network.log"/>
</sharedListeners>
<trace autoflush="true"/>
</system.diagnostics>