views:

37

answers:

1

Hey all,

I'm implementing a lo-REST API and looking to return either XML or JSON. Building it in .NET WCF.

I like the design of both Flickr and Last FM APIs which wrap their variable complex types in a simple response ala:

<lfm status="ok">
  <user>
    <name>RJ</name>
    <realname>Richard Jones </realname>
    <country>UK</country>
    <age>27</age>
  </user>
</lfm>

or

<lfm status="ok">
  <track>
    <name>Best track ever</name>
    <album>Thriller</album>
  </user>
</lfm>

or

<lfm status="fail">
  ... error details
</lfm>

Serialization of the complex types is simple as you'd expect (using DataContract, DataMember etc). But wrapping it in some kind of custom response is tripping me up because of the variable complex types that may be contained inside. Giving the response a member of type object which is filled by the complex type does not serialize:

[DataContract]
public class Response
{
    public enum ResponseStatus
    {
        ok,
        fail
    }

    [DataMember]
    public ResponseStatus Status { get; set; }

    [DataMember]
    public object Data { get; set; }

}

Any ideas or help is greatly appreciated.

Many thanks, Alex

EDIT: Tim Roberts provides an interesting solution although it doesn't serialise nicely. An option is to have all potential complex types as properties with [DataMember(EmitDefaultValue = false)] specified so nulls do not serialise. Not sure this is the best solution though.

+1  A: 

You could define a class hierarchy for your Data types within Response:

e.g.,

[DataContract]
public abstract class Data
{ }

[DataContract]
public class FooData : Data
{ }

[DataContract]
public class BarData : Data
{ }

then indicate the known-types on the Response class:

[DataContract]
[KnownType(typeof(FooData))]
[KnownType(typeof(BarData))]
public class Response
{
    public enum ResponseStatus
    {
        ok,
        fail
    }

    [DataMember]
    public ResponseStatus Status { get; set; }

    [DataMember]
    public Data Data { get; set; }
}
Tim Roberts
Actually, it makes more sense to put the [KnownType] attribute on the Data class.
Tim Roberts
This is almost there. The problem is how it serialises. You end up with a node like <Data i:type="User"> instead of <User>.
Alexander Bobin