views:

475

answers:

6

Hello everyone,

I am developing ASP.Net asmx web services. And at client side, if the request to server returns Http error code, like http 500, how could I know from web services client side (I use the automatically generated client proxy by using add web references)?

thanks in advance, George

A: 

You can set up tracing for your webservices, a how to is below from the MSDN:

http://msdn.microsoft.com/en-us/library/bb885203.aspx

If you have access to the server also, you can set up HealthMonitoring for example which will record any errors which occur on the server side, like you posted the 500 internal server error.

Health Monitoring - http://msdn.microsoft.com/en-us/library/ms998306.aspx

You also have the ever useful Event Viewer if you can remote or log into the server.

Hope this helps:

Andrew

REA_ANDREW
Hi Andrew, your solution is at server side but I want to track at client side.
George2
A: 

You can get the info from e.Response.GetResponseStream(). As read said, you might need to look at the server side to get a more complete info.

eglasius
Good idea! But since I am using asynchronous web service call, in the complete event handler, how could I get the Response object?
George2
A: 

This is a commonly encountered problem because Web services tend only to send you a HTTP 500 (Internal server error) message on encountering an unhandled exception. I use a trick I found long back. Basically, you need to drill into the WebException using a StreamReader to determine the root cause of the exception.

Sample code: (Sorry, didn't have any C# code handy. Please use a converter)

Try
  'Hit the webservice.
Catch ex As WebException
  Dim r As HttpWebResponse = CType(ex.Response(), HttpWebResponse)
  Using sr As StreamReader = New StreamReader(r.GetResponseStream())
    Dim err As String = sr.ReadToEnd()
    'Log the error contained in the "err" variable.
  End Using
  Return Nothing
Finally
  'Clean up  
End Try

Can be converted using the DeveloperFusion converter, which I highly recommend.

Cerebrus
Your code is very very cool! But since I am using asynchronous web service call, in the complete event handler, how could I get the Response object?
George2
The Response object is extracted from the trapped Exception. Are you receiving an exception? P.S: If the answer is cool, please vote! ;-)
Cerebrus
All I could get is ArgumentNullException from client side. Content is, [System.ArgumentNullException] = {"Value cannot be null.\r\nParameter name: stream"}
George2
I think such exception happens because server sends invalid SOAP response format to client side (it sends user friendly html message)? If I could get the content of the user friendly html message, it would be great! Any ideas?
George2
A: 

See a previous question, easy-way-to-catch-all-unhandled-exceptions-in-c-net.

For web services running under IIS, it would seem that you need to catch exceptions in all threads by implementing UnhandledExceptionModule.

gimel
The solution is for server side error handling, my question is about how to get the error from client side, more specically web service proxy based client application. :-)
George2
+1  A: 

George, since you are using async WS calls, you must implement exception handling in the call back method. Eg: Following is the sample code I developed to give a demo of async delegates.

public class TransformDelegateWithCallBack
{
    /// <summary>
    /// Delegate which points to AdapterTransform.ApplyFullMemoryTransformations()
    /// </summary>
    /// <param name="filename">Transformation file name</param>
    /// <param name="rawXml">Raw Xml data to be processed</param>
    /// <param name="count">Variable used to keep a track of no of async delegates</param>
    /// <returns>Transformed XML string</returns>
    public delegate string DelegateApplyTransformations(string filename, string rawXml, int count);

    public ArrayList resultArray;


    //// Declare async delegate and result
    DelegateApplyTransformations delegateApplyTransformation;
    IAsyncResult result;

    /// <summary>
    /// Constructor to initialize the async delegates, results and handles to the no of tabs in excel
    /// </summary>
    public TransformDelegateWithCallBack()
    {
        resultArray = ArrayList.Synchronized(new ArrayList());
    }


