Как вызвать веб-службу без wsdl в .net
Мне нужно подключиться к стороннему веб-сервису, который не поддерживает wsdl и asmx. URL-адрес службы - это http://server/service.soap
Я прочитал эту статью о вызовах сырых сервисов, но я не уверен, что это то, что я ищу.
Кроме того, я попросил wsdl файлы, но мне сказали, что их нет (и их не будет).
Я использую С# с .net 2.0 и не могу обновить до 3.5 (так что WCF еще нет). Я думаю, что сторонняя сторона использует java, как тот пример, который они предоставили.
Спасибо заранее!
ОБНОВЛЕНИЕ Получите этот ответ при просмотре URL:
<SOAP-ENV:Envelope>
<SOAP-ENV:Body>
<SOAP-ENV:Fault>
<faultcode>SOAP-ENV:Server</faultcode>
<faultstring>
Cannot find a Body tag in the enveloppe
</faultstring>
</SOAP-ENV:Fault>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
Ответы
Ответ 1
Хорошо, я наконец получил это, чтобы работать, поэтому я напишу здесь код, который я использую. (Помните,.Net 2.0, и не wsdl, чтобы получить от веб-службы).
Сначала мы создаем 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;
}
Затем мы вызываем веб-сервис, передавая все необходимые значения. Когда я читаю конверт с мылом из XML-документа, я обрабатываю данные как 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 должен быть добавлен в ответ, я его запишу.
Ответ 2
По моему мнению, нет никаких оснований для того, чтобы веб-служба SOAP не предоставляла WSDL. Служба не должна динамически генерироваться службой; он не должен быть доступен через Интернет. Но там должен быть WSDL, даже если он должен отправить его вам на диске floppy disk.
Если у вас есть возможность жаловаться поставщикам этой услуги, я настоятельно рекомендую вам это сделать. Если у вас есть возможность отступить, сделайте это. В идеале, переключите поставщиков услуг и сообщите этим людям, потому что они не предоставили WSDL. По крайней мере, узнайте, почему они не считают это важным.
Ответ 3
Хмм, сложно здесь, но не невозможно, но я сделаю все возможное, чтобы объяснить это.
Что вам нужно сделать, это
- Создание сериализуемых классов, которые соответствуют схемам объектов, с которыми вы имеете дело в службе сторонних разработчиков.
- Узнайте, используют ли они SOAPAction в своих служебных вызовах
- Посмотрите, можете ли вы создать asmx, который имитирует их службу с точки зрения возможности обработки запросов и ответов (это будет полезно для тестирования вашего клиентского приложения, если их служба не работает).
- Затем вы можете создать прокси-сервер службы из вашей фиктивной службы и изменить URL-адрес службы при вызове сторонней службы.
- Если что-то не работает на вашем клиенте, вы можете настроить свою фиктивную службу, повторно создать прокси-сервер и повторить попытку.
Я попытаюсь добавить больше как и когда я думаю об этом, но этого должно быть достаточно, чтобы вы начали.
Ответ 4
Если вам повезет, вы все равно можете получить wsdl. Некоторые структуры веб-сервисов позволяют получить динамически генерируемый WSDL.
Веб-службы, написанные с помощью Axis1.x, позволяют извлекать динамически генерируемый файл WSDL, просматривая URL-адрес.
Просто выберите
http://server/service.soap/?wsdl
Я не знаю, возможно ли это для других фреймворков.
Ответ 5
Я создал следующий вспомогательный метод для вызова WebService вручную без каких-либо ссылок:
public static HttpStatusCode CallWebService(string webWebServiceUrl,
string webServiceNamespace,
string methodName,
Dictionary<string, string> parameters,
out string responseText)
{
const string soapTemplate =
@"<?xml version=""1.0"" encoding=""utf-8""?>
<soap:Envelope xmlns:xsi=""http://www.w3.org/2001/XMLSchema-instance""
xmlns:xsd=""http://www.w3.org/2001/XMLSchema""
xmlns:soap=""http://www.w3.org/2003/05/soap-envelope"">
<soap:Body>
<{0} xmlns=""{1}"">
{2} </{0}>
</soap:Body>
</soap:Envelope>";
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:
//<?xml version="1.0" encoding="utf-8"?>
//<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
// <soap:Body>
// <SayHelloResponse xmlns="http://tempuri.org/">
// <SayHelloResult>Hello</SayHelloResult>
// </SayHellorResponse>
// </soap:Body>
//</soap:Envelope>
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;
}
Затем вы можете просто вызвать любой метод веб-службы со следующим кодом:
var parameters = new Dictionary<string, string>();
parameters.Add("name", "My Name Here");
string responseText;
var responseStatusCode = CallWebService("http://localhost/TestWebService.asmx",
"http://tempuri.org/",
"SayHello",
parameters,
out responseText);