杞人忧天上掉下个林妹妹

穿越旷野的妹妹啊,慢些走;请不要用你的沉默告诉我,你不回头!

导航

Web Services

  1.       Web Services基本规范概述

1.1.   什么是Web Services

Web Services是为实现“基于Web无缝集成”的目标而提出的全新概念,希望通过Web Services能够实现不同的系统之间能够用“软件-软件对话”的方式相互调用,打破软件应用、网站和各种设备之间格格不入的状态。

Web Services是一个应用程序,它向外界暴露一个能够通过Web进行调用的API,这就是说,能够用编程的方法通过web调用来实现某个功能的应用程序。

Web Services是一种新的Web应用程序分支,它们是自包含、自描述,模块化的应用,可以在网络中被描述、发布、查找以及通过Web调用。

1.2.   UDDI (Universal Description Discovery and Integration)

UDDI即统一描述、发现和集成(Universal Description , Discovery , and Integration),其目的是为电子商务建立标准,UDDI是一套基于Web的、分布式、为Web Services提供的、信息注册中心的实现标准规范,同时也包含一组是企业能将自身提供的Web Services注册,可以使别的奇特能够发现访问间协议的实现标准。

1.3.   WSDL (Web Service Description Language)

Web Service描述语言(WSDL)是用计算机能阅读的方式提供的一个正式描述文档而基于XML的语言,用于描述Web Service及其函数、参数和返回值。因为是基于XML的,所以WSDL既是机器可阅读的,又是人可阅读的。

1.4.   XMLXSD

可扩展性标记语言XMLWeb Service平台中表示数据的基本格式。除了易于建立和易于分析外,XML主要的优点在于它基于平台无关,由于厂商无关。XML是由万维网协会(W3C)创建,W3C制定的XML Schema XSD定义了一套标准的数据类型,并给出了一种语言来拓展这套数据类型。
Web Service平台是用XSD来作为数据类型系统的。当用某种语言如VB.NET C#来构造一个Web Service是,为了符合Web Service标准,所有使用的数据类型都必须被转换为XSD类型。如想让他使用在不同的平台和不同的软件的不同组织间传递,还需要用某种东西将它包装起来。这种东西就是一种协议,如SOAP

1.5.   SOAP (Simple Object Access Protocol)

SOAP即简单对象访问协议(Simple Object Access Protocol),它是用于交换XML编码信息的轻量级协议,是基于XMLHTTP的分布式对象的通信协议。

SOAP它包括四个部分:SOAP封装(envelop),封装定义了一个描述消息中的内容是什么,是谁发送的,谁应当接受并处理它以及如何处理它们的框架;SOAP编码规则(encoding rules),用于表示应用程序需要使用的数据类型的实例; SOAP RPC表示(RPC representation),表示远程过程调用和应答的协定;SOAP绑定(binding),使用底层协议交换信息。

SOAP简单的理解,就是这样的一个开放协议SOAP=RPC+HTTP+XML:采用HTTP作为底层通讯协议;RPC作为一致性的调用途径,XML作为数据传送的格式,允许服务提供者和服务客户经过防火墙在INTERNET进行通讯交互。

1.6.   SOAP 信封

Web 服务消息的基本单元是实际的 SOAP 信封。这是包含处理消息所必需的所有信息的 XML 文档:

POST /PCSWebService3/Service.asmx HTTP/1.1
Host: localhost
Content-Type: application/soap+xml; charset=utf-8
Content-Length: length
 
<?xml version="1.0" encoding="utf-8"?>
<soap12:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap12="http://www.w3.org/2003/05/soap-envelope">
 <soap12:Header>
    <AuthenticationToken xmlns="http://tempuri.org/">
      <InnerToken>guid</InnerToken>
    </AuthenticationToken>
 </soap12:Header>
 <soap12:Body>
    <DoSomething xmlns="http://tempuri.org/" />
 </soap12:Body>
</soap12:Envelope>

SOAP Header

SOAP 消息中的 Header用于提供有关消息本身的信息。例如,Header可以包括路由信息、自定义信息等

 <soap12:Header>
    <AuthenticationToken xmlns="http://tempuri.org/">
      <InnerToken>guid</InnerToken>
    </AuthenticationToken>
 </soap12:Header>

