locked
Format of Restful Errors RRS feed

  • Question

  • Hi I'm creating a Restful WCF web services that serves up JSON and XML. I believe with wcf 4 you can specify an error object which will return a detailed error to the client in JSON. Is there any way of completely overriding this and return text and therefore have complete control over the format of the error? I was thinking of the starter kit but was a little worried that it may become unsupported.

    Chris


    • Edited by Fresno Bob Sunday, February 19, 2012 2:23 PM
    Sunday, February 19, 2012 2:22 PM

Answers

  • You can use an error handler to do that. Inside the error handler you can create a response with whichever format you want. The code below shows how to convert exceptions thrown by the code in "simple" text (i.e., content-type of text/plain).

        public class Post_fdb4ea47_18e3_4169_8e1d_0d1ca2b449dc
        {
            [ServiceContract]
            public interface ITest
            {
                [WebGet(ResponseFormat = WebMessageFormat.Json)]
                string Echo(string text);
            }
            public class Service : ITest
            {
                public string Echo(string text)
                {
                    if (text == "exception")
                    {
                        throw new ArgumentException("Simple exception");
                    }
                    else if (text == "nestedException")
                    {
                        throw new ArgumentException("Outer exception",
                            new InvalidOperationException("Inner exception 1",
                                new ArgumentOutOfRangeException("text", "Inner exception 2")));
                    }
                    else
                    {
                        return text;
                    }
                }
            }
            class MyErrorHandler : IEndpointBehavior, IErrorHandler
            {
                public void AddBindingParameters(ServiceEndpoint endpoint, BindingParameterCollection bindingParameters)
                {
                }
    
                public void ApplyClientBehavior(ServiceEndpoint endpoint, ClientRuntime clientRuntime)
                {
                }
    
                public void ApplyDispatchBehavior(ServiceEndpoint endpoint, EndpointDispatcher endpointDispatcher)
                {
                    endpointDispatcher.ChannelDispatcher.ErrorHandlers.Add(this);
                }
    
                public void Validate(ServiceEndpoint endpoint)
                {
                }
    
                public bool HandleError(Exception error)
                {
                    return true;
                }
    
                public void ProvideFault(Exception error, MessageVersion version, ref Message fault)
                {
                    StringBuilder sb = new StringBuilder();
                    sb.AppendFormat("{0}: {1}", error.GetType().FullName, error.Message);
                    Exception inner = error.InnerException;
                    while (inner != null)
                    {
                        sb.AppendLine();
                        sb.AppendFormat("    {0}: {1}", inner.GetType().FullName, inner.Message);
                        inner = inner.InnerException;
                    }
    
                    fault = Message.CreateMessage(version, null, new MyBodyWriter(sb.ToString()));
                    fault.Properties.Add(WebBodyFormatMessageProperty.Name, new WebBodyFormatMessageProperty(WebContentFormat.Raw));
                }
    
                class MyBodyWriter : BodyWriter
                {
                    string text;
                    public MyBodyWriter(string text)
                        : base(true)
                    {
                        this.text = text;
                    }
    
                    protected override void OnWriteBodyContents(XmlDictionaryWriter writer)
                    {
                        writer.WriteStartElement("Binary");
                        byte[] bytes = Encoding.UTF8.GetBytes(this.text);
                        writer.WriteBase64(bytes, 0, bytes.Length);
                        writer.WriteEndElement();
                    }
                }
            }
            public static void Test()
            {
                string baseAddress = "http://" + Environment.MachineName + ":8000/Service";
                ServiceHost host = new ServiceHost(typeof(Service), new Uri(baseAddress));
                ServiceEndpoint endpoint = host.AddServiceEndpoint(typeof(ITest), new WebHttpBinding(), "");
                endpoint.Behaviors.Add(new WebHttpBehavior());
                endpoint.Behaviors.Add(new MyErrorHandler());
                host.Open();
                Console.WriteLine("Host opened");
    
                Util.SendRequest(baseAddress + "/Echo?text=no+exception", "GET", null, null);
                Util.SendRequest(baseAddress + "/Echo?text=exception", "GET", null, null);
                Util.SendRequest(baseAddress + "/Echo?text=nestedException", "GET", null, null);
    
                Console.Write("Press ENTER to close the host");
                Console.ReadLine();
                host.Close();
            }
        }
    


    Carlos Figueira

    • Marked as answer by Yi-Lun Luo Friday, February 24, 2012 8:05 AM
    Sunday, February 19, 2012 6:09 PM