Как проверить подключение к неизвестному веб-сервису на С#?
Я занят написанием класса, который контролирует состояние соединений RAS. Мне нужно протестировать, чтобы убедиться, что соединение не только подключено, но и что он может общаться с моим веб-сервисом. Поскольку этот класс будет использоваться во многих будущих проектах, я бы хотел проверить соединение с веб-сервисом, не зная об этом.
Я думал передать URL-адрес классу, чтобы он, по крайней мере, знал, где его найти. Пинг сервера не является достаточным испытанием. Возможно, сервер доступен, но служба будет отключена.
Как я могу эффективно проверить, что я могу получить ответ от веб-службы?
Ответы
Ответ 1
Вы правы, что pinging server недостаточно. Сервер может быть запущен, но веб-служба недоступна по нескольким причинам.
Чтобы отслеживать наши подключения к веб-сервису, я создал интерфейс IMonitoredService, который имеет метод CheckService(). Класс-оболочка для каждой веб-службы реализует этот метод для вызова безобидного метода в веб-службе и сообщает, если служба работает или нет. Это позволяет отслеживать любое количество сервисов без кода, ответственного за мониторинг, зная детали услуги.
Если вы немного знаете о том, что веб-служба вернется с прямого доступа к URL-адресу, вы можете попробовать просто использовать URL-адрес. Например, файл Microsoft asmx возвращает сводку веб-службы. Другие реализации могут вести себя по-разному, хотя.
Ответ 2
Вы можете попробовать следующее, которое проверяет существование веб-сайта:
public static bool ServiceExists(
string url,
bool throwExceptions,
out string errorMessage)
{
try
{
errorMessage = string.Empty;
// try accessing the web service directly via it URL
HttpWebRequest request =
WebRequest.Create(url) as HttpWebRequest;
request.Timeout = 30000;
using (HttpWebResponse response =
request.GetResponse() as HttpWebResponse)
{
if (response.StatusCode != HttpStatusCode.OK)
throw new Exception("Error locating web service");
}
// try getting the WSDL?
// asmx lets you put "?wsdl" to make sure the URL is a web service
// could parse and validate WSDL here
}
catch (WebException ex)
{
// decompose 400- codes here if you like
errorMessage =
string.Format("Error testing connection to web service at" +
" \"{0}\":\r\n{1}", url, ex);
Trace.TraceError(errorMessage);
if (throwExceptions)
throw new Exception(errorMessage, ex);
}
catch (Exception ex)
{
errorMessage =
string.Format("Error testing connection to web service at " +
"\"{0}\":\r\n{1}", url, ex);
Trace.TraceError(errorMessage);
if (throwExceptions)
throw new Exception(errorMessage, ex);
return false;
}
return true;
}
Ответ 3
Совет: создайте интерфейс/базовый класс с помощью метода InvokeWithSomeParameters. Значение "SomeParameters" должно быть "параметрами, которые 100% не влияют на какое-либо важное состояние".
Я думаю, что есть 2 случая:
- Простой веб-сервис, который не влияет на какие-либо данные на сервере. Например: GetCurrentTime(). Этот веб-сервис можно вызвать без параметров.
- Комплексный webservice, который может повлиять на некоторые данные на сервере. Например: Запуск ожидающих задач. Вы заполняете параметр со значениями, которые 100% выбрасывают исключение (соответственно не изменяет влияние ожидающих задач), если у вас есть какое-то исключение, такое как "ArgumentException", вы знаете, что сервис жив.
Я не думаю, что это наиболее четкое решение, но оно должно работать.
Ответ 4
Как открыть соединение TCP/IP с портом, используемым веб-сервисом? Если соединение работает, все соединения работают с RAS-соединением, остальной частью сети и хостом. Webservice почти наверняка работает тоже.
Ответ 5
Если это разрешено службой SOAP или WCF Microsoft, вы можете запросить веб-страницу serviceurl + "? disco" для обнаружения. Если возвращаемое является допустимым XML-документом, вы знаете, что сервис жив и здоров. Служба SOAP, отличная от Microsoft, которая не разрешает? Disco, вероятно, также вернет правильный XML.
Пример кода:
HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(URL + "?disco");
request.ClientCertificates.Add(
new X509Certificate2(@"c:\mycertpath\mycert.pfx", "<privatekeypassword>")); // If server requires client certificate
request.Timeout = 300000; // 5 minutes
using (WebResponse response = request.GetResponse())
using (Stream stream = response.GetResponseStream())
using (StreamReader sr = new StreamReader(stream, Encoding.UTF8))
{
XmlDocument xd = new XmlDocument();
xd.LoadXml(sr.ReadToEnd());
return xd.DocumentElement.ChildNodes.Count > 0;
}
Если веб-сервер присутствует, но служба не существует, для ошибки 404 будет быстро возбуждено исключение. Достаточно длинный тайм-аут в этом примере - позволить медленной службе WCF перезапускать после длительного периода бездействия или после iisreset. Если клиент должен реагировать, вы можете опросить более короткий таймаут, пока услуга не будет доступна.