views:

106

answers:

3

Hello everybody,

I am currently working on a WCF application that consumes a Rails REST Service. The problem is when I do a update or remove request, Rails does not return XML, only the following header:

HTTP/1.1 200 OK
Date: Wed, 13 Jan 2010 13:56:25 GMT
Server: Apache/2.2.14 (Debian)
X-Powered-By: Phusion Passenger (mod_rails/mod_rack) 2.2.7
X-Runtime: 20
Cache-Control: private, max-age=0, must-revalidate
Set-Cookie: _Shop-R+Server_session=BAh7BzoPc2Vzc2lvbl9pZCIlODY0NmZlZjQyZTg1OTcyNTE0ZTRlN2NkNTcyZDVmYTEiCmZsYXNoSUM6J0FjdGlvbkNvbnRyb2xsZXI6OkZsYXNoOjpGbGFzaEhhc2h7BjoLbm90aWNlIidDdXN0b21lciB3YXMgc3VjY2Vzc2Z1bGx5IHVwZGF0ZWQuBjoKQHVzZWR7BjsHRg%3D%3D--88d0f739a64ea3a92e3a034d73365393dcfeee1e; path=/; HttpOnly
Content-Length: 1
Status: 200
Content-Type: application/xml; charset=utf-8

This is to be expected and correct as far as I know. However when calling the following service request from WCF we get a ProtocolException (InnerException: XMLException Unexpected end of file).

    [ServiceContract]
    [XmlSerializerFormat]
    public interface ICustomerService
    {

        [OperationContract]
        [WebGet(
            BodyStyle = WebMessageBodyStyle.Bare,
            ResponseFormat = WebMessageFormat.Xml, 
            UriTemplate = "customers/{id}.xml")]
        Customer GetCustomer(string id);

        [OperationContract]
        [WebInvoke(
            BodyStyle = WebMessageBodyStyle.Bare,
            UriTemplate = "customers/{id}.xml",
            Method = "PUT")]
        void UpdateCustomer(string id, Customer newCustomer);

        [OperationContract]
        [WebInvoke(
            BodyStyle = WebMessageBodyStyle.Bare,
            ResponseFormat = WebMessageFormat.Xml,
            UriTemplate = "customers.xml",
            Method = "POST")]
        Customer CreateCustomer(Customer newCustomer);

        [OperationContract]
        [WebInvoke(
            BodyStyle = WebMessageBodyStyle.Bare,
            UriTemplate = "customers/{id}.xml",
            Method = "DELETE")]
        void DeleteCustomer(string id);

    }

The GetCustomer and CreateCustomer methods work without a problem, UpdateCustomer and DestroyCustomer throw the exception. We suspect this is because XML is expected as a response.

Does anybody have any experience with Rails and WCF and knows a solution/workaround for this problem?

For completeness here are the exception details:

ProtocolException {"There is a problem with the XML that was received from the network. See inner exception for more details."}

XMLException (InnerException) {"Unexpected end of file."} StackTrace:

   at System.Xml.EncodingStreamWrapper.ProcessBuffer(Byte[] buffer, Int32 offset, Int32 count, Encoding encoding)
   at System.Xml.XmlUTF8TextReader.SetInput(Byte[] buffer, Int32 offset, Int32 count, Encoding encoding, XmlDictionaryReaderQuotas quotas, OnXmlDictionaryReaderClose onClose)
   at System.Xml.XmlDictionaryReader.CreateTextReader(Byte[] buffer, Int32 offset, Int32 count, Encoding encoding, XmlDictionaryReaderQuotas quotas, OnXmlDictionaryReaderClose onClose)
   at System.ServiceModel.Channels.TextMessageEncoderFactory.TextMessageEncoder.UTF8BufferedMessageData.TakeXmlReader()
   at System.ServiceModel.Channels.BufferedMessageData.GetMessageReader()
   at System.ServiceModel.Channels.BufferedMessage..ctor(IBufferedMessageData messageData, RecycledMessageState recycledMessageState, Boolean[] understoodHeaders)
   at System.ServiceModel.Channels.TextMessageEncoderFactory.TextMessageEncoder.ReadMessage(ArraySegment`1 buffer, BufferManager bufferManager, String contentType)
   at System.ServiceModel.Channels.WebMessageEncoderFactory.WebMessageEncoder.ReadMessage(ArraySegment`1 buffer, BufferManager bufferManager, String contentType)
   at System.ServiceModel.Channels.HttpInput.DecodeBufferedMessage(ArraySegment`1 buffer, Stream inputStream)
+1  A: 
Content-Length: 1
Content-Type: application/xml; charset=utf-8

Is not a valid XML response.

Darin Dimitrov
Good point, this concerns default rails code. We rather not chance the rails code since this is used in another application.Code for destroy action:respond_to do |format| format.html { redirect_to(customers_url) } format.xml { head :ok }endThis produces the exception in the WCF Client. If the action reponds with XML, like get, this is not a problem.Code for show (get) action:respond_to do |format| format.html # new.html.erb format.xml { render :xml => @customer }end
Ferdy
A: 

I've already found it, thanks to "Darin Dimitrov" and "Nate Bross". They were right that WCF expects XML when you set the content-type to application/xml. I've changed the content-type to text/plain (in rails) and it works.

Change the following in your rails formatting:

format.xml { head :ok }

to

format.xml { head :ok, :content_type => 'text/plain' }
Ferdy
A: 

Go download the REST Starter Kit Preview 2 and take a look at the Microsoft.Http namespace. Using this library doing the POST to the Rails interface is as easy as this:

var client = new HttpClient("http://railsinterface.com");
var content = HttpContent.CreateXmlSerializable<Customer>(customer);
var response = client.Post("customers.xml",content);
Darrel Miller