SOAP

发送 SOAP 消息时,都是有目的性的。在尝试告诉接收者执行某种操作,或尝试向服务器传递相关信息。此信息称为有效负载。有效负载位于 Envelope Body中。它还具有自己的命名空间。

 <soap12:Body>
    <DoSomething xmlns="http://tempuri.org/" />
 </soap12:Body>

1.7.   远程过程调用RPC与消息传递

Web Service本身其实是在实现应用程序的通信。现在有两种应用程序通信的方法:RPC远程过程调用和信息传递。使用RPC的时候,客户端的概念是调用服务器上的远程过程,通常的方式为实例化一个远程对象并调用其方法和属性。RPC系统试图达到一种位置上的透明性:服务器暴露出远程对象的端口,而客户端就好像在本地使用这些对象的接口一样,这样就隐藏的底层的信息,客户端也就根本不需要知道对象是在哪台机器上。

2.       Web Services结构

在这张图中,从左到右表示出Web Services在提供者和使用者之间操作的几个主要步骤。横向上则是每个步骤使用到的标准。这张图可以很清楚的了解到Web Services的基本运行和上面这些标准的关系。需要说明的是,寻找服务同时使用到了UDDISOAP,原因是这里UDDI的目录服务也是通过Web Services来提供的。

3.       Web Services引用

3.1.   添加Web引用

在添加Web引用窗体中选择您所使用到的Web服务

选择后,在Web引用名(N)中输入该Web Services的名称

点击“添加引用”后即Web Services添加完成,会自动在目录App_WebReferences中生成该服务的描述文件。

3.2.   使用Web Services

详见:5.2示例

3.3.   发布配置

在添加引用时,系统会自动为web.config文件添加如下配置:

<configuration>

     <appSettings>

     <addkey="MyWebServices.Service"value="http://localhost:1249/Services2/Service.asmx"/>

</appSettings>

<connectionStrings/>

Web ServicesWeb应用发布时,由于Web Services访问URL发生改变,因此需要修改Web应用的web.config中的Web Services服务引用URL

3.4.   一个网上的免费Web Services

http://www2.flash8.net/teach/4830.htm

http://www.webservicex.net/globalweather.asmx

http://www.webservicex.net/CurrencyConvertor.asmx

4.       Web Services状态管理及生存期

.NET Web Services 是建立在 ASP.NET 基础上,在 Web Services 中我们同样可以访问 SessionUserApplication 等上下文对象,不过在某些使用细节上有所不同。

4.1.   Application

Application 的使用和 WebForm 中基本没有什么区别

4.2.   Session

由于 WebService 客户端代理对象可能应用于 ConsoleApplicationWinForm WebForm 等环境,而 Session 又必须通过 Cookie 来保存唯一的 SessionID,因此我们必须使用 CookieContainer 创建 Cookie 容器来保存 WebService 返回的 Session 信息,否则每次调用的 SessionID 都不同,自然无法使用 Session 来保存状态了。

创建容器对象后,必须将其引用赋值给代理对象的 CookieContainer 属性。在第一次调用 SessionEnabled WebMethod 后,该容器将持有 Session Cookie 信息。如果需要在多个代理对象中调用 SessionEnabled WebMethod,那么它们必须持有同一个 Cookie 容器对象。

在默认情况下Web Services并不会创建客户端会话,必须使用WebMethod属性的EnableSession子属性来表明服务类的哪能个方法需要了解客户端状态。

[WebMethod(EnableSession=true)][WebMethod(true)]

Web Services使用端需要使用System.Net命名空间,因为它包含CookieContainer类。这个类用于存储Cookie的引用,如果运行使用会话状态的Web Services,就需要它。Web Services需要在客户的多个调用之间,以某种方式检索正确的会话状态,通过它在每次回送时重新创建服务的代理。检索Web Services使用的Cookie,以存储会话状态,在Web Services调用之间存储它,然后在以后的调用中使用它,应试可以在Web Services中维护正确的会话状态。

Web Services   

