1

I am having problem with using REST and returning response as an XML. I've created basic service from the template and everything looks nice but when I want to serialize my class and return it as a responce the service returns something else.

Take a look:

[WebHelp(Comment = "Sample description for DoWork")]
[WebInvoke(UriTemplate = "DoWork")]
[OperationContract]
public SampleResponseBody DoWork(SampleRequestBody request)
{
    //TODO: Change the sample implementation here
    return new SampleResponseBody()
    {
        Value = String.Format("Sample DoWork response: '{0}'", request.Data)

    };
}

[WebHelp(Comment = "Returns order state based on client and order number")]
[WebInvoke(UriTemplate = "OrderStatus")]
[OperationContract]
public order_status OrderStatus(q_order_status request)
{   
    return new order_status() 
    {
        error_id = 0,
        client_acr = "client", 
        order_acr = "order"
    };
}

The first method is from the template, the second is mine. Returning structures look like this:

public class SampleResponseBody
{
    [DataMember]
    public string Value { get; set; }
}

public class q_order_status
{
    public string client_acr;
    public string order_acr;
}

[DataContract]
[XmlSerializerFormat]
public class order_status
{
    [XmlAttribute]
    public int error_id;
    [XmlElement]
    public string error_desc;
    [XmlElement]
    public string order_acr;
    [XmlElement]
    public string client_acr;
}

Edited:

When I am on the help page of the REST kit, I am getting this as a sample response for both methods which is wrong (I should not get this for the second method):

<SampleResponseBody>
<Value>String content</Value>
</SampleResponseBody>

When I call first method like this:

User-Agent: Fiddler
Host: ipv4.fiddler:4617
Content-Type: text/xml
Content-Length: 63

<SampleRequestBody>
<Data>bla bla</Data>
</SampleRequestBody>

I receive:

HTTP/1.1 200 OK
Server: ASP.NET Development Server/9.0.0.0
Date: Wed, 30 Sep 2009 09:41:20 GMT
X-AspNet-Version: 2.0.50727
Cache-Control: private
Content-Type: application/xml; charset=utf-8
Content-Length: 141
Connection: Close

<SampleResponseBody xmlns:i="http://www.w3.org/2001/XMLSchema-instance"><Value>Sample DoWork response: 'bla bla'</Value></SampleResponseBody>

Whis is ok.

WHen I call second method like this:

User-Agent: Fiddler
Host: ipv4.fiddler:4617
Content-Type: text/xml
Content-Length: 115

<q_order_status>
<client_acr>String content</client_acr>
<order_acr>String content</order_acr>
</q_order_status>

I am getting this:

HTTP/1.1 200 OK
Server: ASP.NET Development Server/9.0.0.0
Date: Wed, 30 Sep 2009 09:44:18 GMT
X-AspNet-Version: 2.0.50727
Cache-Control: private
Content-Type: application/xml; charset=utf-8
Content-Length: 67
Connection: Close

<order_status xmlns:i="http://www.w3.org/2001/XMLSchema-instance"/>

And it should return a serialized to XML instance of class order_status What is wrong?

Thanks in advance.

After edit: ok, the problem was that for [OperationContract] XmlSerializer wasn't triggered. [XmlSerializerFormat] must be inserted right after the [OperationContract] to override default DataContractSerializer.

1
  • You saved me a lot of time! [XmlSerializerFormat] did the trick! Thank you so much! Commented Jun 18, 2020 at 9:37

3 Answers 3

4

With the WCF REST Starter Kit, you should be able to create a method that returns an XElement as its return value:

[WebHelp(Comment = "Returns order state based on client and order number")]
[WebInvoke(UriTemplate = "OrderStatus")]
[OperationContract]
public XElement OrderStatus(q_order_status request)
{   
  .....
}

In that case, your method implementation could look something like this:

public XElement OrderStatus(q_order_status request)
{   
    return new XElement("q_order_status",
                 new XAttribute("error_id", 0),
                 new XElement("client_acr", "client acr value"),
                 new XElement("order_acr", "order acr value")
           );
}

This would return an XML fragment like this:

<q_order_status error_id="0">
  <client_acr>client acr value</client_acr>
  <order_acr>order acr value</order_acr>
</q_order_status>

This way, anything really is possible - it's totally up to you how and what to create in terms of XML structure.

Marc

Sign up to request clarification or add additional context in comments.

2 Comments

marc_s: thanks, this is one of the ways to achieve this. But what if I would like to serialize some big object which contains other objects. In this solution I don't have serializer capabilities.. or am I wrong?
sure! You can have your q_order_status class and simply manually instantiate a XmlSerializer, and serialize an object of that type into a string and return it as a XElement. That should work just fine.
0

I would say that q_order_status should be decorated with [DataContract] attribute, and all of his members (along with those of order_status) should be decorated with [DataMember] attribute. Or did you omit these on purpose?

Can you try with this order_status code:

[DataContract]
public class order_status
{
    [DataMember]
    public int error_id;
    [DataMember]
    public string error_desc;
    [DataMember]
    public string order_acr;
    [DataMember]
    public string client_acr;
}

Side note: I would also suggest that you follow .NET naming conventions for classes and members, PascalCase and no underscore. If you are restricted to a given xml name, you can use the Name member of the DataContract/DataMember attribute to define the xml name. (eg: [DataContract(Name="order_status")] public class OrderStatus). ;)

6 Comments

@Philippe: q_order_status is passed as a parameter and it works fine. I need to return order_status in a deserialized XML. I am calling the service correctly via HTTP, but I will show you how. .NET conventions: the problem is that I need to deserialize it to the exact XML structure which was not definied by me.
Can you try adding the [DataMember] attribute to all the members of the order_status class?
Side note again: you can follow .NET naming convention and define the xml name of the element using the Name member of the DataContract/DataMember attribute: msdn.microsoft.com/en-us/library/…
I know, buf before I will start to mess with it. I want to obtain a basic result and it doesn't work.
From what I see, the response order_status contains no element. Can you try, as I said before, to add [DataMember] attributes to the order_status members (eddited the answer)?
|
0

This question (and the last edit) helped us to solve a similar problem. Instead of decorating thousands of data elements with DataContract/DataMember attributes and using the (default) DataContractSerializer, we found that if our WCF service used the XmlSerializerFormat instead, we could easily deserialize our objects.

For those who need an example:

[System.ServiceModel.ServiceContract]
public interface IRestService
{
    [System.ServiceModel.OperationContract]
    // Added this attribute to use XmlSerializer instead of DataContractSerializer
    [System.ServiceModel.XmlSerializerFormat(
        Style=System.ServiceModel.OperationFormatStyle.Document)]
    [System.ServiceModel.Web.WebGet(
        ResponseFormat = System.ServiceModel.Web.WebMessageFormat.Xml,
        UriTemplate = "xml/objects/{myObjectIdentifier}")]
    MyObject GetMyObject(int myObjectIdentifier);
}

This is how we're deserializing the objects:

public static T DeserializeTypedObjectFromXmlString<T>(string input)
{
    T result;

    try
    {
        System.Xml.Serialization.XmlSerializer xs = new System.Xml.Serialization.XmlSerializer(typeof(T));
        using (System.IO.TextReader textReader = new System.IO.StringReader(input))
        {
            result = (T)xs.Deserialize(textReader);
        }
    }
    catch
    {
        throw;
    }

    return result;
}

1 Comment

I am glad that it helped you!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.