How do I test connectivity to an unknown web service in C#?

北慕城南 提交于 2019-12-30 05:53:06

问题


I'm busy writing a class that monitors the status of RAS connections. I need to test to make sure that the connection is not only connected, but also that it can communicate with my web service. Since this class will be used in many future projects, I'd like a way to test the connection to the webservice without knowing anything about it.

I was thinking of passing the URL to the class so that it at least knows where to find it. Pinging the server is not a sufficient test. It is possible for the server to be available, but the service to be offline.

How can I effectively test that I'm able to get a response from the web service?


回答1:


You are right that pinging the server isn't sufficient. The server can be up, but the web service unavailable due to a number of reasons.

To monitor our web service connections, I created a IMonitoredService interface that has a method CheckService(). The wrapper class for each web service implements this method to call an innocuous method on the web service and reports if the service is up or not. This allows any number of services to be monitored with out the code responsible for the monitoring knowing the details of the service.

If you know a bit about what the web service will return from accessing the URL directly, you could try just using the URL. For example, Microsoft's asmx file returns a summary of the web service. Other implementations may behave differently though.




回答2:


You could try the following which tests the web site's existence:

public static bool ServiceExists(
    string url, 
    bool throwExceptions, 
    out string errorMessage)
{
    try
    {
        errorMessage = string.Empty;

        // try accessing the web service directly via it's 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:


The tip: create a interface/baseclass with method "InvokeWithSomeParameters". The meaning of "SomeParameters" should be a "parameters which 100% does not affect any important state".

I think, there are 2 cases:

  • Simple webservice, which does not affect any data on server. For example: GetCurrentTime(). This web service can be called without parameters.
  • Complex webservice, which can affect some daty on server. For example: Enlist pending tasks. You fill-up parameter with values which 100% throws a exception (resp. does not change affect pending tasks), if you got some exception like "ArgumentException", you know the service is alive.

I don't think, this is most clear solution, but it should works.




回答4:


How about opening a TCP/IP connection to the port used by the webservice? If the connection works, the RAS connection, the rest of the network and the host are all working. The webservice is almost certainly running too.




回答5:


If it is a Microsoft SOAP or WCF service and service discovery is allowed, you can request the web page serviceurl + "?disco" for discovery. If what is returned is a valid XML document , you know the service is alive and well. A non-Microsoft SOAP service that does not allow ?disco will probably return valid XML too.

Sample code:

    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;
    }

If the web server is present, but the service does not exist, an exception will be raised quickly for the 404 error. The fairly long time-out in the example is to allow a slow WCF service to restart after a long period of inactivity or after iisreset. If the client needs to be responsive, you could poll with a shorter timeout until the service is available.



来源:https://stackoverflow.com/questions/330496/how-do-i-test-connectivity-to-an-unknown-web-service-in-c

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!