[WebMethod(EnableSession = true)]

    public int GetCallCount()

    {

        int callCount = 0;

        if (Session["CallCount"] != null)

        {

            callCount = Convert.ToInt32(Session["CallCount"].ToString());

        }

        callCount++;

        Session["CallCount"] = callCount;

        return(callCount);

}

Web Services使用端

    private MyWebServices.WebServiceSession wss;

    protected void Page_Load(object sender, EventArgs e)

    {

        wss = new MyWebServices.WebServiceSession();

        wss.Credentials = CredentialCache.DefaultCredentials;

        CookieContainer serviceCookie;

        //检查已存储的CookieContainer实例或创建一个新的实例

        if (Session["WSSessionID"] == null)

        {

            serviceCookie = new CookieContainer();

        }

        else

        {

            serviceCookie = (CookieContainer)Session["WSSessionID"];

        }

        //将CookieContainer赋予Web Services代理类,以准备在调用后接收Web Services的Cookie信息。

        wss.CookieContainer = serviceCookie;

        Session["WSSessionID"] = serviceCookie;

    }

    protected void Button1_Click(object sender, EventArgs e)

    {

        Label1.Text = "请求次数" + Convert.ToString(wss.GetCallCount());

}

4.3.   生存期

正常情况下,每次调用 WebMethod,服务器都会创建一个新的 Web Service 对象,即便客户端使用同一个代理对象多次调用 WebMethod。而我们一旦调用了有缓存标记的 WebMethod,只要未超出缓存期,WebService 对象都不会被重新创建。有很多因素让这个缓存机制变得不那么可靠,因此我们不能奢望用缓存标记来维持特定的对象状态,况且缓存机制的设计初衷也只是为了快速输出那些比较稳定非常大的数据。

基于多用户并发调用这个环境,WebService 本身最好设计成无状态对象,我们可以使用 Session Application 来保持特定的状态信息。

5.       Web Services可以使用的类型

5.1.   可以使用的类型

String

Char

Byte

Boolean

Int16

Int32

Int64

Uint16

Uint32

Uint64

Single

Double

Guid

Decimal

DataTime

XmlQualifiedName

Class

Struct

XmlNode

DataSet

Enum

以上所有类型的数组都可以使用,因为它们都是一般集合类型,例如List<string>。还要注意,只能编组ClassStruct类型的公共属性和字段。

5.2.   示例

5.2.1.Service.cs

using System;

using System.Web;

using System.Data;

using System.Web.Services;

using System.Web.Services.Protocols;

using System.Xml;

namespace SoapDataType

{

    //枚举类型

    public enum Mode

    {

        On = 1,

        Off = 2

    }

    //结构类型

    public struct Order

    {

        public int OrderID;

        public double Price;

        public int ORDERID

        {

            get

            {

                return (100);

            }

        }

        //无法编组方法

        public static int GetSum(int val1, int val2)

        {

            return (val1 + val2);

        }

        //无法编组方法

        public int GetValue(int val1, int val2, int val3)

        {

            return (val1 + val2 + val3);

        }

    }

    //

    public class Person

    {

        private string name;

        public string Name

        {

            get

            {

                return name;

            }

            set

            {

                name = value;

            }

        }

        //无法编组方法

        public static int GetSum(int val1, int val2)

        {

            return (val1 + val2);

        }

        //无法编组方法

        public int GetValue(int val1, int val2, int val3)

       {

            return (val1 + val2 + val3);

        }

    }

    [WebService(Namespace = "http://tempuri.org/")]

    [WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]

    public class Service : System.Web.Services.WebService

    {

        [WebMethod]

        //传人对象,操作类

        public string Hello(Person p)

        {

            return "Hello " + p.Name;

        }

        [WebMethod]

        //操作基类元素

        public int[] getIntArray()

        {

            int[] a = new int[5];

            for (int i = 0; i < 4; i++)

            {

                a[i] = i;

            }

            return a;

        }

        [WebMethod]

        //操作枚举

        public Mode getMode()

        {

            return Mode.Off;

        }

        [WebMethod]

        //操作结构

        public Order getOrder()

        {

            Order myOrder = new Order();

            myOrder.OrderID = 2222;

            myOrder.Price = 22.2;

            return myOrder;

        }

        [WebMethod]

        //操作结构数组

        public Order[] getOrders()

