1

I am calling on a WCF Data Services v3 Odata service. I am having trouble getting my collection filled in the below example. I am able to get a json string of the 3 people, but if I try and get a custom collection filled, the collection has a count = 0.

HttpClient client = new HttpClient();

client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));

client.BaseAddress = new Uri("http://localhost:7500/Wcf1.svc/People");

HttpResponseMessage resp = client.GetAsync("").Result;

string jsonString = resp.Content.ReadAsStringAsync().Result;

List<Person> personCollection = resp.Content.ReadAsAsync<List<Person>>().Result;

jsonString has 3 people in it.

personCollection has a count = 0.

the jsonString looks like this:

{"d":[
{"__metadata":{"id":"http://localhost:7500/Wcf1.svc/People(1)",
"uri":"http://localhost:7500/Wcf1.svc/People(1)",
"type":"WcfService1.Person"},
"ID":1,"Fname":"Fred","Lname":"Peters","Address1":"123 Main"},

 {"__metadata":{"id":"http://localhost:7500/Wcf1.svc/People(2)",
"uri":"http://localhost:7500/Wcf1.svc/People(2)",
"type":"WcfService1.Person"},
"ID":2,"Fname":"John","Lname":"Smith","Address1":"123 Oak"},

{"__metadata":{"id":"http://localhost:7500/Wcf1.svc/People(3)",
"uri":"http://localhost:7500/Wcf1.svc/People(3)",
"type":"WcfService1.Person"},
"ID":3,"Fname":"Tom","Lname":"Anders","Address1":"123 Hill St."}]}

I must be doing something wrong, please point out my error if you can.

Thanks. Terrence

Terrence
  • 313
  • 2
  • 12

1 Answers1

3

Your content is not a List<Person>

Paste your Json into json2csharp and you'll see it.

To get a better overview what your response content is, download Json Viewer - this is a screenshot of your data:

enter image description here

As you can see: the Persons are a property of the Json root object.

If you wanted to use your code from above, the Json should have to look like this (or you need to access the data in the given structure mapping you classes according to the Json):

[{"__metadata":{"id":"http://localhost:7500/Wcf1.svc/People(1)",
"uri":"http://localhost:7500/Wcf1.svc/People(1)",
"type":"WcfService1.Person"},
"ID":1,"Fname":"Fred","Lname":"Peters","Address1":"123 Main"},

 {"__metadata":{"id":"http://localhost:7500/Wcf1.svc/People(2)",
"uri":"http://localhost:7500/Wcf1.svc/People(2)",
"type":"WcfService1.Person"},
"ID":2,"Fname":"John","Lname":"Smith","Address1":"123 Oak"},

{"__metadata":{"id":"http://localhost:7500/Wcf1.svc/People(3)",
"uri":"http://localhost:7500/Wcf1.svc/People(3)",
"type":"WcfService1.Person"},
"ID":3,"Fname":"Tom","Lname":"Anders","Address1":"123 Hill St."}]}]

Update:

You should be able to parse your initially posted Json like this:

var json = JsonValue.Parse(response.Content.ReadAsStringAsync().Result);
var arr = json["d"];
var contact1 = arr[0];
var fname = result1["Fname"];

I have done a blog post on JsonValue and JsonArray recently. It's server side, but it should point you the direction.

2nd Update:

Using the classes from the json2csharp.com output, you can do this:

public class Metadata
{
    public string id { get; set; }
    public string uri { get; set; }
    public string type { get; set; }
}

public class D
{
    public Metadata __metadata { get; set; }
    public int ID { get; set; }
    public string Fname { get; set; }
    public string Lname { get; set; }
    public string Address1 { get; set; }
}

public class RootObject
{
    public List<D> d { get; set; }
}

Usage:

var root = resp.Content.ReadAsAsync<RootObject>().Result;
var persons = root.d;
var person1 = persons[0];
lukkea
  • 3,606
  • 2
  • 37
  • 51
Alexander Zeitler
  • 11,919
  • 11
  • 81
  • 124
  • Alexander, thanks for your comments. I wonder why the odata service is not returning a valid json collection. I guess I need to find out what is going on with the serive. I am asking for json in my request header. – Terrence Jan 12 '12 at 15:38
  • The Json returned by the service is not wrong in the sence of OData - it just doesn't match with your expectations. Plus, if you're expecting a list, it may be better to request/accept an application/atom+xml instead of Json in the sence of OData. http://www.odata.org/developers/protocols/operations#RetrievingfeedsEntriesandservicedocument – Alexander Zeitler Jan 12 '12 at 18:03
  • Alexander, could you just provide me with a simple example of getting a collection of data from an odata service kind of like I am trying to do here: List personCollection = resp.Content.ReadAsAsync>().Result; – Terrence Jan 13 '12 at 04:33
  • I can easily request atom+xml from my service. – Terrence Jan 13 '12 at 04:34
  • It could make sense that you use JsonValue on the client so you don't have to introduce types for each object in the Atom+Xml. Please read my answer here: http://stackoverflow.com/a/8136901/90800 (the JsonValue part of the answer) – Alexander Zeitler Jan 13 '12 at 08:28
  • Alexander, thanks, I read that post earlier. I own the server, so I can make it return any format I want. My problem is getting the webapi httpclient side of things to grab a collection of data from a service and populate a collection of entities. I can't find any examples of this simple scenario on the web. Have you done something like this? Thanks for your continued help. – Terrence Jan 13 '12 at 17:01
  • Thank You, I guess I will push to a json object then push them to poco objects. I though I could there in one step with ReadAsAsync, but I guess not. – Terrence Jan 13 '12 at 20:15
  • You can do this only if your client and server side objects have the same properties and type names (just copy/paste the output from json2csharp to create your needed client types). – Alexander Zeitler Jan 13 '12 at 21:03
  • My test Person has ID, fname and lname, that is it. My client and server side object are the same. I am trying to find out why this line results in an empty collection. List personCollection = resp.Content.ReadAsAsync>().Result; If you have time, could you re-read my original post. Shouldn't this line work? Have you ever gotten a collection populated with the syntax I am using? Thank you for keep up with this conversation. – Terrence Jan 14 '12 at 00:28
  • Btw: why don't you use Web Api to generate the OData stuff? – Alexander Zeitler Jan 15 '12 at 00:45
  • Because exposing OData with WCF Data Services is soooo easy. I create the service and point it at my EF model and its done. Why mess with writing lots of methods to get standard functionality, when WCF DS does it for you? – Terrence Jan 15 '12 at 02:46
  • Alex, that second update looks interesting. Is there a reason that you can't produce an example that uses the line of code I want to use? Maybe I am missing something and my syntax does not make since? – Terrence Jan 15 '12 at 02:48
  • Alex, I think I am getting it now. I really appreciate your helping me out on this problem of mine. – Terrence Jan 15 '12 at 14:44