views:

2167

answers:

5

I have a simple web service operation like this one:

    [WebMethod]
    public string HelloWorld()
    {
        throw new Exception("HelloWorldException");
        return "Hello World";
    }

And then I have a client application that consumes the web service and then calls the operation. Obviously it will throw an exception :-)

    try
    {
        hwservicens.Service1 service1 = new hwservicens.Service1();
        service1.HelloWorld();
    }
    catch(Exception e)
    {
        Console.WriteLine(e.ToString());
    }

In my catch-block, what I would like to do is extract the Message of the actual exception to use it in my code. The exception caught is a SoapException, which is fine, but it's Message property is like this...

System.Web.Services.Protocols.SoapException: Server was unable to process request. ---> System.Exception: HelloWorldException
   at WebService1.Service1.HelloWorld() in C:\svnroot\Vordur\WebService1\Service1.asmx.cs:line 27
   --- End of inner exception stack trace ---

...and the InnerException is null.

What I would like to do is extract the Message property of the InnerException (the HelloWorldException text in my sample), can anyone help with that? If you can avoid it, please don't suggest parsing the Message property of the SoapException.

A: 

I think you need to re-throw the exception

try
{
   // Something
}
catch
{
     throw;
}

That will re-throw the exception. Details here.

IainMH
A: 

I can't see how this is going to help me because I don't want to re-throw the exception!

I want to have a Console.WriteLine command in my catch-block, which then writes out the message of the original exception, which incidentally got thrown on the server side and was wrapped with a SoapException on the client side.

Basically, I would like to change my client code to something like:

try
{
    hwservicens.Service1 service1 = new hwservicens.Service1();
    service1.HelloWorld();
}
catch(Exception e)
{
    Console.WriteLine(e.InnerException.Message);
}

But unfortunately the InnerException property is empty in the SoapException that I catch on the client side. This is what I need help with.

Alfred B. Thordarson
@Alfred: Your discussion throughout this question thread makes it really hard to read. Please edit your original question and delete these answers so we can understand. Thank you! :-)
Alex Angas
+3  A: 

Unfortunately I don't think this is possible.

The exception you are raising in your web service code is being encoded into a Soap Fault, which then being passed as a string back to your client code.

What you are seeing in the SoapException message is simply the text from the Soap fault, which is not being converted back to an exception, but merely stored as text.

If you want to return useful information in error conditions then I recommend returning a custom class from your web service which can have an "Error" property which contains your information.

[WebMethod]
public ResponseClass HelloWorld()
{
  ResponseClass c = new ResponseClass();
  try 
  {
    throw new Exception("Exception Text");
    // The following would be returned on a success
    c.WasError = false;
    c.ReturnValue = "Hello World";
  }
  catch(Exception e)
  {
    c.WasError = true;
    c.ErrorMessage = e.Message;
    return c;
  }
}
samjudson
+1  A: 

I ran into something similar a bit ago and blogged about it. I'm not certain if it is precisely applicable, but might be. The code is simple enough once you realize that you have to go through a MessageFault object. In my case, I knew that the detail contained a GUID I could use to re-query the SOAP service for details. The code looks like this:

catch (FaultException soapEx)
{
    MessageFault mf = soapEx.CreateMessageFault();
    if (mf.HasDetail)
    {
        XmlDictionaryReader reader = mf.GetReaderAtDetailContents();
        Guid g = reader.ReadContentAsGuid();
    }
}
Jacob Proffitt
A: 

I have looked at this better, and to me, it seems that Sam's answer is the best one in general - it will work for any .NET version and any web service you want to write. Thank you Sam.

However, it is not a very elegant solution because, from your operation, you have to return a type that has nothing to do with the actual type you want to return. So you return something like ResponseClass that encapsulates the string type you want to return, instead of simply returning the plain string type. Makes my services more difficult to read and understand!

If using .NET 3.5 and WCF it seems like Jacob's solution is better than the best :-)

What I mean is that when developing my web service I can throw a FaultException (instead of the plain Exception class) and attach any kind of detail, which can then be extracted on the client side. The solution has nothing to do with the signature of my web service operation, making it easy to understand. Thank you Jacob.

Alfred B. Thordarson