    /// <summary>
    /// Invoke the async delegates with callback model
    /// </summary>
    /// <param name="filename">Transformation file name</param>
    /// <param name="rawXml">Raw Xml data to be processed</param>
    /// <param name="count">Variable used to keep a track of no of async delegates</param>
    public void CallDelegates(string fileName, string rawXml, int count)
    {
        try
        {
            AdapterTransform adapterTrans = new AdapterTransform();
            // In the below stmt, adapterTrans.ApplyFullMemoryTransformations is the web method being called
            delegateApplyTransformation = new DelegateApplyTransformations(adapterTrans.ApplyFullMemoryTransformations);
            // The below stmt places an async call to the web method
            // Since it is an async operation control flows immediately to the next line eventually coming out of the current method. Hence exceptions in the web service if any will NOT be caught here.
            // CallBackMethod() is the method that will be called automatically after the async operation is done
            // result is an IAsyncResult which will be used in the CallBackMethod to refer to this delegate
            // result gets passed to the CallBackMethod 
            result = delegateApplyTransformation.BeginInvoke(fileName, rawXml, count, new AsyncCallback(CallBackMethod), null);
        }
        catch (CustomException ce)
        {
            throw ce;
        }
    }

    /// <summary>
    /// Callback method for async delegate
    /// </summary>
    /// <param name="o">By default o will always have the corresponding AsyncResult</param>
    public void CallBackMethod(object o)
    {

        try
        {
            AsyncResult asyncResult = (AsyncResult)o;
            // Now when you do an EndInvoke, if the web service has thrown any exceptions, they will be caught
            // resultString is the value the web method has returned. (Return parameter of the web method)
            string resultString = ((DelegateApplyTransformations)asyncResult.AsyncDelegate).EndInvoke((IAsyncResult)asyncResult);

            lock (this.resultArray.SyncRoot)
            {
                this.resultArray.Add(resultString);
            }
        }
        catch (Exception ex)
        {
            // Handle ex
        }
    }

}

If your WS call is throwing an exception, it only gets caught when you do an EndInvoke on the AsynResult. If you are using a fire & forget mechanism of async WS call, you wont call EndInvoke and hence exception will be lost. So always use callback mechanism when you need to catch exceptions Hope this helps :)

Let me know if you have any more doubts.

Rashmi Pandit
Thanks Rashmi, sorry I have a very stupid question, which method in your code is used as web method which we called?
George2
"If your WS call is throwing an exception, it only gets caught when you do an EndInvoke on the AsynResult" -- confused. I think when using asynchronous web services call, underlying web services stack automatically helps me to call Begin/EndInvoke, so no need to call again?
George2
delegateApplyTransformation = new DelegateApplyTransformations(adapterTrans.ApplyFullMemoryTransformations);adapterTrans.ApplyFullMemoryTransformations is the web method that is being called.
Rashmi Pandit
George, i have edited my code above to add appropriate comments as there isnt enough space in the comments section.
Rashmi Pandit
A: 

Assuming you have Visual Studio import the webservice and you use the Microsoft Web Services Enhancement 3.0 library, it will probably look something like this:

 private void DoWebService()
 {
      try
      {
           MyWebService.MyWebserviceWSE WSE = new MyWebService.MyWebserviceWSE.MyWebserviceWSE();

           WSE.DoSomethingCompleted += new MyWebService.DoSomethingCompletedEventHandler(WSE_DoSomethingCompleted);

           WSE.DoSomethingAsync(/* pass arguments to webservice */);            
      }
      catch (Exception ex)
      {
           // Handle errors
      }
 }

 private void WSE_DoSomethingCompleted(object o, MyWebService.DoSomethingCompletedEventArgs args)
 {
      if (args.Error != null)
      {
           // The following gets the error and shows it in a msg box
           StringBuilder sb = new StringBuilder();

           sb.AppendLine(args.Error.ToString());

           if (args.Error.InnerException != null)
           {
               sb.AppendLine(args.Error.ToString());
           }

           MessageBox.Show(sb.ToString());
      }
      else
      {
           // Do something with the results
      }
 }

Any errors will be returned inside the 'MyWebService.DoSomethingCompletedEventArgs' object.

uzbones