如何在.net中调用没有wsdl的Web服务
我必须连接到不提供wsdl或asmx的第三方Web服务。 该服务的URL只是http://server/service.soap
我已经阅读了有关原始服务调用的这篇文章 ,但我不确定这是否是我正在寻找的。
此外,我已经要求wsdl文件,但被告知没有(并且不会有)。
我正在使用带有.net 2.0的C#,并且无法升级到3.5(所以还没有WCF)。 我认为第三方正在使用java,因为这是他们提供的示例。
提前致谢!
更新浏览url时获取此响应:
SOAP-ENV:Server Cannot find a Body tag in the enveloppe
好吧,我终于让它工作了,所以我会在这里写下我正在使用的代码。 (请记住,.Net 2.0,没有wsdl来自Web服务)。
首先,我们创建一个HttpWebRequest:
public static HttpWebRequest CreateWebRequest(string url) { HttpWebRequest webRequest = (HttpWebRequest)WebRequest.Create(url); webRequest.Headers.Add("SOAP:Action"); webRequest.ContentType = "text/xml;charset=\"utf-8\""; webRequest.Accept = "text/xml"; webRequest.Method = "POST"; return webRequest; }
接下来,我们调用webservice,传递所需的所有值。 当我从xml文档中读取soap信封时,我将把数据作为StringDictionary处理。 应该是一个更好的方法来做到这一点,但我稍后会考虑这个:
public static XmlDocument ServiceCall(string url, int service, StringDictionary data) { HttpWebRequest request = CreateWebRequest(url); XmlDocument soapEnvelopeXml = GetSoapXml(service, data); using (Stream stream = request.GetRequestStream()) { soapEnvelopeXml.Save(stream); } IAsyncResult asyncResult = request.BeginGetResponse(null, null); asyncResult.AsyncWaitHandle.WaitOne(); string soapResult; using (WebResponse webResponse = request.EndGetResponse(asyncResult)) using (StreamReader rd = new StreamReader(webResponse.GetResponseStream())) { soapResult = rd.ReadToEnd(); } File.WriteAllText(HttpContext.Current.Server.MapPath("/servicios/" + DateTime.Now.Ticks.ToString() + "assor_r" + service.ToString() + ".xml"), soapResult); XmlDocument resp = new XmlDocument(); resp.LoadXml(soapResult); return resp; }
所以,就是这样。 如果有人认为必须将GetSoapXml添加到答案中,我会把它写下来。
在我看来,SOAP Web服务没有理由不提供WSDL。 它不需要由服务动态生成; 它无需通过互联网提供。 但是必须有一个WSDL,即使他们必须在软盘驱动器上发送给你!
如果您有任何能力向这项服务的提供者投诉,那么我强烈建议您这样做。 如果你有能力推回,那么就这样做。 理想情况下,切换服务提供商,并告诉这些人,因为他们没有提供WSDL。 至少,找出他们认为不重要的原因。
嗯,这里很棘手,但并非不可能,但我会尽我所能去探索它。
你需要做的是
- 创建与您在第三方服务上处理的对象模式匹配的可序列化类。
- 了解他们是否在服务调用中使用任何SOAPAction
- 看看你是否可以创建一个模拟其服务的asmx,以便能够处理请求和响应(如果服务中断,这将有助于测试客户端应用程序)
- 然后,您可以从虚拟服务创建服务代理,并在调用第三方服务时更改服务URL。
- 如果某些内容在您的客户端无效,那么您可以调整您的虚拟服务,重新生成代理并再试一次。
当我想到它时,我会尝试添加更多,但这应该足以让你开始。
如果你很幸运,你仍然可以获得wsdl。 一些Web服务框架允许您检索动态生成的WSDL。
使用Axis1.x编写的Web服务允许您通过浏览URL来检索动态生成的WSDL文件。
只需浏览
http://server/service.soap/?wsdl
我不知道这是否可以与其他框架一起使用。
我创建了以下帮助器方法来手动调用WebService而不需要任何引用:
public static HttpStatusCode CallWebService(string webWebServiceUrl, string webServiceNamespace, string methodName, Dictionary parameters, out string responseText) { const string soapTemplate = @" <{0} xmlns=""{1}""> {2} {0}> "; var req = (HttpWebRequest)WebRequest.Create(webWebServiceUrl); req.ContentType = "application/soap+xml;"; req.Method = "POST"; string parametersText; if (parameters != null && parameters.Count > 0) { var sb = new StringBuilder(); foreach (var oneParameter in parameters) sb.AppendFormat(" <{0}>{1}{0}>\r\n", oneParameter.Key, oneParameter.Value); parametersText = sb.ToString(); } else { parametersText = ""; } string soapText = string.Format(soapTemplate, methodName, webServiceNamespace, parametersText); using (Stream stm = req.GetRequestStream()) { using (var stmw = new StreamWriter(stm)) { stmw.Write(soapText); } } var responseHttpStatusCode = HttpStatusCode.Unused; responseText = null; using (var response = (HttpWebResponse)req.GetResponse()) { responseHttpStatusCode = response.StatusCode; if (responseHttpStatusCode == HttpStatusCode.OK) { int contentLength = (int)response.ContentLength; if (contentLength > 0) { int readBytes = 0; int bytesToRead = contentLength; byte[] resultBytes = new byte[contentLength]; using (var responseStream = response.GetResponseStream()) { while (bytesToRead > 0) { // Read may return anything from 0 to 10. int actualBytesRead = responseStream.Read(resultBytes, readBytes, bytesToRead); // The end of the file is reached. if (actualBytesRead == 0) break; readBytes += actualBytesRead; bytesToRead -= actualBytesRead; } responseText = Encoding.UTF8.GetString(resultBytes); //responseText = Encoding.ASCII.GetString(resultBytes); } } } } // standard responseText: // // // // // Hello // // // if (!string.IsNullOrEmpty(responseText)) { string responseElement = methodName + "Result>"; int pos1 = responseText.IndexOf(responseElement); if (pos1 >= 0) { pos1 += responseElement.Length; int pos2 = responseText.IndexOf("", pos1); if (pos2 > pos1) responseText = responseText.Substring(pos1, pos2 - pos1); } else { responseText = ""; // No result } } return responseHttpStatusCode; }
然后,您可以使用以下代码简单地调用任何Web服务方法:
var parameters = new Dictionary(); parameters.Add("name", "My Name Here"); string responseText; var responseStatusCode = CallWebService("http://localhost/TestWebService.asmx", "http://tempuri.org/", "SayHello", parameters, out responseText);
- 为什么我不能两次读取Http Request Input流?
- 内存映射文件.NET
- 在Winforms中绘制一条线
- entity framework是否具有来自Linq2Sql(ObjectContext.CreateQuery ?)的等效DataContext.GetTable
- “在大多数情况下,基础抽象通用类是一个糟糕的选择。”为什么? (或者为什么不)
- 使用C#或F#查找包含单个字符的字符串排列
- 是否会在发布版本中评估提供给Debug.Assert的表达式?
- 使用Google Data API使用C#访问Google Spreadsheets会因Mono而失败
- 特定于文化的DateTime字符串在平台之间不一致