如何调用WebService中的自定义实体类型?

时间:2023-01-24 19:33:06
场景:客户端访问WebService连接,需要返回实体类的集合。采用xml字符串的形式传输,用到了序列化和反序列化。
具体步骤及代码:
1 在WebService中定义了实体类。
[Serializable]
    public class LightningStrike
    {
        public int ID { get;set; }
        public double Longitude { get; set; }
        public double Latitude { get; set; }
        public DateTime DateTime { get; set; }
        public double Intensity { get; set; }
        public double Slope { get; set; }
        public double Error { get; set; }
        public string Province { get; set; }
        public string City { get; set; }
        public string District { get; set; }

        public static Collection<LightningStrike> GetLightningStrikes()
        {
            Collection<LightningStrike> lightningStrikes = new Collection<LightningStrike>();
            for (int i = 0; i < 100; i++)
            {
                LightningStrike strike = new LightningStrike();
                strike.ID = i;
                strike.Longitude = 120;
                strike.Latitude = 30;
                strike.Intensity = 45;
                strike.DateTime = DateTime.Now;
                strike.Province = "浙江省";
                strike.City = "杭州市";
                strike.District = "上城区";
                lightningStrikes.Add(strike);
            }
            return lightningStrikes;
        }
    }

2 asmx中定义了如下内容
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Services;
using System.Collections.ObjectModel;
using System.Xml;
using System.IO;
using System.Xml.Serialization;

namespace WebServiceApplication
{
    /// <summary>
    /// Summary description for WebServiceTest
    /// </summary>
    [WebService(Namespace = "http://tempuri.org/")]
    [WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
    [System.ComponentModel.ToolboxItem(false)]
    // To allow this Web Service to be called from script, using ASP.NET AJAX, uncomment the following line. 
    [System.Web.Script.Services.ScriptService]
    public class WebServiceTest : System.Web.Services.WebService
    {

        [XmlInclude(typeof(LightningStrike))]
        [WebMethod]
        public string GetStrikesCollection()
        {
            //Collection<LightningStrike> strikeCollection =Serializer.DeserializerCollection<LightningStrike>(sXml, typeof(LightningStrike));
            Collection<LightningStrike> strikeCollection = LightningStrike.GetLightningStrikes();
            string sXml = Serializer.Serialize<Collection<LightningStrike>>(strikeCollection);
            return sXml;
        }
    }
}

3 采用winform作为TestApp,添加了对WebService的引用。
4 需要调用localhost下面的LightningStrike失败,代码如下:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using WindowsFormsApplicationTest.localhost;
using System.Xml.Serialization;

namespace WindowsFormsApplicationTest
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void button1_Click(object sender, EventArgs e)
        {
            WebServiceTest cal = new  WebServiceTest();
            double a = 32132.321;
            double b = 54334.321;
            textBoxResult.Text = cal.Div(a,b).ToString();
            string resultString=cal.GetStrikesCollection();
            localhost.
        }
    }
}


问题为什么无法调用自定义实体类型?

7 个解决方案

#1


直接返回集合不就行了?干嘛要先序列化再传递?localhost又是啥东西?

#2


引用 1 楼 starfd 的回复:
直接返回集合不就行了?干嘛要先序列化再传递?localhost又是啥东西?

localhost是客户端引用的Web Reference的名称。

#3


引用 1 楼 starfd 的回复:
 
  
直接返回集合不就行了?干嘛要先序列化再传递?localhost又是啥东西?

为什么不直接引用自定义实体类?
答:用xml序列化可以很好地实现跨平台。所以直接传实体类不可以

我在webService中加了个如下代码,客户端可以引用到自定义类了,很奇怪。代码如下:
 [XmlInclude(typeof(LightningStrike))]
        [WebMethod]
        public string GetStrikesCollection()
        {
            Collection<LightningStrike> strikeCollection = CreateLightningStrikes();
            string sXml = Serializer.Serialize<Collection<LightningStrike>>(strikeCollection);
            return sXml;
        }

        [XmlInclude(typeof(LightningStrike))]
        [WebMethod]
        public LightningStrike GetStrike()
        {
            LightningStrike tmpStrike = new LightningStrike();
            tmpStrike.ID = 1;
            tmpStrike.Longitude = 120;
            tmpStrike.Latitude = 30;
            tmpStrike.Intensity = 45;
            tmpStrike.DateTime = DateTime.Now;
            tmpStrike.Province = "浙江省";
            tmpStrike.City = "杭州市";
            tmpStrike.District = "上城区";
            return tmpStrike;
        }


结果有了新的问题,反序列化中弹出错误:
如何调用WebService中的自定义实体类型?

#4


顶上那一行,以及下面的命名空间声明,都会在你“跨平台”时造成无法修复的bug。

所以不要使用 xml,它太严格了,以至于你会遇到经常遇到诡异的格式问题。应该使用 json,而不是 xml。

#5


另外,给你一个进一步的忠告,在服务器方面尽量使用轻量级的 http 直接处理程序,例如asp.net 的 ashx 程序形式或者自己服务 http 消息,不要使用 webservice/wcf。

#6


我刚才回答了一个关于 xml 读取问题,你可以参考  http://bbs.csdn.net/topics/390969446

注意我删除了它多余的“-”号。


#7


