灰灰狼

灰灰的狼

  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

访问WebService的方法有3大种:

1.       通过HttpGetPost方法

2.       通过SOAP

3.       .net的代理类

第一种只能访问本机的,后二种可以访问任何地方的。

使用最方便,编码量最少,且可配置性也较好的是第三种,所以应尽可能多的使用第三种,其代码就是实例化一个对象,然后调用其方法即可。

有时候(比如在开发阶段不知道要访问哪个服务)需要用前2种方式,因为第一种有只能访问本机的限制,所以不推荐使用,一般应用第二种,即SOAP方式,它也是WebService标准的交互协议,其实就是基于Http协议之上,对输入和输出参数的字符串格式的规定。

SOAP又分为1.11.2两种,它们的区别仅限于XML编码和TagName,调用过程没有区别,都是基于HttpPost,拿1.1为例:

1.       首先通过在浏览器里输入http://domain/ServiceName.asmx?op=FunName 查看其输入和输出的样例(里面有1.11.2两种)。

2.       用服务地址(如http://domain/ServiceName.asmx )实例化一个HttpWebRequest类,然后设置其方法名(SOAPAction, ContentType等属性

3.       发出调用请求(即把SOAP消息写入到请求流)。

4.       接收响应(是一个XmlDocument对象)。

代码如下:

 

        public static XmlDocument CallWebServiceBySoap(string serviceUrl, string argString)

        {

            // For example: serviceUrl = "http://localhost:2258/ComplexService.asmx?"

            // argString = "op=DoSomething&input=<a>1</a><b>2</b>"

            // op is function name

 

            try

            {

                //return QueryPostWebService(serviceUrl, Encoding.UTF8.GetBytes(argString));

                char[] sepKey = "&".ToCharArray();

                char[] sepValue = "=".ToCharArray();

                string[] pas = argString.Split(sepKey);

                StringBuilder sb = new StringBuilder();

                string funName = null;

                foreach (string pa in pas)

                {

                    string[] ps = pa.Split(sepValue);

                    if (ps[0] == "op")

                    {

                        funName = ps[1];

                    }

                    else

                    {

                        sb.Append("<" + ps[0] + ">");

                        sb.Append(ps[1]);

                        sb.Append("</" + ps[0] + ">");

                    }

                }

 

                string soapFmt =

    @"<?xml version=""1.0"" encoding=""utf-8""?>

<soap:Envelope xmlns:xsi=""http://www.w3.org/2001/XMLSchema-instance""

   xmlns:xsd=""http://www.w3.org/2001/XMLSchema""

   xmlns:soap=""http://schemas.xmlsoap.org/soap/envelope/"">

  <soap:Body>

    <{0} xmlns=""http://tempuri.org/"">

      {1}

    </{0}>

  </soap:Body>

</soap:Envelope>";

 

                string soap = string.Format(soapFmt, funName, sb.ToString());

 

                HttpWebRequest req = (HttpWebRequest)WebRequest.Create(serviceUrl);

                req.Headers.Add("SOAPAction", string.Format("\"http://tempuri.org/{0}\"", funName));

                req.ContentType = "text/xml;charset=\"utf-8\"";

                req.Accept = "text/xml";

                req.Method = "POST";

 

                using (Stream stm = req.GetRequestStream())

                {

                    using (StreamWriter stmw = new StreamWriter(stm))

                    {

                        stmw.Write(soap);

                    }

                }

 

                WebResponse response = req.GetResponse();

 

                //Stream responseStream = response.GetResponseStream();

                XmlDocument doc = ReadXmlResponse(response);

                return doc;

            }

            catch

            {

                //EntLibLogger.LogCriticalException(

                //    string.Format("Web Service error: url = {0}, args = {1}"

                //    , serviceUrl, argString));

                throw;

            }

        }

       

参数部分需要有一定的构成格式,我封装了一个较通用的单参数(简单类型(如int,string)的参数不必用此,直接拼字符串即可,此处是为复杂类型设计的)示例(可以作为进一步扩展的基础,用于我们未来的的访问Web服务的项目),多参数可以进一步将最后2个参数改进为Dictionary

 

        private T GetFromWebServiceBySoap<T>(string serviceUrl, string funName, string inputParaName, object input)

        {

            // Prepare Input

            string inputStr = ObjectSerializer.Serialize(input);

            XmlDocument docInput = new XmlDocument();

            docInput.LoadXml(inputStr);

            string inputXml = docInput.DocumentElement.InnerXml;

            string argString = string.Format("op={0}&{1}={2}", funName, inputParaName, inputXml);

 

            // Call & Get Result XmlDocument

            XmlDocument docResult;

            docResult = WebServiceAccess.CallWebServiceBySoap(serviceUrl, argString);

 

            // DeSerialize to Result Object

            Type resultType = typeof(T);

            string objStr = docResult.DocumentElement.ChildNodes[0].ChildNodes[0].ChildNodes[0].OuterXml;

            string tagName = docResult.DocumentElement.ChildNodes[0].ChildNodes[0].ChildNodes[0].Name;

            objStr = objStr.Replace("<" + tagName, "<" + resultType.Name);

            objStr = objStr.Replace("</" + tagName, "</" + resultType.Name);

            docResult.LoadXml(objStr);

            docResult.LoadXml(docResult.OuterXml.Replace(docResult.DocumentElement.NamespaceURI, ""));

            docResult.DocumentElement.RemoveAllAttributes();

            objStr = docResult.OuterXml;

            T result

                = ObjectSerializer.DeSerializerString2Object<T>(objStr);

 

            // Return Result

            return result;

        }

工具类:

public static class ObjectSerializer

    {

        public static string Serialize(object objToXml)

        {

            if (objToXml == null)

                throw new ArgumentNullException("objToXml");

 

            XmlSerializer serializer;

            XmlSerializerNamespaces xsn;

            StringWriter writer;

 

            serializer = new XmlSerializer(objToXml.GetType());

            xsn = new XmlSerializerNamespaces();

            xsn.Add(String.Empty, String.Empty);

            writer = new StringWriter();

 

            serializer.Serialize(writer, objToXml, xsn);

 

            return writer.GetStringBuilder().ToString();

        }

        public static T DeSerializerString2Object<T>(string sXml)

        {

            if (sXml == null)

                throw new ArgumentNullException("sXml");

 

            XmlReader reader = XmlReader.Create(new StringReader(sXml));

            XmlSerializer serializer = new XmlSerializer(typeof(T));

            object obj = serializer.Deserialize(reader);

            return (T)obj;

        }

    }

 

调用示例:

protected void Button2_Click(object sender, EventArgs e)

        {

            TestEntities.ComplexInput input = new TestEntities.ComplexInput();

            input.a = 1;

            input.b = 2;

            string serviceUrl = "http://localhost:2258/ComplexService.asmx";

            TestEntities.ComplexResult complexResult

                = GetFromWebServiceBySoap<TestEntities.ComplexResult>(serviceUrl, "DoSomething", "input", input);

 

            lblMsg.Text = "complexResult.x = " + complexResult.x.ToString();

        }

其中输入和输出参数的类定义为:

public class ComplexInput

    {

        public int a;

        public int b;

    }

public class ComplexResult

    {

        public int x;

    }

Web服务代码为:

public class ComplexService : System.Web.Services.WebService

    {

        [WebMethod]

        public ComplexResult DoSomething(ComplexInput input)

        {

            ComplexResult complexResult = new ComplexResult();

            complexResult.x = input.a + input.b;

            return complexResult;

        }

}

posted on 2010-07-05 12:53  灰灰狼  阅读(2159)  评论(0编辑  收藏  举报