Asp.net轻松修改Web Service返回格式
作者:翅膀的初衷 来源:本站原创 发布时间:2015-07-02 查看数:11702
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