Flea
Flea

Reputation: 11284

REST WCF service returns XML response but not JSON response

I am new to WCF so I think this is pretty basic. I have a simple method that a single "order" object is returned. It works just fine when using the default XML, however, when I apply the

ResponseFormat = WebMessageFormat.Json

attribute, it fails to return JSON. The code successfully executes and hits the return line but then the method is immediately called again and then finally a third time before the browser returns an error stating the connection to localhost has been interrupted.

When I remove the ResponseFormat = WebMessageFormat.Json, the method is called and XML is returned just fine. Not sure I am missing for the JSON.

IProductSales.cs

namespace ProductsSalesService
{
    [ServiceContract(Name = "ProductsSales")]
    public interface IProductsSales
    {

        [OperationContract]
        [WebGet(UriTemplate = "Orders/{orderID}", ResponseFormat = WebMessageFormat.Json)]
        [Description("Returns the details of an order")]
        SalesOrderHeader GetOrder(string orderID);

    }
}

ProductSales

public SalesOrderHeader GetOrder(string orderID)
{
    SalesOrderHeader header = null;

    try
    {
        int id = Convert.ToInt32(orderID);
        AdventureWorksEntities database = new AdventureWorksEntities();

            header = (from order in database.SalesOrderHeaders
                      where order.SalesOrderID == id
                      select order).FirstOrDefault();

    }
    catch
    {
        throw new WebFaultException(HttpStatusCode.BadRequest);
    }

    return header;
}

I am working through an sample in a WCF book so they had me build a small console application to be the host, so this is the app.config file I have for the host client.

<?xml version="1.0"?>
<configuration>
  <connectionStrings>
    <add name="AdventureWorksEntities" connectionString="metadata=res://*/ProductsSalesModel.csdl|res://*/ProductsSalesModel.ssdl|res://*/ProductsSalesModel.msl;provider=System.Data.SqlClient;provider connection string=&quot;Data Source=BINGBONG;Initial Catalog=AdventureWorks;Integrated Security=True;MultipleActiveResultSets=True&quot;" providerName="System.Data.EntityClient" />
  </connectionStrings>
<startup><supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.0"/></startup><system.serviceModel>
    <services>
      <service name="ProductsSalesService.ProductsSales">
        <endpoint address="http://localhost:8000/Sales" binding="webHttpBinding"
          bindingConfiguration="" name="ProductsSalesService.ProductsSales"
          contract="ProductsSalesService.IProductsSales" />
      </service>
    </services>
  </system.serviceModel>
</configuration>

Finally, this is just the host client code.

public class Program
    {
        static void Main(string[] args)
        {
            WebServiceHost host = new WebServiceHost(typeof(ProductsSalesService.ProductsSales));
            host.Open();
            Console.WriteLine("Service running");
            Console.WriteLine("Press ENTER to stop the service");
            Console.ReadLine();
            host.Close();
        }
    }

So when I go to http://localhost:8000/Sales/Orders/43659 to pull up my order it hits three times and the page cancels in Chrome with the following error:

This webpage is not available The connection to localhost was interrupted. Here are some suggestions: Reload this webpage later. Check your Internet connection. Restart any router, modem, or other network devices you may be using. Add Google Chrome as a permitted program in your firewall's or antivirus software's settings. If it is already a permitted program, try deleting it from the list of permitted programs and adding it again. If you use a proxy server, check your proxy settings or contact your network administrator to make sure the proxy server is working. If you don't believe you should be using a proxy server, adjust your proxy settings: Go to the wrench menu > Settings > Show advanced settings... > Change proxy settings...

LAN Settings and deselect the "Use a proxy server for your LAN" checkbox. Error 101 (net::ERR_CONNECTION_RESET): The connection was reset.

If I remove the WebMessageFormat.Json everything works fine!

Thanks for any assistance!

Upvotes: 3

Views: 5356

Answers (3)

Martin
Martin

Reputation: 16423

Although my fault is actually unrelated, this is the first article I found when looking into my problem which is that my service was failing and I was seeing an error connection has been interrupted.

My fault was to do with the fact that the class I was outputting from my WebGet method had properties that had DataContract attributes but I had not added a Set accessor to each one (because I considered them to be output-only I didn't see the point).

Adding the tracing into my configuration file quickly revealed that the fault was that there were no Set accessors, so I added private set accessors to each DataContract property and all is now working as expected.

I have added this here in case anyone else follows the same search path and has the same issue.

Upvotes: 1

Dmitry Harnitski
Dmitry Harnitski

Reputation: 6008

This line of code will construct Service Host without taking configuration into account so you will have Service but it will listen different URL.

WebServiceHost host = new WebServiceHost(typeof(ProductsSalesService.ProductsSales));

Add base address new WebServiceHost plus code below:

    WebChannelFactory<ProductsSalesService.IProductsSales> cf = 
    new WebChannelFactory<ProductsSalesService.IProductsSales>("ProductsSalesService.ProductsSales");
ProductsSalesService.IProductsSales channel = cf.CreateChannel();

See full code here - http://msdn.microsoft.com/en-us/library/bb919583

Upvotes: 0

Andrew Stephens
Andrew Stephens

Reputation: 10193

For starters try WCF tracing/logging to see if it sheds any light on things.

Put this in your server's config file (somewhere within the <configuration> element):-

<system.diagnostics>
 <sources>
  <source name="System.ServiceModel" switchValue="Error" propagateActivity="true">
    <listeners>
      <add name="traceListener" type="System.Diagnostics.XmlWriterTraceListener" initializeData="C:\Temp\server.svclog"/>
    </listeners>
  </source>
  <source name="System.ServiceModel.MessageLogging">
    <listeners>
      <add name="messages"
      type="System.Diagnostics.XmlWriterTraceListener"
      initializeData="C:\Temp\server_messages.svclog" />
    </listeners>
  </source>
 </sources>
</system.diagnostics>

And put this inside the <system.serviceModel> element:-

<diagnostics>
  <messageLogging
       logEntireMessage="true"
       logMalformedMessages="false"
       logMessagesAtServiceLevel="true"
       logMessagesAtTransportLevel="false"
       maxMessagesToLog="3000"
       maxSizeOfMessageToLog="2000"/>
</diagnostics>

Try hitting your service again and examine the .svclog files that this (hopefully) generates for clues. The files will open in a "Service Trace Viewer" tool - if not it can be downloaded from MS (part of the Win SDK I think).

Upvotes: 5

Related Questions