        {

            Order[] myOrder = new Order[2];

            myOrder[0].OrderID = 2222;

            myOrder[0].Price = 22.2;

            myOrder[1].OrderID = 3333;

            myOrder[1].Price = 33.3;

            return myOrder;

        }

       [WebMethod]

        //操作数据集

        public DataSet getDataSet()

        {

            DataSet ds = new DataSet();

            DataRow dr;

            DataColumn dc;

            //Table1

            ds.Tables.Add(new DataTable());

            dc = new DataColumn("Name");

            ds.Tables[0].Columns.Add(dc);

            dc = new DataColumn("Age");

            ds.Tables[0].Columns.Add(dc);

            dr = ds.Tables[0].NewRow();

            dr["Name"] = "zwx";

            dr["Age"] = 26;

            ds.Tables[0].Rows.Add(dr);

            //Table2

            ds.Tables.Add(new DataTable());

            dc = new DataColumn("Hist");

            ds.Tables[1].Columns.Add(dc);

            dc = new DataColumn("Record");

            ds.Tables[1].Columns.Add(dc);

            dr = ds.Tables[1].NewRow();

            dr["Hist"] = "zhong guo";

            dr["Record"] = 100;

            ds.Tables[1].Rows.Add(dr);

            return ds;

        }

        [WebMethod]

        //操作XmlNode

        public XmlElement getXmlNode()

        {

            XmlDocument xdoc = new XmlDocument();

            XmlElement node = xdoc.CreateElement("Hello");

            node.InnerXml = "zwx";

            return node;

        }

    }

}

5.2.2.Default.aspx.cs

using System;

using System.Data;

using System.Configuration;

using System.Web;

using System.Web.Security;

using System.Web.UI;

using System.Web.UI.WebControls;

using System.Web.UI.WebControls.WebParts;

using System.Web.UI.HtmlControls;

using System.Xml;

public partial class _Default : System.Web.UI.Page

{

    protected void Page_Load(object sender, EventArgs e)

    {

        MyWebServices.Service s = new MyWebServices.Service();

        Write("类参数:public string Hello(Person p)");

        WriteBR();

        MyWebServices.Person person = new MyWebServices.Person();

        person.Name = "zwx";

        Write(s.Hello(person));

        WriteBR();

        WriteBR();

        Write("基本类型数组参数:public int[] getIntArray()");

        int[] val = s.getIntArray();

        for (int i = 0; i < val.Length; i++)

        {

            WriteBR();

            Write(val[i].ToString());

        }

        WriteBR();

        WriteBR();

        Write("枚举参数:public Mode getMode()");

        MyWebServices.Mode mode = s.getMode();

        WriteBR();

        Write(mode.ToString());

        WriteBR();

        WriteBR();

        Write("结构体参数:public Order getOrder()");

        MyWebServices.Order order = s.getOrder();

        WriteBR();

        Write("OrderID:" + order.OrderID.ToString());

        WriteBR();

       Write("Price:" + order.Price.ToString());

        WriteBR();

        WriteBR();

        Write("结构体数组参数:public Order[] getOrders()");

        MyWebServices.Order[] orders = s.getOrders();

        for (int i = 0; i < orders.Length; i++)

        {

            WriteBR();

            Write("Order" + i.ToString() + "&nbsp;&nbsp;&nbsp;&nbsp;");

            Write("OrderID:" + order.OrderID.ToString());

            Write("&nbsp;&nbsp;&nbsp;&nbsp;");

            Write("Price:" + order.Price.ToString());

        }

        WriteBR();

        WriteBR();

        Write("DataSet参数:public DataSet getDataSet()");

        DataSet ds = s.getDataSet();

        for (int i = 0; i < ds.Tables.Count; i++)

        {

            WriteBR();

            Write("&nbsp;&nbsp;");

           Write("Tabale Name " + ds.Tables[i].TableName);

            Write("&nbsp;&nbsp;&nbsp;&nbsp;");

            Write("Table Row Count " + ds.Tables[i].Rows.Count.ToString());

            for (int j = 0; j < ds.Tables[i].Rows.Count; j++)

            {

                WriteBR();

                for (int k = 0; k < ds.Tables[i].Columns.Count; k++)

                {

                    Write("&nbsp;&nbsp;&nbsp;&nbsp;");

                    Write(ds.Tables[i].Columns[k].ColumnName + ":");

                    Write(ds.Tables[i].Rows[j][k].ToString());

                }

            }

        }

        WriteBR();

        WriteBR();

        Write("XmlNode参数:public DataSet getDataSet()");

        XmlElement node = s.getXmlNode();

        WriteBR();

        Write("InnerXml:" + node.InnerXml);

    }

