Reputation: 1709
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
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
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