Asp.net轻松修改Web Service返回格式

翅膀的初衷

发表于2015-07-02 21:29:00

Web Service是目前使用非常普及的一种跨平台的基于WEB的数据交互技术 ,深受广大开发者的喜欢,但是因为Web Service基于XML格式,有时返回的结果中带有较多的额外的数据格式信息,或者基于一些特殊的应用场景,希望对返回的XML格式进行一些自定义,那么,我们怎么办呢?

首先,看一个例子:

下面的数据是某web service返回的一个字符串数组:

<ArrayOfString xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="http://WebXml.com.cn/"> <string>湖南</string> <string>长沙</string> <string>57679</string> <string>57679.jpg</string> <string>2015-7-2 20:20:02</string> <string>23℃/31℃</string> <string>7月2日 多云</string> <string>东北风微风</string> <string>1.gif</string> <string>1.gif</string> <string>今日天气实况:气温:29℃;风向/风力:西北风 1级;湿度:71%;空气质量:暂无;紫外线强度:中等</string> <string> 太阳镜指数:必要。建议佩戴透射比为1级的浅色太阳镜。 穿衣指数:热。适合穿T恤、短薄外套等夏季服装。 旅游指数:适宜。微风,虽天气稍热,但不会影响心情。 运动指数:较适宜。户外运动请注意防晒。 洗车指数:不宜。有雨,雨水和泥水会弄脏爱车。 化妆指数:去油。请选用露质面霜打底,水质无油粉底霜。 感冒指数:少发。感冒机率较低,避免长期处于空调屋中。 空气污染指数:暂无。 紫外线指数:中等。涂擦SPF大于15、PA+防晒护肤品。 舒适度指数:较不舒适。晴,有些热。 </string> <string>25℃/31℃</string> <string>7月3日 多云</string> <string>东北风微风</string> <string>1.gif</string> <string>1.gif</string> <string>23℃/27℃</string> <string>7月4日 阵雨转小雨</string> <string>东北风转西北风微风</string> <string>3.gif</string> <string>7.gif</string> </ArrayOfString>

看起来还算比较正常,但是如果是object数组,下面的子点节的名字就会五花八门,变成如下格式:

湖南 长沙 57679 57679.jpg 2015-7-2 20:20:02

看起来非常不整齐,而且读取起来也不方便。幸好.NET中我们可以通过为对象实现IXmlSerializable接口来自定义格式,比如:

public class MyObjectList : List<Object>, IXmlSerializable { public System.Xml.Schema.XmlSchema GetSchema() { return null; } public void ReadXml(System.Xml.XmlReader reader) { } public void WriteXml(System.Xml.XmlWriter writer) { writer.WriteStartElement("List"); for (var i = 0; i < this.Count; i++) { writer.WriteStartElement("Item"); writer.WriteString(this[i].ToString()); writer.WriteEndElement(); } writer.WriteEndElement(); } }

那么,该类型的web service返回的结果就是

<MyObjectList xmlns="http://tempuri.org/"> <List> <Item>sss</Item> <Item>aaa</Item> <Item>1111</Item> </List> </MyObjectList>

好了,要是我返回有很多格式,比如字典啊,INT数组啊,DataTable啊,及其它泛型数组与各式自定义对象,那我不是每个类型都要先重新定义一个并实现一下IXmlSerializable接口?那不是多麻烦?

理论上确实是这样,不过,我们可以灵活变通一下,不必要这么麻烦。我们只要定义一个类并实现IXmlSerializable就行了,然后在WriteXml中判断下类型即可,代码如下(仅供参考原理):

public class ResultData : IXmlSerializable { #region IXmlSerializable 成员 private object _data; public object Data { get { return _data; } set { _data = value; } } public ResultData(object data) { this._data = data; } public ResultData() : this(null) { } public System.Xml.Schema.XmlSchema GetSchema() { return null; } public void ReadXml(System.Xml.XmlReader reader) { } public void WriteXml(System.Xml.XmlWriter writer) { Type t = this._data.GetType(); if(this._data is IEnumerable) //是否是可枚举对象 { IEnumerable data1 = (IEnumerable)this._data; IEnumerator data2 = data1.GetEnumerator(); writer.WriteStartElement("List"); while (data2.MoveNext()) { writer.WriteStartElement("Item"); writer.WriteString(data2.Current.ToString()); writer.WriteEndElement(); } writer.WriteEndElement() } else if (t.IsClass) { PropertyInfo[] pi = this._data.GetType().GetProperties(); for (int i = 0; i < pi.Length; i++) { writer.WriteStartElement("Item"); writer.WriteStartElement(pi[i].Name.ToLower()); writer.WriteString(pi[i].GetValue(this._data, null).ToString()); writer.WriteEndElement(); writer.WriteEndElement(); } } //更多略... //此处只做了简单判断,实际应用中应该要处理注意处理和复杂情况 } }

我们在web service中返回其它类型时,只要 return new ResultData(你的对象) 就行了。如果是可枚举对象,返回的格式为

<ResultData xmlns="http://tempuri.org/"> <List> <Item>你的数据</Item> <Item>你的数据</Item> </List> </ResultDatat>

如果是类,则为

<ResultData xmlns="http://tempuri.org/"> <Item> <属性1>你的数据</属性1> <属性2>你的数据</属性2> </Item> </ResultDatat>

当然,你也可以根据自己的需要自行定义成任何格式。(注:以上演示代码仅供演示,类型的判断不完善,实际应用中请注意完善相关代码)

原创文章,转载请注明作者与出处:http://www.jiniannet.com