Rwiti
Rwiti

Reputation: 1066

how to extract faultcode from a WCF message in AfterReceiveReply

This is what I ideally want to do

    public void AfterReceiveReply(ref Message reply, object correlationState) 
    {
        if (reply.IsFault)
        {
            FaultException exp = reply.GetBody<FaultException>();
            if (exp.Code.Name == "MyFaultCode")
            {
               //Do something here
            }
        }
    } 

but I get this exception

Error in line 1 position 82. Expecting element 'FaultException' from namespace 'http://schemas.datacontract.org/2004/07/System.ServiceModel'.. Encountered 'Element' with name 'Fault', namespace 'http://schemas.xmlsoap.org/soap/envelope/'.

when I try to do

FaultException exp = reply.GetBody<FaultException>();

From the server side this is how I throw the exception.

public object AfterReceiveRequest(ref Message request, IClientChannel channel, InstanceContext             
                                  instanceContext)
{
    throw new FaultException("MyFaultCode", new FaultCode("MyFaultCode"));
}

Can someone please tell me how to deserialize the Fault Exception from the message so that I can access the FaultCode?

Upvotes: 3

Views: 4003

Answers (3)

Sielu
Sielu

Reputation: 1110

you can extract fault information directly from System.ServiceModel.Channels.Message class (here in message variable):

var fault = MessageFault.CreateFault(message, int.MaxValue);

Then from this fault you can read fault code or message:

var error = fault.Reason.GetMatchingTranslation().Text;

To sum up, you can create a simple validation method:

private static void ValidateMessage(Message message)
    {
        if (!message.IsFault) return;
        var fault = MessageFault.CreateFault(message, int.MaxValue);
        var error = fault.Reason.GetMatchingTranslation().Text;
        //do something :)
    }

Upvotes: 3

Rwiti
Rwiti

Reputation: 1066

This is how I actually did it... Stack Overflow solution

public void AfterReceiveReply(ref Message reply, object correlationState)
    {
        if (reply.IsFault)
        {
            MessageBuffer buffer = reply.CreateBufferedCopy(Int32.MaxValue);

            XmlDictionaryReader xdr = buffer.CreateMessage().GetReaderAtBodyContents();
            XNode xn = XDocument.ReadFrom(xdr);
            string s = xn.ToString();
            XDocument xd = XDocument.Parse(s);
            XNamespace nsSoap = "http://schemas.xmlsoap.org/soap/envelope/";
            XNamespace ns = "";
            XElement xErrorCode = xd.Element(nsSoap + "Fault").Element("faultcode");

            if (xErrorCode.Value.Contains("MyFaultCode"))
            {
             // Redirect to login page
            }

            reply = buffer.CreateMessage();
            buffer.Close();
        }
    }

Upvotes: 2

ture
ture

Reputation: 1

I don't know if .NET has that type built in, but here's how you can generate it yourself:

  1. Download http://schemas.xmlsoap.org/soap/envelope/
  2. Run the command:

    svcutil /dconly /importxmltypes envelope.xml
    

But is this really what you "ideally want to do"?

If you're throwing that FaultException is the server, shouldn't you be able to catch it directly in the client?

Or even better, use the FaultContract attribute on your operation contracts to handle custom fault exceptions.

Upvotes: 0

Related Questions