    private void Write(string txt)

    {

        this.Response.Write(txt);

    }

    private void WriteBR()

    {

        this.Response.Write("<br>");

    }

}

5.3.   C#Web Services附件参数的传递(未整理)

6.       自定义SOAP

创建SOAP头需要有三个步骤

6.1.   自定义 SoapHeader 类型

using System;

using System.Web.Services.Protocols;

//创建一个从System.Web.Services.Protocols类派生而来的类,用它代表SOAP头。这个类的公共字段和属性定义了作为SOAP头传输的数据。

public class AuthenticationToken :SoapHeader

{

    ///<summary>

    ///身份认证后的唯一标识Guid

    ///</summary>

    public Guid InnerToken;

    ///<summary>

    ///访问次数

    ///</summary>

    public int CallCount;

}

6.2.   声明自定义SoapHeader

public class WebServiceSoapHeader : System.Web.Services.WebService

{

    ///<summary>

    ///将AuthenticationToken的公共成员添加到Web Services类中。处理包含在客户请求中的SOAP头或者在准备一个要发送回客户端的SOAP头时,您要通过该成员的字段来填充头中的数据。

    ///</summary>

public AuthenticationToken AuthenticationTokenHeader;

}

6.3.   应用

SoapHeader属性应用到Web Services方法或用来处理SOAP头的方法

6.3.1.Web Servies

SoapHeaderAttributeMemberNameDirectionRequired

MemberNameWeb Services成员(其中存储了代表SOAP头内容的对象)的名称。

Direction:指定是否向Web Services、客户端应用程序或都两者都发送SOAP头。

使用SoapHeaderDirection枚举的成员来指定Direction。有效值有:

InSOAP头被发送到Web Services。接收到SOAP消息时,ASP.NET创建一个SOAP头类的实例,用SOAP头中包含的数据填充它,并将它分配给由MemberName属性指定的Web Services成员。

OutSOAP头被发送到Web Services服务的客户端。当Web Services服务方法完成时,.NET运行库从MemberName属性标识的Web Services成员中获取值,并将它打包到返回客户的SOAP头中。

InOut:向Web Services和客户都发送SOAP头。这个值联合了以上InOut值中描述的动作。

Required:指示是否解析SOAP头以及接收端是否处理它。

    //指示接收SOAP头中的信息

    [SoapHeaderAttribute("AuthenticationTokenHeader", Direction = SoapHeaderDirection.InOut)]

    [WebMethod]

    public string DoSomething()

    {

        if (this.Application["currentUser"] != null &&

            AuthenticationTokenHeader != null &&

            AuthenticationTokenHeader.InnerToken

            == (Guid)this.Application["currentUser"])

        {

            AuthenticationTokenHeader.CallCount++;

            return "认证成功。";

        }

        else

        {

            return "认证失败。";

        }

}

6.3.2.Web Servies使用端

            MyWebServices.WebServiceSoapHeader wssh = new MyWebServices.WebServiceSoapHeader();

            //将登录认证的Guid构造后赋予Web Services的头信息,使用Web Services端接收并做验证

            MyWebServices.AuthenticationToken header = (MyWebServices.AuthenticationToken)Session["Header"];

            wssh.AuthenticationTokenValue = header;

            //访问Web Services

            result = wssh.DoSomething();

            //访问完Web Services后,接收由Web Services返回的头信息

            header = wssh.AuthenticationTokenValue;

            Session["Header"] = header;

7.       异步调用Web Services(未整理)

异步调用与委托的结合使用

异步示例

8.       发布Web Services(未整理)

安全性、布署等

posted on 2007-09-13 17:39  杞人  阅读(986)  评论(0编辑  收藏  举报