HttpClient.ReadAsAsync<T> 使用 [Serializable] 时返回空对象

Posted

技术标签:

【中文标题】HttpClient.ReadAsAsync<T> 使用 [Serializable] 时返回空对象【英文标题】:HttpClient.ReadAsAsync<T> Returns Empty Object When Using [Serializable] 【发布时间】:2014-06-10 10:16:36 【问题描述】:

我正在使用 Microsoft ASP.NET Web API 客户端库(版本 4.0.30506,因为我必须在 .NET Framework 4.0 上运行)来与 .NET Web API 交互。我已经确认数据接收良好。但是,从 ReadAsAsync 调用返回的对象未填充(非空)。在网上搜索后,我发现了这个 SO 帖子(也请参阅答案):

HttpClient response ReadAsAsync() doesn't fully deserialize object

事实证明,我通过 JSON 发送给客户端的对象被标记为 [Serializable] 并且删除此属性使一切正常(我已通过测试确认)。但是,这些对象需要 [Serializable] 属性才能在其他应用程序中使用它们的其他场景,因此简单地删除该属性并不是一个真正的选择。

我的代码如下所示。当 [Serializable] 属性应用于 Customer 对象(如图所示)时,对 Get 方法的调用(未显示)返回一个未填充的 Customer 对象。当属性被移除时,返回的 Customer 对象是属性填充的。

    [Serializable]
    public class Customer
    
        public string Name  get; set; 
    

    public class WebAPIClient
    
        private readonly HttpClient _httpClient;

        public WebAPIClient(Uri baseAddress)
        
            _httpClient = new HttpClient();
            _httpClient.BaseAddress = baseAddress:
            _httpClient.DefaultRequestHeaders.Accept.Clear();
            _httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
        

        public Customer Get(int id)
        
            string url = [code that builds url] + id.ToString();
            HttpResponseMessage response = _httpClient.GetAsync(url).Result;
            response.EnsureSuccessStatusCode();
            return response.Content.ReadAsAsync<Customer>().Result;
        
    

谁能解释为什么我会看到这种行为以及如何在不从我的数据类中删除 [Serializable] 属性的情况下解决它?

【问题讨论】:

你的json在哪里? TEntity 是什么?发个SSCCE怎么样 为上下文和清晰度添加了额外的编码。 我在 [这里][1] 找到了解决方案,并确认它有效。 [1]:***.com/questions/20914080/… 感谢它现在可以工作了...一个简单的属性可以破坏很多东西哈哈... 【参考方案1】:

试试这样的...

public static class ApiUtil

    static HttpClient GetApiClient()
            
                var client = new HttpClient();
                client.BaseAddress = new Uri(ConfigurationManager.AppSettings["apiUrl"]);
                return client;
            

    public static async Task<Customer> GetCustomer(int id)
            
                var client = GetApiClient();
                string query = "Customers(" + id + ")";
                var response = await client.GetAsync(query);
                return await response.Content.ReadAsAsync<Customer>();
            

然后要使用它,您可以在异步方法中执行类似的操作...

var customer = await ApiUtil.GetCustomer(1);

如果您在调用此函数时不能使用 async 和 await,请尝试类似 ...

var customerTask = ApiUtil.GetCustomer(1);
customerTask.Wait();
var customer = customerTask.Result;

【讨论】:

这并不能解决问题,即标记为 [Serializable] 的类没有被 ReadAsAsync 反序列化。等待是无关紧要的。 我完全同意 await 正是我选择使用任务的方式,我可以向您保证,上面的代码示例在我标记为可序列化的类型上运行良好。这段代码是从我的代码库中复制的(目前在生产环境中工作),所以我确信它适用于我拥有的类型......也许问题不在于可序列化的属性? 我想我会对此作出回应......这并不是代码不起作用,而是它不是一个好的答案。 OP 在一个稍微不同的问题上找到了答案(添加 [JsonObject]),我希望他们在这里添加它作为答案。 你能把我链接到解决方案吗?只是好奇......我想我可能错过了什么。 这是对我有用的答案,OP:***.com/a/20914389。看起来它是由 json.net 中的更改引起的。再次明确地说,我认为您的代码本身没有任何问题,只是不适合这个问题。

以上是关于HttpClient.ReadAsAsync<T> 使用 [Serializable] 时返回空对象的主要内容,如果未能解决你的问题,请参考以下文章

Linux内核分析实验二

WEB开发经验点滴

X-005 FriendlyARM tiny4412 uboot移植之时钟初始化

X-004 FriendlyARM tiny4412 uboot移植之点亮指路灯

X-003 FriendlyARM tiny4412 uboot移植之添加相应目录文件

X-007 FriendlyARM tiny4412 u-boot移植之内存初始化