.net调用web Service时集合序列化的解决方案
在.net中调用Web Service时,如果要返回一个集合,一般使用Dataset或DataTable(Framework 2.0后DataTable也可以序列化了)
DataSet的优势是可以与XML实现自由转换,可以被.net以外的其他平台调用。
可以参考MSDN:通过 XML Web Services 使用数据集 (ADO.NET) http://msdn.microsoft.com/zh-cn/library/s5xy331f.aspx
遗憾的是,如果客户端无法传递特定序列化的集合,如自定义的对象集合。
曾经看到萤火虫这样用:XmlSerializer 序列化实体类来操作xml文件 http://www.cnblogs.com/Marvel/archive/2009/01/20/1379041.html
以前有做法是转化为DataSet,今天试了下,发现可以不用DataSet也可以实现WebSercice传递序列集合。
新建一个web service,并建一个三个类:
代码
using System;
using System.Collections.Generic;
using System.Collections;
using System.Xml;
namespace DemoListsByWebService
{
#region Area
public class Area
{
private string m_Area_ID;
/// <summary>
/// Area_ID
/// </summary>
public string Area_ID
{
get { return m_Area_ID; }
set { m_Area_ID = value; }
}
private string m_Area_Name;
/// <summary>
/// Area_Name
/// </summary>
public string Area_Name
{
get { return m_Area_Name; }
set { m_Area_Name = value; }
}
private double m_Area_Order;
/// <summary>
/// Area_Order
/// </summary>
public double Area_Order
{
get { return m_Area_Order; }
set { m_Area_Order = value; }
}
}
#endregion
#region AreaCollection
[Serializable]
public class AreaCollection : CollectionBase
{
public AreaCollection()
{
}
public AreaCollection(Area[] value)
{
}
public Area this[int index]
{
get { return ((Area)(this.List[index])); }
}
public int Add(Area value)
{
return this.List.Add(value);
}
public void AddRange(Area[] value)
{
for (int i = 0; (i < value.Length); i = (i + 1))
{
this.Add(value[i]);
}
}
public void AddRange(AreaCollection value)
{
for (int i = 0; (i < value.Count); i = (i + 1))
{
this.Add((Area)value.List[i]);
}
}
public bool Contains(Area value)
{
return this.List.Contains(value);
}
public void CopyTo(Area[] array, int index)
{
this.List.CopyTo(array, index);
}
public int IndexOf(Area value)
{
return this.List.IndexOf(value);
}
public void Insert(int index, Area value)
{
List.Insert(index, value);
}
public void Remove(Area value)
{
List.Remove(value);
}
private int _maxItems = 0;
public int MaxItems
{
get { return this._maxItems; }
set { this._maxItems = value; }
}
public Area FindByID(string id)
{
for (int i = 0; (i < Count); i++)
{
if (this[i].Area_ID == id)
{
return this[i];
}
}
return null;
}
public string FindNameByID(string id)
{
for (int i = 0; (i < Count); i++)
{
if (this[i].Area_ID == id)
{
return this[i].Area_Name;
}
}
return null;
}
public string FindIDByName(string cateName)
{
for (int i = 0; (i < Count); i++)
{
Area tempArea = this[i];
if (tempArea.Area_Name.Trim() == cateName.Trim())
{
return tempArea.Area_ID;
}
}
return null;
}
}
[Serializable]
public class AreaLists : List<Area>
{
//Extend your properties and methods by Tony . for more Help to
//http://msdn.microsoft.com/zh-cn/library/s6hkc2c4.aspx
private int _maxItems = 0;
public int MaxItems { get { return this._maxItems; } set { this._maxItems = value; } }
}
#endregion
}
using System.Collections.Generic;
using System.Collections;
using System.Xml;
namespace DemoListsByWebService
{
#region Area
public class Area
{
private string m_Area_ID;
/// <summary>
/// Area_ID
/// </summary>
public string Area_ID
{
get { return m_Area_ID; }
set { m_Area_ID = value; }
}
private string m_Area_Name;
/// <summary>
/// Area_Name
/// </summary>
public string Area_Name
{
get { return m_Area_Name; }
set { m_Area_Name = value; }
}
private double m_Area_Order;
/// <summary>
/// Area_Order
/// </summary>
public double Area_Order
{
get { return m_Area_Order; }
set { m_Area_Order = value; }
}
}
#endregion
#region AreaCollection
[Serializable]
public class AreaCollection : CollectionBase
{
public AreaCollection()
{
}
public AreaCollection(Area[] value)
{
}
public Area this[int index]
{
get { return ((Area)(this.List[index])); }
}
public int Add(Area value)
{
return this.List.Add(value);
}
public void AddRange(Area[] value)
{
for (int i = 0; (i < value.Length); i = (i + 1))
{
this.Add(value[i]);
}
}
public void AddRange(AreaCollection value)
{
for (int i = 0; (i < value.Count); i = (i + 1))
{
this.Add((Area)value.List[i]);
}
}
public bool Contains(Area value)
{
return this.List.Contains(value);
}
public void CopyTo(Area[] array, int index)
{
this.List.CopyTo(array, index);
}
public int IndexOf(Area value)
{
return this.List.IndexOf(value);
}
public void Insert(int index, Area value)
{
List.Insert(index, value);
}
public void Remove(Area value)
{
List.Remove(value);
}
private int _maxItems = 0;
public int MaxItems
{
get { return this._maxItems; }
set { this._maxItems = value; }
}
public Area FindByID(string id)
{
for (int i = 0; (i < Count); i++)
{
if (this[i].Area_ID == id)
{
return this[i];
}
}
return null;
}
public string FindNameByID(string id)
{
for (int i = 0; (i < Count); i++)
{
if (this[i].Area_ID == id)
{
return this[i].Area_Name;
}
}
return null;
}
public string FindIDByName(string cateName)
{
for (int i = 0; (i < Count); i++)
{
Area tempArea = this[i];
if (tempArea.Area_Name.Trim() == cateName.Trim())
{
return tempArea.Area_ID;
}
}
return null;
}
}
[Serializable]
public class AreaLists : List<Area>
{
//Extend your properties and methods by Tony . for more Help to
//http://msdn.microsoft.com/zh-cn/library/s6hkc2c4.aspx
private int _maxItems = 0;
public int MaxItems { get { return this._maxItems; } set { this._maxItems = value; } }
}
#endregion
}
注意对象集合必须添加属性 [Serializable]
再建一测试方法:
代码
using System;
using System.Collections.Generic;
using System.Web;
namespace DemoListsByWebService
{
public class MyMethods
{
#region Methods
public static AreaLists GetTestArea()
{
AreaLists al = new AreaLists();
for (int i = 1; i < 11; i++)
{
Area a = new Area();
a.Area_ID = i.ToString();
a.Area_Name = "第" + i.ToString() + "名";
al.Add(a);
}
return al;
}
public static AreaCollection GetTestAreaCollection()
{
AreaCollection al = new AreaCollection();
for (int i = 1; i < 11; i++)
{
Area a = new Area();
a.Area_ID = i.ToString();
a.Area_Name = "第" + i.ToString() + "名";
al.Add(a);
}
return al;
}
#endregion
}
}
using System.Collections.Generic;
using System.Web;
namespace DemoListsByWebService
{
public class MyMethods
{
#region Methods
public static AreaLists GetTestArea()
{
AreaLists al = new AreaLists();
for (int i = 1; i < 11; i++)
{
Area a = new Area();
a.Area_ID = i.ToString();
a.Area_Name = "第" + i.ToString() + "名";
al.Add(a);
}
return al;
}
public static AreaCollection GetTestAreaCollection()
{
AreaCollection al = new AreaCollection();
for (int i = 1; i < 11; i++)
{
Area a = new Area();
a.Area_ID = i.ToString();
a.Area_Name = "第" + i.ToString() + "名";
al.Add(a);
}
return al;
}
#endregion
}
}
web Service提供的方法:
代码
using System;
using System.Collections.Generic;
using System.Web;
using System.Web.Services;
namespace DemoListsByWebService
{
/// <summary>
/// Summary description for Service1
/// </summary>
[WebService(Namespace = "http://tempuri.org/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
[System.ComponentModel.ToolboxItem(false)]
public class Service1 : System.Web.Services.WebService
{
[WebMethod(Description = "Get Areas")]
public AreaLists GetTestArea()
{
try
{
AreaLists ac = MyMethods.GetTestArea();
return ac;
}
catch (Exception e)
{
return null;
}
}
[WebMethod(Description = "Get AreaCollections")]
public AreaCollection GetTestAreaCollection()
{
try
{
AreaCollection ac = MyMethods.GetTestAreaCollection();
return ac;
}
catch (Exception e)
{
return null;
}
}
}
}
using System.Collections.Generic;
using System.Web;
using System.Web.Services;
namespace DemoListsByWebService
{
/// <summary>
/// Summary description for Service1
/// </summary>
[WebService(Namespace = "http://tempuri.org/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
[System.ComponentModel.ToolboxItem(false)]
public class Service1 : System.Web.Services.WebService
{
[WebMethod(Description = "Get Areas")]
public AreaLists GetTestArea()
{
try
{
AreaLists ac = MyMethods.GetTestArea();
return ac;
}
catch (Exception e)
{
return null;
}
}
[WebMethod(Description = "Get AreaCollections")]
public AreaCollection GetTestAreaCollection()
{
try
{
AreaCollection ac = MyMethods.GetTestAreaCollection();
return ac;
}
catch (Exception e)
{
return null;
}
}
}
}
服务OK!
新建一 Winform窗体项目,添加web service引用,http://localhost/DemoListsByWebService/Service1.asmx
在主窗体中调用方法:
private void BindAreaList()
{
DemoWebServiceList.Service1 dl = new TestWebServiceOfLists.DemoWebServiceList.Service1();
DemoWebServiceList.Area[] ac = dl.GetTestArea();
cbArea.DataSource = ac;
cbArea.DisplayMember = "Area_Name";
cbArea.ValueMember = "Area_ID";
cbArea.SelectedValue = "5";
lbResult.Text = "集合共:" + ac.Length.ToString() + "个元素!";
}
private void BindAreaCollection()
{
DemoWebServiceList.Service1 dl = new TestWebServiceOfLists.DemoWebServiceList.Service1();
DemoWebServiceList.Area[] ac = dl.GetTestAreaCollection();
cbArea.DataSource = ac;
cbArea.DisplayMember = "Area_Name";
cbArea.ValueMember = "Area_ID";
cbArea.SelectedValue = "5";
lbResult.Text = "集合共:" + ac.Length.ToString() + "个元素!";
}
{
DemoWebServiceList.Service1 dl = new TestWebServiceOfLists.DemoWebServiceList.Service1();
DemoWebServiceList.Area[] ac = dl.GetTestArea();
cbArea.DataSource = ac;
cbArea.DisplayMember = "Area_Name";
cbArea.ValueMember = "Area_ID";
cbArea.SelectedValue = "5";
lbResult.Text = "集合共:" + ac.Length.ToString() + "个元素!";
}
private void BindAreaCollection()
{
DemoWebServiceList.Service1 dl = new TestWebServiceOfLists.DemoWebServiceList.Service1();
DemoWebServiceList.Area[] ac = dl.GetTestAreaCollection();
cbArea.DataSource = ac;
cbArea.DisplayMember = "Area_Name";
cbArea.ValueMember = "Area_ID";
cbArea.SelectedValue = "5";
lbResult.Text = "集合共:" + ac.Length.ToString() + "个元素!";
}
注意: DemoWebServiceList.Area[]的集合个数不用Count,MaxItems,而用Length,因为这是一个重新序列化后的数组集合。
省去了对象转换的烦恼!