引用 4 楼 sp1234 的回复:
顶上那一行,以及下面的命名空间声明,都会在你“跨平台”时造成无法修复的bug。

所以不要使用 xml,它太严格了,以至于你会遇到经常遇到诡异的格式问题。应该使用 json,而不是 xml。


使用你的思路,通过json的序列化与反序列化很好的解决了问题。

代码如下:
 public class Serializer
    {
        /// <summary>
        /// 序列化方法,把自定义实体类转化为Json格式的字符串
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="objToJson"></param>
        /// <returns></returns>
        public static string SerializeJson<T>(T objToJson)
        {
            DataContractJsonSerializer json = new DataContractJsonSerializer(objToJson.GetType());
            string resultString;
            //序列化
            using(MemoryStream stream=new MemoryStream ())
            {
                json.WriteObject(stream,objToJson);
                resultString = Encoding.UTF8.GetString(stream.ToArray());
                return resultString;
            }     
        }


        /// <summary>
        /// 反序列化方法。将客户端发来的Json转化为Collection<T>
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="sJson"></param>
        /// <param name="type"></param>
        /// <returns></returns>
        public static T DeserializeJson<T>(string sJson, Type type)
        {
            using (MemoryStream ms = new MemoryStream(Encoding.UTF8.GetBytes(sJson)))
            {
                DataContractJsonSerializer serializer = new DataContractJsonSerializer(type);
                object obj = serializer.ReadObject(ms);
                return (T)obj;
            }
        }
    }


感谢建议,结帖给分。
我再查查WebService的并发压力支撑问题。

#1


直接返回集合不就行了?干嘛要先序列化再传递?localhost又是啥东西?

#2


引用 1 楼 starfd 的回复:
直接返回集合不就行了?干嘛要先序列化再传递?localhost又是啥东西?

localhost是客户端引用的Web Reference的名称。

#3


引用 1 楼 starfd 的回复:
 
  
直接返回集合不就行了?干嘛要先序列化再传递?localhost又是啥东西?

为什么不直接引用自定义实体类?
答:用xml序列化可以很好地实现跨平台。所以直接传实体类不可以

我在webService中加了个如下代码,客户端可以引用到自定义类了,很奇怪。代码如下:
 [XmlInclude(typeof(LightningStrike))]
        [WebMethod]
        public string GetStrikesCollection()
        {
            Collection<LightningStrike> strikeCollection = CreateLightningStrikes();
            string sXml = Serializer.Serialize<Collection<LightningStrike>>(strikeCollection);
            return sXml;
        }

        [XmlInclude(typeof(LightningStrike))]
        [WebMethod]
        public LightningStrike GetStrike()
        {
            LightningStrike tmpStrike = new LightningStrike();
            tmpStrike.ID = 1;
            tmpStrike.Longitude = 120;
            tmpStrike.Latitude = 30;
            tmpStrike.Intensity = 45;
            tmpStrike.DateTime = DateTime.Now;
            tmpStrike.Province = "浙江省";
            tmpStrike.City = "杭州市";
            tmpStrike.District = "上城区";
            return tmpStrike;
        }


结果有了新的问题,反序列化中弹出错误:
如何调用WebService中的自定义实体类型?

#4


顶上那一行,以及下面的命名空间声明,都会在你“跨平台”时造成无法修复的bug。

所以不要使用 xml,它太严格了,以至于你会遇到经常遇到诡异的格式问题。应该使用 json,而不是 xml。

#5


另外,给你一个进一步的忠告,在服务器方面尽量使用轻量级的 http 直接处理程序,例如asp.net 的 ashx 程序形式或者自己服务 http 消息,不要使用 webservice/wcf。

#6


我刚才回答了一个关于 xml 读取问题,你可以参考  http://bbs.csdn.net/topics/390969446

注意我删除了它多余的“-”号。


#7


引用 4 楼 sp1234 的回复:
顶上那一行,以及下面的命名空间声明,都会在你“跨平台”时造成无法修复的bug。

所以不要使用 xml,它太严格了,以至于你会遇到经常遇到诡异的格式问题。应该使用 json,而不是 xml。


使用你的思路,通过json的序列化与反序列化很好的解决了问题。

代码如下:
 public class Serializer
    {
        /// <summary>
        /// 序列化方法,把自定义实体类转化为Json格式的字符串
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="objToJson"></param>
        /// <returns></returns>
        public static string SerializeJson<T>(T objToJson)
        {
            DataContractJsonSerializer json = new DataContractJsonSerializer(objToJson.GetType());
            string resultString;
            //序列化
            using(MemoryStream stream=new MemoryStream ())
            {
                json.WriteObject(stream,objToJson);
                resultString = Encoding.UTF8.GetString(stream.ToArray());
                return resultString;
            }     
        }


        /// <summary>
        /// 反序列化方法。将客户端发来的Json转化为Collection<T>
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="sJson"></param>
        /// <param name="type"></param>
        /// <returns></returns>
        public static T DeserializeJson<T>(string sJson, Type type)
        {
            using (MemoryStream ms = new MemoryStream(Encoding.UTF8.GetBytes(sJson)))
            {
                DataContractJsonSerializer serializer = new DataContractJsonSerializer(type);
                object obj = serializer.ReadObject(ms);
                return (T)obj;
            }
        }
    }


感谢建议,结帖给分。
我再查查WebService的并发压力支撑问题。