7

I want to return an anonymous type over WCF. Is this possible?

marc_s
  • 732,580
  • 175
  • 1,330
  • 1,459
Tamim Sadikali
  • 203
  • 4
  • 11
  • How does the client know what the type will be? – Steve Severance Oct 14 '09 at 15:45
  • This is a _wrong_ thing to do, even if you use untyped contract – Krzysztof Kozmic Oct 15 '09 at 09:56
  • 2
    Here are couple ideas why someone would need this. 1. The client could be Javascript handling JSON responses, having no idea of the type anyway. 2. One might want to be able to make 'generic' requests to WCF without having to maintain numerous response types. It's sad that only (positive) answer (@dave-ward) so far appears to lack configuration details that actually make this possible. – tishma Mar 30 '12 at 10:05

7 Answers7

4

You cannot use anonymous types, but maybe you are talking about WCF and untyped messages?

There is an option in WCF to just define a parameter of type Message (and possibly a return value of the same type). This is just the raw message that goes to WCF (and comes back from it).

I can't find much good information out there - there's some documentation on MSDN, but the best I've seen so far is Kurt Claeys' blog post WCF : Untyped messages on WCF operations.

I would not recommend using this approach - it's a lot more grunt work to handle the message contents directly yourself and that's what WCF is trying to spare us from - but if you absolutely, positively have to tweak every bit of your message - this seems like the way to go.

Marc

Glorfindel
  • 21,988
  • 13
  • 81
  • 109
marc_s
  • 732,580
  • 175
  • 1,330
  • 1,459
3

You can't return an anonymous type from any method, can you? So why would you be able to return it from WCF?

John Saunders
  • 160,644
  • 26
  • 247
  • 397
  • I don't understand this downvote - John is absolutely right, anonymous types cannot be returned from any .NET method, you can only ever use them **within** your current method. Why a downvote for a response that's 100% correct...... – marc_s Oct 17 '09 at 09:14
  • 1
    Not entirely. You can return anonymous types as "object", and this works just fine with Web API and the JSON serializer. – Steve Andrews Nov 03 '15 at 01:48
  • This question is about WCF in general, not about Web API. Also, JSON format includes the field names. It can be serialized and deserialized fine for JavaScript. But try serializing the string value "20" will it deserialize as a string or an integer. It doesn't matter to Javascript but likely matters to C#. Be careful how you define "works just fine". – John Saunders Nov 03 '15 at 03:06
1

OK, I understand. But then if I define a type - MyObj - for this purpose and mark its members IsRequired=false, how can I create+send across an instance of MyObj with only some of its members? Is this possible??

Take a look at [DataMember(EmitDefaultValue=false)]

John Saunders
  • 160,644
  • 26
  • 247
  • 397
Eugene Osovetsky
  • 6,443
  • 2
  • 38
  • 59
1

Looks like you cannot do so with the XML Serializer because of some complaint about a parameterless constructor but it works for the json serializer if you are serving to an ajax client as indicated by Dave Ward.

Vikram A
  • 11
  • 1
0

No, it is not. You'll have to define your types ahead of time.

Randolpho
  • 55,384
  • 17
  • 145
  • 179
  • OK, I understand. But then if I define a type - MyObj - for this purpose and mark its members IsRequired=false, how can I create+send across an instance of MyObj with only some of its members? Is this possible?? – Tamim Sadikali Oct 14 '09 at 15:50
  • See the answers of either Eugene Osovetsky or marc_s. Either route will help you. I'd say marc_s' answer is probably your best one for your problem. – Randolpho Oct 14 '09 at 18:10
0

You can use the ExpandoObject. When you define a property in a DTO as ExpandoObject the client is generated as Dictionary:

Contract DTO

public class TaskDTO
{
    public string Type { get; set; }
    public ExpandoObject Args { get; set; }
    public string Id { get; set; }
    public TaskDTO SuccessTask { get; set; }
    public TaskDTO FailTask { get; set; }
    public bool IsFinal { get; set; }
}

Client

using (var client = new JobServiceClient())
{
    var task = new TaskDTO
    {
        Id = Guid.NewGuid().ToString(),
        Type = "SendEmailTask",
        IsFinal = true
    };
    dynamic args = new ExpandoObject();
    args.To = "who@mail.com";
    args.Title = "test job service";
    args.Content = "test job service";
    task.Args = ((IDictionary<string, object>)args).ToDictionary(i => i.Key, i => i.Value);
    client.Execute(task);
}

Service

dynamic args = dto.Args;
0

You definitely can return anonymous types. This works, for example:

public object GetLatestPost()
{
  XDocument feedXML = XDocument.Load("http://feeds.encosia.com/Encosia");

  var posts = from feed in feedXML.Descendants("item")
                   select new
                   {
                     Title = feed.Element("title").Value,
                     Link = feed.Element("link").Value,
                     Description = feed.Element("description").Value
                   };

  return posts.First();
}

If you call that method as an ASMX ScriptService's WebMethod, you'll get this JSON from it:

{"d":
    {"Title":"Using an iPhone with the Visual Studio development server",
     "Link":"http://feeds.encosia.com/~r/Encosia/~3/vQoxmC6lOYk/",
     "Description":" Developing iPhone-optimized portions of an ASP.NET ..."}}

You can use a return type of IEnumerable to return a collection of anonymous types also.

Dave Ward
  • 59,815
  • 13
  • 117
  • 134