Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

WCF Rest service error handling & WebChannelFactory

From my understanding the following should properly throw a custom error from a WCF Rest service:

[DataContract(Namespace = "")]
public class ErrorHandler
{
    [DataMember]
    public int errorCode { get; set; }

    [DataMember]
    public string errorMessage { get; set; }
} // End of ErrorHandler

public class Implementation : ISomeInterface
{
    public string SomeMethod()
    {
        throw new WebFaultException<ErrorHandler>(new ErrorHandler()
        {
            errorCode = 5,
            errorMessage = "Something failed"
        }, System.Net.HttpStatusCode.BadRequest);
    }
}

In Fiddler this seems to work, I get the following raw data:

HTTP/1.1 400 Bad Request
Cache-Control: private
Content-Length: 145
Content-Type: application/xml; charset=utf-8
Server: Microsoft-IIS/7.5
X-AspNet-Version: 4.0.30319
Set-Cookie: ASP.NET_SessionId=gwsy212sbjfxdfzslgyrmli1; path=/; HttpOnly
X-Powered-By: ASP.NET
Date: Thu, 03 May 2012 17:49:14 GMT

<ErrorHandler xmlns:i="http://www.w3.org/2001/XMLSchema-instance"><errorCode>5</errorCode><errorMessage>Something failed</errorMessage></ErrorHandler>

But now on my client side I have the following code:

WebChannelFactory<ISomeInterface> client = new WebChannelFactory<ISomeInterface>(new Uri(targetHost));

ISomeInterface someInterface = client.CreateChannel();
try
{
  var result = someInterface.SomeMethod();
}
catch(Exception ex)
{
   // Try to examine the ErrorHandler to get additional details.
}

Now when the code runs, it hits the catch and is a System.ServiceModel.ProtocolException with the message 'The remote server returned an unexpected response: (400) Bad Request.'. It seems that I have no way to see the ErrorHandler details at this point. Has anyone run into this? Is there a way I can get the ErrorHander details at this point?

like image 906
Kyle Avatar asked Oct 07 '22 22:10

Kyle


1 Answers

WebChannelFactory or ChannelFactory will only disclose to you the generic CommunicationException. You will need to use a IClientMessageInspector behavior or rely on WebRequest to return the actual error.

For the IClientMessageInspector approach - see the comments in this blog entry.

For the WebRequest approach, you can you the following to catch the WebException.

try { }
catch (Exception ex)
{
    if (ex.GetType().IsAssignableFrom(typeof(WebException)))
    {
        WebException webEx = ex as WebException;
        if (webEx.Status == WebExceptionStatus.ProtocolError)
        {
            using (StreamReader exResponseReader = new StreamReader(webEx.Response.GetResponseStream()))
            {
                string exceptionMessage = exResponseReader.ReadToEnd();
                Trace.TraceInformation("Internal Error: {0}", exceptionMessage);
            }
        }
    }
}
like image 162
SliverNinja - MSFT Avatar answered Oct 12 '22 12:10

SliverNinja - MSFT