如何在Service层不使用Model反序列化JSON列表并绑定ViewModel?
解决Service层不依赖Model时的JSON反序列化问题
我来帮你搞定这个问题!你现在的核心需求是让Service层完全不依赖Model,同时把它返回的JSON数据正确反序列化成ViewModel里的List<Employee>对吧?咱们先梳理下你之前代码里的问题,再给出正确的修改方案:
之前代码的核心问题
- 手动拼接JSON格式错误:你之前手动拼的JSON字符串里,字符串类型的字段(比如Name、Location)没有加双引号,这会导致JSON格式非法,反序列化失败。
- 反序列化类型不匹配:Controller里你用了
JsonConvert.DeserializeObject<Employee>(...),但Service返回的是一个列表的JSON,应该对应List<Employee>类型,类型不匹配会直接报错。 - Service层仍依赖Model:你之前的Service代码里还保留了
using listTest.Models;,这就没做到完全不依赖Model的要求。
正确的修改方案
1. 修正Service层代码(完全移除Model依赖)
这里我们用dynamic+ExpandoObject来构建数据,最后直接序列化整个列表,避免手动拼接JSON的错误,同时完全移除对Model的引用:
using System; using System.Collections.Generic; using System.Configuration; using System.Data.SqlClient; using System.Data; using Newtonsoft.Json; using System.Dynamic; namespace listTest.Service { public class DBService { private readonly static string cnstr = ConfigurationManager.ConnectionStrings["connection1"].ConnectionString; SqlConnection conn = new SqlConnection(cnstr); public string getData() { List<dynamic> DataList = new List<dynamic>(); string sql = @"select * from Employee"; try { conn.Open(); SqlCommand cmd = new SqlCommand(sql, conn); SqlDataReader dr = cmd.ExecuteReader(); while (dr.Read()) { dynamic empObj = new ExpandoObject(); // 保持Id的数值类型,避免后续反序列化时的类型转换问题 empObj.Id = Convert.ToInt32(dr["Id"]); empObj.Name = dr["Name"].ToString(); empObj.Age = dr["Age"].ToString(); empObj.Location = dr["Location"].ToString(); empObj.Sex = dr["Sex"].ToString(); DataList.Add(empObj); } } catch (Exception e) { throw new Exception(e.Message.ToString()); } finally { conn.Close(); } // 直接序列化整个动态对象列表,生成合法的JSON数组 return JsonConvert.SerializeObject(DataList); } } }
2. 修正Controller层代码(正确反序列化)
只需要把反序列化的目标类型改成List<Employee>,和ViewModel里的EmployeeDataList类型匹配:
using System; using System.Web.Mvc; using listTest.Service; using listTest.ViewModels; using Newtonsoft.Json; using listTest.Models; namespace listTest.Controllers { public class HomeController : Controller { public ActionResult Index() { return View(); } public ActionResult EmpList() { DBService service = new DBService(); ViewModel data = new ViewModel(); // 关键:反序列化成List<Employee>,匹配ViewModel的属性类型 data.EmployeeDataList = JsonConvert.DeserializeObject<List<Employee>>(service.getData()); return View(data); } } }
更类型安全的替代方案(可选)
如果你觉得dynamic不够类型安全,可以在Service层定义一个内部DTO(数据传输对象),只在Service内部使用,这样既不依赖外部Model,又能保证类型安全:
在Service里添加一个内部类:
namespace listTest.Service { public class DBService { // 内部DTO,仅Service层使用 private class EmployeeDto { public int Id { get; set; } public string Name { get; set; } public string Age { get; set; } public string Location { get; set; } public string Sex { get; set; } } // 剩余Service代码不变,只是把dynamic换成EmployeeDto public string getData() { List<EmployeeDto> DataList = new List<EmployeeDto>(); string sql = @"select * from Employee"; try { conn.Open(); SqlCommand cmd = new SqlCommand(sql, conn); SqlDataReader dr = cmd.ExecuteReader(); while (dr.Read()) { var empDto = new EmployeeDto(); empDto.Id = Convert.ToInt32(dr["Id"]); empDto.Name = dr["Name"].ToString(); empDto.Age = dr["Age"].ToString(); empDto.Location = dr["Location"].ToString(); empDto.Sex = dr["Sex"].ToString(); DataList.Add(empDto); } } // ... 剩余代码和之前一致 } } }
这样Controller层的反序列化代码不需要修改,依然可以正常把JSON转换成List<Employee>。
内容的提问来源于stack exchange,提问作者kyle
相关产品推荐
相关产品推荐

