Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

WCF JSON Service returns XML on Fault

Tags:

json

wcf

I am running a ServiceHost to test one of my services and all works fine until I throw a FaultException - bang I get XML not JSON

my service contract - lovely

   /// <summary>
    ///   <para>Get category by id</para>
    /// </summary>
    [OperationContract(AsyncPattern = true)]
    [FaultContract(typeof(CategoryNotFound))]
    [FaultContract(typeof(UnexpectedExceptionDetail))]
    IAsyncResult BeginCategoryById(
        CategoryByIdRequest request,
        AsyncCallback callback, object state);

    CategoryByIdResponse EndCategoryById(IAsyncResult result);

Host Set-up - scrummy yum

var host = new ServiceHost(serviceType, new Uri(serviceUrl));
host.AddServiceEndpoint(
    serviceContract,
    new WebHttpBinding(), "")
        .Behaviors.Add(
             new WebHttpBehavior
                            {
                                DefaultBodyStyle = WebMessageBodyStyle.Bare,
                                DefaultOutgoingResponseFormat = WebMessageFormat.Json,
                                FaultExceptionEnabled = true
                            });

host.Open();

Here's the call - oo belly ache

var request = WebRequest.Create(serviceUrl + "/" + serviceName);
request.Method = "POST";
request.ContentType = "application/json; charset=utf-8";
request.ContentLength = 0;

try
{
    // receive response
    using (var response = request.GetResponse())
    {
        var responseStream = response.GetResponseStream();

        // convert back into referenced object for verification
        var deserialiser = new DataContractJsonSerializer(typeof (TResponseData));
        return (TResponseData) deserialiser.ReadObject(responseStream);
    }
}
catch (WebException wex)
{
    var response = wex.Response;

    using (var responseStream = response.GetResponseStream())
    {
        // convert back into fault
        //var deserialiser = new DataContractJsonSerializer(typeof(FaultException<CategoryNotFound>));
        //var fex = (FaultException<CategoryNotFound>)deserialiser.ReadObject(responseStream);

        var text = new StreamReader(responseStream).ReadToEnd();
        var fex = new Exception(text, wex);    

        Logger.Error(fex);
        throw fex;
    }
}

the text var contains the correct fault, but serialized as Xml What have I done wrong here?

like image 877
Anthony Johnston Avatar asked Jun 22 '11 13:06

Anthony Johnston


2 Answers

The answer is to implement an IErrorHandler and supporting behavior

I found this excellent post by iainjmitchell

http://iainjmitchell.com/blog/?p=142

like image 189
Anthony Johnston Avatar answered Nov 18 '22 05:11

Anthony Johnston


I can happily present the solution. I had exactly the same problem and after i messed a little with my endpoint behavior configuration i discovered the needed config element. The solution is to force wcf to use the selected format (json):

 <behavior name="ExtendedJSONBehavior">
     <webHttp defaultOutgoingResponseFormat="Json" defaultBodyStyle="Wrapped" automaticFormatSelectionEnabled="false"/>
 </behavior>

As you can see, the key was the "automaticFormatSelectionEnabled" attribute.

Have fun with wcf again

like image 2
Firzen Avatar answered Nov 18 '22 05:11

Firzen