我和我的团队正在使用 OData 开发一个项目。我们正在尝试使用 RestSharp 客户端,但找不到任何在 C# 中将其与 OData 结合使用的最佳实践的干净示例。
我们遇到的问题是,当尝试获取数据时,我们认为它是 2 层 JSON。
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;
}
在此结果中,如果我们使用像 Person (ID,enabled,active) 这样的简单类型,我们会在response.content中看到数据。
"{\"@odata.context\":\"http://localhost:56460/$metadata#Person\",\"value\":[{\"ID\":1090,\"enabled\":true,\"active\":false}]}"
然而resultdata实际上并没有获取数据...它初始化了对象,但ID、enabled和active分别是0、false、false。
我们对此还很陌生...但我的感觉是,由于返回的响应不是 100%,json 数据可能是问题所在?
(另外,还在寻找一些与 OData 和 RESTSharp 相关的文档)。
编辑:我们认为我们需要反序列化到更高级别的对象,因为response.content中的数据是一个对象,然后是每个对象。我们正在尝试使用 OData 找到一个清晰的示例,但尚未找到。
最佳答案
您是对的:从 OData 资源端点检索集合时,实际记录并不表示为顶级数组。为了以您的示例为基础,您将返回:
{
"@odata.context":"http://localhost:56460/odata/$metadata#Person",
"value": [
{
"ID": 1090,
"enabled" : true,
"active" : false
},
{
// second Person object, and so on...
}
]
}
实际包含结果的属性是value
。您可以使用泛型创建一个简单的包装器来处理集合结果:
using System.Collections.Generic;
namespace Api.Models
{
public class ODataCollectionWrapper<T> where T : class
{
public IEnumerable<T> Value { get; set; }
}
}
现在,当您使用RestSharp时,您可以在调用Execute
方法时指定反序列化类型,并节省一些代码。另请注意 RestSharp no longer natively uses Json.NET (尽管您可以管理自己的反序列化并保留 Json.NET,如果您确实愿意的话)。
// RestSharp automatically deserializes to ODataCollectionWrapper<Person>
response = client.Execute<ODataCollectionWrapper<Person>>(request);
// Return the actual collection
return response.Value; // Contains IEnumerable<Person>
请注意,如果您只是检索单个资源(通过 ID 或您拥有的任何东西,任何保证返回零或一个结果而不是数组的资源),则没有必要这样做。
关于c# - RestSharp 和 OData - 反序列化 JSON 的问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44929895/