Gregory Nozik
Gregory Nozik

Reputation: 3372

Adding dynamic datamembers to DataContract

I have WCF service that return Json.

Data contract defined below

  [DataContract]
    public class OptionData
    {
        [DataMember]
        public string Book { get; set; }
        [DataMember]
        public string Id { get; set; }
        [DataMember]
        public string DealId { get; set; }
        [DataMember]
        public string DeliveryDate { get; set; }
        [DataMember]
        public string ExpiryDate { get; set; }
   }

And Operation Contract defined as follows

[Description("Returns List of Options by user id")]
        [WebGet(UriTemplate = "{sessionId}/Application/{applicationId}?start={start}&limit={limit}&page={page}", ResponseFormat = WebMessageFormat.Json)]
        public List<OptionData> GetAllTask(string sessionId, string applicationId)

I need to add dynamically new DataMember field to the OptionData class .

What is the best practice to do it ?

Upvotes: 4

Views: 8167

Answers (5)

brando
brando

Reputation: 8431

I just ran up against this exact issue as i posted recently here: Configuring WCF data contract for proper JSON response

My solution was to use ExpandoObject. However, I had to use Newtsoft.json to do the JSON serialization then I had to make my webservice return raw text (rather than rely on the WCF serialization). I would be happy to post my code if you like. There may be a way to do dynamic datacontracts, but I wasn't able to figure that out. But my solution does the job.

Upvotes: 1

SliverNinja - MSFT
SliverNinja - MSFT

Reputation: 31651

If you know you want JSON, you could always control the serialization yourself (see this post) - just return a string of JSON using an existing library.

Another option is to just us IsRequired = false if you know all the possible field names.

The final alternative is to use the same pattern WCF uses for Forward-Compatible Contracts - just attach all unknown properties to single collection object (ExtensionData). ExtensionData is just a dictionary of key/value pairs according to this post. Unfortunately - ExtensionData is not writable directly. This would be my approach to simulate what IExtensibleDataObject is doing...

[DataContract]
public class OptionData 
{
    [DataMember]
    public string Book { get; set; }
    [DataMember]
    public string Id { get; set; }
    [DataMember]
    public string DealId { get; set; }
    [DataMember]
    public string DeliveryDate { get; set; }
    [DataMember]
    public string ExpiryDate { get; set; }
    [DataMember]
    public Dictionary<string, string> Metadata { get; set;}
} 

Upvotes: 1

Sixto Saez
Sixto Saez

Reputation: 12680

As long as the client receiving the json knows how to handle dynamically added class members, you can use the Expando object strategy outlined in the accepted answer to this SO question. It uses the ServiceStack library but you may be able extract the necessary code to do what you want. A simple key/value pair approach from an ExpandoObject is documented in this code snippet.

EDIT: I should point out that this approach wouldn't rely on WCF so it may not be what you need given the context of the question.

Upvotes: 2

chris.house.00
chris.house.00

Reputation: 3301

If you need to dynamically control the data structures your RESTful service is returning, I think your only option is to return something like an XDocument. Your service operation could create an XDocument of an arbitrary structure and return that. That being said, I'm not sure what would happen when WCF tries to serialize an XDocument to JSON.

Upvotes: 0

Tad Donaghe
Tad Donaghe

Reputation: 6588

I don't think this is possible.

Let's think about what your DataContract is for a moment: it's how your service defines what it knows about - either as input or output. A client has to either find this out through meta-data exchange discovery or from a static proxy class (in a dll probably) that you provide.

If you change your contract on the fly, there's no mechanism for your service to let its clients know that the contract has changed. There's just no way to change that contract on the fly.

Even if you changed the definition of the class on the fly, including the proper attributes, etc, the client would not be able to find out about it since the contract had already previously been published.

I can't imagine what kind of mechanism would be needed to communicate changes like this on the fly with a client.

The only workaround I can think of is to have a parameter that takes in a string and allows clients to pass in XML or similar which could be just about anything. That's a pretty nasty hack though...

Upvotes: 1

Related Questions