Как проверить подключение к неизвестному веб-сервису на С#?

Я занят написанием класса, который контролирует состояние соединений 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. Если клиент должен реагировать, вы можете опросить более короткий таймаут, пока услуга не будет доступна.