Wim Haanstra
Wim Haanstra

Reputation: 5998

WCF service returning JSON with an anonymous object

For a simple API I am building I am using a couple of techniques. First of all, this is not my first API I am creating, but it is the first where I have combination of WCF, json and anonymous objects.

I got the following interface for the WCF API:

[ServiceContract]
public interface IAPI
{
    [OperationContract]
    [WebInvoke(Method = "POST",
                 BodyStyle = WebMessageBodyStyle.WrappedRequest,
                 ResponseFormat = WebMessageFormat.Json,
                 RequestFormat = WebMessageFormat.Json)]
    ServiceResponse Authenticate(string username, string hashedPassword);

    [OperationContract]
    [WebInvoke(Method = "POST",
                 BodyStyle = WebMessageBodyStyle.WrappedRequest,
                 ResponseFormat = WebMessageFormat.Json,
                 RequestFormat = WebMessageFormat.Json)]
    ServiceResponse GetProducts();
}

It's all pretty simple, just 2 methods I want to have working. The ServiceResponse class you see there is also really simple, but causing the problems I think:

[DataContract]
public class ServiceResponse
{
    [DataMember]
    public ResponseCode Status { get; set; }

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

I made this class, so I can always send a Status (Simple int enum) and an object, for example a string or a list of objects.

I created a small script using jQuery to test my service, and the Authenticate method works like it should, but this method returns a ServiceResponse object, with just a 0 in the Status field. The Value field is left empty here.

The GetProducts method is the one where it gets tricky, an array of anonymous objects like this:

public ServiceResponse GetProducts()
{
       DataClassesDataContext db = new DataClassesDataContext();
       var results = from p in db.Products
                     where p.UserID == 1
                     select new
                     {
                         ID = p.ID,
                         Name = p.DecryptedName
                     };

        return ServiceResponse.OK(results.ToArray());
}

I am using an anonymous type object here, because I do not want to create proxy classes for all the classes I want to use in the API.

When I try out this code, with my simple jQuery script, FireBug tells me that my request has been aborted. I guess this is because of an Error 500 or something. When I put a breakpoint in my GetProducts method, it gets hit 7 times before Firefox says it is aborted and the script is fully run.

Here is the jQuery script I use to test out my WCF service:

$.ajax({
    type: "POST",
    contentType: "application/json; charset=utf-8",
    url: "/Handlers/API.svc/GetProducts",
    data: '{}',
    dataType: "json",
    success: function (response) {
        var test = inspect(response, 5);
        $("#output").html(test);
    },
    error: function (message) {
        $("#output").html(inspect(message, 5));
    }
});

The inspect method you see in there, is just a small JS script that shows me the contents of an object.

I tried the following things to get it moving:

I would love it if I could use WCF to return some sort of array of anonymous objects, because that saves me creating 30+ proxy classes.

NOTE: The Product class is a class generated by LINQ. I am using C# 4.0 for this.

Upvotes: 4

Views: 4345

Answers (2)

Jandro Rojas
Jandro Rojas

Reputation: 1972

Short answer: You can't. You have to use web services instead or -as you said- use a proxy class.

Upvotes: 0

David Brainer
David Brainer

Reputation: 6331

I may be wrong, but I believe that WCF is fairly strict and will not allow you to return an object the way you are trying to. If you know that the data is going to be an array every time you could change your definition to reflect that (but it sounds like this is not going to work in your case). Otherwise, you might want to consider changing your signature to a simple string and serializing the data into JSON first before returning it.

Upvotes: 2

Related Questions