views:

153

answers:

4

Is there a good way to check if a web service is available that does not involve simply calling a served method?

That is, I was looking for something like a .TryConnect() or .IsAvailable() method I could call before calling my .TransferData(data) method.

I've tried reading the State variable of the service, but it even while the service is throwing EndpointNotFoundExceptions, it's reporting itself in the "Opened" state, and not "Faulted" like I had hoped.

I'm using synchronous data calls, and the web service implements IDataTransferService, if that helps. Also--.NET 3.5.

+4  A: 

The only reliable way is to actually invoke the method and retry if it fails. No matter what preliminary checks you do the service could report that it is running and go offline at the moment you call it.

Darin Dimitrov
+3  A: 

No, there is no better way. Just call the simplest WebMethod. Some services provide a dummy method or GetVersion() more or less for this purpose.

And then catch the TimeOut exception.

Henk Holterman
A: 

You can attempt to make a WebRequest that checks the wsdl of the web service. It's not a guarantee, but in most cases, if the service will serve the wsdl it'll serve the function as well. Here's one I wrote to test basic availability of a service.

Dim _streamReader As StreamReader
Dim responseString As New StringBuilder()

_streamReader = New StreamReader(Me.Response.GetResponseStream())
responseString.Append(_streamReader.ReadToEnd())
_streamReader.Close()
_streamReader = Nothing

If responseString.ToString().Contains("<wsdl:definitions") AndAlso _
    responseString.ToString().Contains("</wsdl:definitions>") Then
    wsdlVerified = True
Else
    Throw New Exception("The response did not generate valid wsdl.")
End If

Where the properties for this class serve the code above:

Public Property Url() As String
    Get
        Return _url.Trim()
    End Get
    Set(ByVal value As String)
        _url = value.Trim()
    End Set
End Property

Public ReadOnly Property Request() As System.Net.HttpWebRequest
    Get
        If _request Is Nothing AndAlso Me.Url.Trim.Length > 0 Then _
            _request = CType(System.Net.HttpWebRequest.Create(Me.Url & "?wsdl"), _
                System.Net.HttpWebRequest)
        Return _request
    End Get
End Property

Public ReadOnly Property Response() As System.Net.HttpWebResponse
    Get
        If _response Is Nothing AndAlso Me.Url.Trim().Length > 0 Then _
            _response = CType(Request.GetResponse(), System.Net.HttpWebResponse)
        Return _response
    End Get
End Property

EDIT: I'd refactor this into C# but it is fairly basic and should translate easily.

Joel Etherton
I think you mentioned the main problem yourself: It's not guaranteed (that ?wsdl is supported).
Henk Holterman
@Henk - Actually, he said his service is a C# 3.5 service. So ?wsdl is supported by default. However, just because it produces wsdl doesn't mean that the service is all well and dandy. If the wsdl file is static rather than auto-generated, it would return the wsdl even if the service was dead. The code I posted above works for me because I control the services, they are auto-generated and are done with the .Net framework so ?wsdl is supported. It isn't a perfect solution, and I'd say calling a custom SYN/ACK function would be more ideal, but he asked for an alternative, so I threw one up.
Joel Etherton
Joel, "by default on" yes, but still optional.
Henk Holterman
Thanks for the code! I assume this call would also be subject to timeout like a method call would be. Is this correct? Or would it fail faster than with the method call?
Klay
They're both WebRequests so a standard "not available" timeout would be identical. However, a wsdl query will respond faster than a method call if the timeout is something in the back end (SQL call/file look up/etc). This check will only test to see that the service is there and responding as expected. Subsequent dependencies could be deficient and this would not expose them.
Joel Etherton
A: 

We are using a cached proxy client in one of our projects. In order to guarantee that the connection stays alive, we've created a simple Ping Operation in the Service. We call this method every x seconds, and report in the log if the Ping operation failed. You can expand this to also find the reason for the fail - timeouts or communication errors would indicate service unavailable. Of course this method is only possible when you have both service and client under your control.

Wagner Silveira