melegant
melegant

Reputation: 1709

RestSharp and OData - Issue Deserializing JSON

My team and I are working on a project with OData. We are trying to use the RestSharp client but cannot find any clean example of a best practice on using it with OData in C#.

The issue we are having is that when trying to get the data it is 2 layers of JSON we think.

private T execRequest<T>(RestClient client, RestRequest request, bool retry = true)
    {
        IRestResponse response;
        T resultdata = default(T);
        try
        {
            response = client.Execute(request);
        }
        catch (Exception)
        {
            throw;
        }
        if (response.StatusDescription == "OK") // TAKE CARE OF Session expired or invalid
        {
            resultdata = JsonConvert.DeserializeObject<T>(response.Content);
        }


       return resultdata;
    }

In this result if we use a simple Type like Person (ID,enabled,active) we see the data in response.content.

"{\"@odata.context\":\"http://localhost:56460/$metadata#Person\",\"value\":[{\"ID\":1090,\"enabled\":true,\"active\":false}]}"

However resultdata does not actually get the data...it initializes the object but ID, enabled and active are 0, false, false.

We are fairly new to this...my feeling though is that since the response back is not 100% the json data might be the issue?

(p.s. also looking for a some doc's pertaining to OData and RESTSharp).

edit: We are thinking that we need to deserialize to a higher level object since the data in response.content is an object, then the object per say. We are trying to find a clean example of this with OData but have not yet.

Upvotes: 2

Views: 2959

Answers (2)

Akshay Kumar Sharma
Akshay Kumar Sharma

Reputation: 281

You should use response.Data.Value

        var restRequest = new RestRequest($"Applications?$filter=Name eq '{applicationTargetName}'", Method.GET);
        var response = client.Execute<ODataCollectionWrapper<Application>>(restRequest);

        var application = response.Data.Value;
        return application.First(); 

Upvotes: 0

CBono
CBono

Reputation: 3803

You're right: when retrieving a collection back from an OData resource endpoint, the actual records aren't represented as a top-level array. To build on your example, you're getting back:

{
   "@odata.context":"http://localhost:56460/odata/$metadata#Person",
   "value": [
      {
        "ID": 1090,
        "enabled" : true,
        "active" : false
      },
      {
        // second Person object, and so on...
      }
   ]
}

The property that actually contains your results is value. You can create a simple wrapper using generics to handle collection results:

using System.Collections.Generic;

namespace Api.Models
{
    public class ODataCollectionWrapper<T> where T : class
    {
        public IEnumerable<T> Value { get; set; }
    }
}

Now when you use RestSharp, you can specify the the deserialization type when calling the Execute method and save yourself some code. Also note that RestSharp no longer natively uses Json.NET (though you can manage your own deserialization and keep Json.NET if you really want to).

// RestSharp automatically deserializes to ODataCollectionWrapper<Person>
response = client.Execute<ODataCollectionWrapper<Person>>(request);

// Return the actual collection
return response.Value; // Contains IEnumerable<Person>

Do note that this isn't necessary if you're just retrieving a single resource (by ID or what-have-you, anything that is guaranteed to return zero or one result and not an array).

Upvotes: 4

Related Questions