C#调用Web Services获取数据格式异常,如何获取规范JSON/XML并转为对象
解决方案
核心问题说明
现有实现存在两个核心问题:
- 服务端将查询结果拼接为无字段标识的扁平字符串数组,序列化后无结构化信息
- ASMX WebService默认会将string类型返回值包裹在XML
<string>节点中,直接读取得到的不是纯JSON/XML格式数据
服务端改造
第一步:定义强类型业务实体
先定义和查询结果对应的Learner实体,替换下列字段名为实际业务字段即可:
public class Learner { // 依次对应DataRow中索引0、1、2、3、5的字段,按需修改字段名 public string LearnerName { get; set; } public string Mobile { get; set; } public string RegisterTime { get; set; } public string Status { get; set; } public string Company { get; set; } }
第二步:改造WebMethod
方案A:输出纯JSON(推荐,前端/客户端直接可用)
[WebMethod] public void LoadLearner(string id) { DataSet dtsta = SQLServer.GetDsBySP("Load_Learner_ForCRM", "learnerId", id); List<Learner> learnerList = new List<Learner>(); foreach (DataRow rdr in dtsta.Tables[0].Rows) { learnerList.Add(new Learner { LearnerName = rdr[0].ToString(), Mobile = rdr[1].ToString(), RegisterTime = rdr[2].ToString(), Status = rdr[3].ToString(), Company = rdr[5].ToString() }); } // 直接输出纯JSON,避免XML包装 Context.Response.ContentType = "application/json"; Context.Response.Write(JsonConvert.SerializeObject(learnerList)); Context.Response.End(); }
方案B:返回实体类(兼容XML格式请求)
如果需要同时支持XML格式返回,直接返回实体集合即可,ASMX会自动根据请求头适配序列化格式:
[WebMethod] public List<Learner> LoadLearner(string id) { DataSet dtsta = SQLServer.GetDsBySP("Load_Learner_ForCRM", "learnerId", id); List<Learner> learnerList = new List<Learner>(); foreach (DataRow rdr in dtsta.Tables[0].Rows) { learnerList.Add(new Learner { LearnerName = rdr[0].ToString(), Mobile = rdr[1].ToString(), RegisterTime = rdr[2].ToString(), Status = rdr[3].ToString(), Company = rdr[5].ToString() }); } return learnerList; }
客户端改造
第一步:定义和服务端一致的实体类
和服务端的Learner类保持字段完全一致即可。
第二步:优化请求逻辑,反序列化到对象
string responseFromServer = string.Empty; // 对ID参数做URL编码,避免特殊字符报错 string encodedId = HttpUtility.UrlEncode(item.learner_id); HttpWebRequest request = (HttpWebRequest)WebRequest.Create($"http://abc/Company/CrmLearner.asmx/LoadLearner?id={encodedId}"); request.Method = "GET"; // 明确要求返回JSON格式 request.Accept = "application/json"; // 补上缺失的获取响应逻辑 using (HttpWebResponse response = (HttpWebResponse)request.GetResponse()) { using (Stream dataStream = response.GetResponseStream()) { using (StreamReader reader = new StreamReader(dataStream)) { responseFromServer = reader.ReadToEnd(); } } } // 反序列化得到结构化对象,直接使用即可 List<Learner> learnerList = JsonConvert.DeserializeObject<List<Learner>>(responseFromServer);
注意事项
- 如果使用方案B的自动序列化模式,返回结果会带ASMX默认的XML包装,需要先提取XML节点中的内容再做反序列化
- 实体类字段名、类型必须和服务端完全一致,否则会反序列化失败
内容的提问来源于stack exchange,提问作者Rahmat Afridi
相关产品推荐
相关产品推荐

