Web API客户端如何从响应中读取复杂类型?
问题分析与解决方案
首先咱们先揪出核心问题:你当前的服务端返回逻辑有偏差,这直接导致客户端没法正确解析到User对象;另外客户端的处理顺序也需要调整。
第一步:修正服务端代码
你现在用Ok(responseContent)返回HttpContent对象的做法是错的——Web API会把这个StringContent本身序列化,而不是把它内部的User JSON作为响应体返回。其实完全不用手动序列化,直接返回User对象就好,Web API会自动帮你完成JSON序列化工作:
[HttpPost] [Route("users/verifyLoginCredentials")] public IHttpActionResult VerifyLoginCredentials([FromBody]Dictionary<string,string> loginCredentials) { // 保留你的测试逻辑 Models.User user = new Models.User(); string username = loginCredentials.ContainsKey("userLogin") ? loginCredentials["userLogin"] : ""; string password = loginCredentials.ContainsKey("password") ? loginCredentials["password"] : ""; var verificationResult = Models.User.VerifyLoginCredentials(username, password, out user); if (verificationResult) { // 直接返回User对象,Web API自动处理序列化 return Ok(user); } return BadRequest("Login Failed"); }
如果非要手动控制序列化(不推荐,没必要),可以改成返回ResponseMessageResult:
return ResponseMessage(new HttpResponseMessage(HttpStatusCode.OK) { Content = new StringContent(Newtonsoft.Json.JsonConvert.SerializeObject(user), Encoding.UTF8, "application/json") });
第二步:客户端的正确处理方式
首先,客户端必须定义一个和服务端Models.User属性完全匹配的User类(属性名、类型要一致,比如服务端有Id、Username这些属性,客户端也要对应),示例如下:
public class User { public int Id { get; set; } public string Username { get; set; } public string Email { get; set; } // 其他和服务端User对应的属性 }
然后调整客户端的请求逻辑:先判断响应是否成功,再读取内容反序列化,同时可以把User对象返回供后续使用:
public static async Task<User> VerifyCredentials(string userLogin, string password) { var value = new Dictionary<string, string> { { "userLogin", userLogin }, { "password", password } }; var jsonContent = Newtonsoft.Json.JsonConvert.SerializeObject(value); var content = new StringContent(jsonContent, Encoding.UTF8, "application/json"); var result = await WebApiHelper.Client.PostAsync("users/verifyLoginCredentials", content); if (result.IsSuccessStatusCode) { string resultContent = await result.Content.ReadAsStringAsync(); // 反序列化为User对象 return Newtonsoft.Json.JsonConvert.DeserializeObject<User>(resultContent); } else { // 登录失败的处理逻辑,比如返回null或者抛出异常 string errorMsg = await result.Content.ReadAsStringAsync(); Console.WriteLine($"登录失败:{errorMsg}"); return null; } }
额外小提示
如果服务端和客户端的属性大小写不一致(比如服务端用驼峰,客户端用 Pascal 命名),可以在反序列化时忽略大小写:
var settings = new Newtonsoft.Json.JsonSerializerSettings { ContractResolver = new Newtonsoft.Json.Serialization.CamelCasePropertyNamesContractResolver(), MissingMemberHandling = Newtonsoft.Json.MissingMemberHandling.Ignore }; var user = Newtonsoft.Json.JsonConvert.DeserializeObject<User>(resultContent, settings);
内容的提问来源于stack exchange,提问作者Aboudi
相关产品推荐
相关产品推荐

