Catching a custom Exception thrown by a WebMethod

2020-06-17 01:42发布

问题:

I have a classical asp.net web service (asmx) and a web method in it. I need to throw a custom exception for some case in my web method, and I need to catch that specific custom exception where I call the web service method.

[WebService(Namespace = "http://tempuri.org/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
public class WebService : System.Web.Services.WebService
{
    [WebMethod]
    public HelloWorldOutput HelloWorld(HelloWorldInput input)
    {
        try
        {
            // My Code
            return new HelloWorldOutput();
        }
        catch (Exception ex)
        {
            throw new HelloWorldException("Hello World Exception", ex);
        }
    }
}

Input, output and exception classes as a sample:

public class HelloWorldInput { }
public class HelloWorldOutput { }    

[Serializable]
public class HelloWorldException : Exception
{
    public HelloWorldException() { }
    public HelloWorldException(string message) : base(message) { }
    public HelloWorldException(string message, Exception inner) 
        : base(message, inner) { }
    protected HelloWorldException(
      System.Runtime.Serialization.SerializationInfo info,
      System.Runtime.Serialization.StreamingContext context)
        : base(info, context) { }
}

In the client side, I need:

public static void Main()
{
    WebService service = new WebService();
    try
    {
        service.HelloWorld(new HelloWorldInput());
    }
    catch (HelloWorldException ex)
    {
        // Do sth with HelloWorldException
    }
    catch (Exception ex)
    {
        // Do sth with Exception
    }
}

However, I cannot do that because when I add the web service reference on the client, I have service class, input and output classes, but I do not have custom exception class.

Also another problem is that, I have also problems with serializing Exception class (because of Exception.Data property implements IDictionary interface)

Is there a way to do this in my way, or am I in a completely wrong way, or is there something I miss about fundamentals of web services?

Thanks.

回答1:

ASP.NET Web Service can throw any type of exception: SoapException, HelloWorldException or soever. However, the exception is serialized into a SOAP Fault element, and regardless of the type of the exception thrown in the service, the exception is converted into a SoapException while deserialization. Hence, it is not possible to catch the HelloWorldException with my catch block in my question, even if I deploy the HelloWorldException to the client.

For an ASP.NET client, the only way is to catch the exception as SoapException and handle it by its Actor or SoapFaultSubCode property.

I've basically solved my problem as below:

Web Service:

[WebService(Namespace = "http://tempuri.org/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
public class WebService : System.Web.Services.WebService
{
    [WebMethod]
    public HelloWorldOutput HelloWorld(HelloWorldInput input)
    {
        try
        {
            // My Code
            return new HelloWorldOutput();
        }
        catch (Exception ex)
        {
            throw new SoapException("Hello World Exception",   
                 SoapException.ServerFaultCode, "HelloWorld", ex);
        }
    }
}

Client:

public static void Main()
{
    WebService service = new WebService();
    try
    {
        service.HelloWorld(new HelloWorldInput());
    }
    catch (SoapException ex)
    {
        if(ex.Actor == "HelloWorld")
            // Do sth with HelloWorldException
    }
    catch (Exception ex)
    {
        // Do sth with Exception
    }
}

Together with the document which Bryce Fischer wrote in his answer; these msdn documents also has helpful information about throwing and handling web service exceptions.

How to: Throw Exceptions from a Web Service Created Using ASP.NET

How to: Handle Exceptions Thrown by a Web Service Method



回答2:

This may be of help. Looks like you'll get a SoapException, but you can inspect the details to determine if its your class or not.

Side note, to have access to "HelloWorldException", you can pull it out into a seperate assembly and deploy that on the client...