通过aps.net创建web services 3

 ASP.NET web services 之路

      .net 的两个主要特征是创建web service服务器和创建 web services客户端的能力,我们需要了解它的几个组件:用于DISCO(web services Discovery Language,web 服务发现语言)和WSDL(web services Description Language ,web 服务描述语言)

  构建服务器

    1.确认你是否安装了IIS和.Net Framework (或者安装了vs2005等以上版本)

    2.创建一个Asp.net 需要的虚拟目录。将其命名为"Test"(或者使用vs2008创建一个空的web项目).

    3.创建一个Test.asmx,把它放在这个虚拟目录中(如果使用vs不需要发布的话,就不需要后者了)。

    4.在这个文件的第一行添加webService 指示符(使用vs开发工具就无需下面两步操作)

      <%@ webService Class="TestClass" Language="C#"%>

    5.引用System和 System.web.Services命名空间。

    6.创建一个类"TestClass".

    7.使用如下代码:     

      public int add(int a,int  b),给类添加一个方法add.

     8.使用webMethod特性把这个方法声明为可调用的XML web Service,如下

      [webMethod]

      public int add(int a,int b)

      {

        return a+b;

      }

      9.我们可以使用本地的地址打开:http://localhost/text/test.asmx .(如果使用的是vs开发工具直接按F5)

    web service 公开的方法(都会使用webMethod的特性来标记)

    如果你需要查看生成的WSDL文档或者是DISCO的话只需要在地址后面加上"?WSDL"或"?DISCO  "就行了

剖析web service

       当请求进入IIS时,检查并且是否发出一个.asmx扩展文件,asp.net为了处理程序通过IIS进行注册,因此它请求完全被移交给ASP.Net进程。

  ASP.Net工作进程会检查这个请求,并且发现它在machine.config中注册了一个处理程序,用于扩展名为.asmx的资源请求。

    接着处理程序创建一个在处理程序中定义的类的实例,并且使用反射查看类所支持的操作以及这些操作如何路由。默认情况下,操作通过SOAPactiion HTTP标头映射

到方法,但这可以改变为映射到SOAPbody的第一个子元素。

    一旦消息路由,这个处理程序将使用XML序列化器发序列化XML请求,使之成为方法期望的参数,一旦方法返回返回值和任何输出参数又通过XML序列化映射成XML

。接着一个包含这个XML的SOAP响应被创建,并通过ASP.Net的HttpResquet上下文把响应发送回来,

  如果有异常会抛出到SoapException 中,一个SOAP错误将返回,同时HTTP状态码被设置为500或OK.

构建文档字面服务

    webService 默认是基于架构的,或者称为字面的XML。

    在.NET中,这些文档/字面服务的编程模型的扩展性是相当好的,你可以使用多种XML创建接收或响应的操作。

    例如:这个操作将购买订单文档作为SOAP<Body>内的请求(与实际相比,作了大量的简化)

      <PurchaseOrder   ID="1234">

          <Date>1/2/2013</Date>

          <Item>Widgets</Item>

          <Amout>400</Amout>

     </PurchaseOrder>

    接收文档响应看起来:  

      <PurchaseOrderReceipt>

          <ReceiptID>5678</ReceipID>

      </PurchaseOrderReceipt>

  可以用几种方式把这个XML映射成方法。

    1.

        [webMethod]

        [return:XmlElement("PurchaseOrderReceipt")]

        public void PurchaseOrder([XmlAttribute]string ID,DateTime Date,int Amout,out string ReceiptID)

        {

            ReceiptID="5678";

            retrun;

        }

        由于XmlElementAttribute 和XmlAttributeAttribute特性类用于XML序列化,所以必须导入System.Xml.Serialization;

        默认情况下,方法名被映射成根元素,方法的每一个参数会被映射成子元素,但是ID参数会映射成XML属性而不是子元素,因为序列化这一点被利用

      XmlAttribute特性覆盖。

        因为ReceiptID是一个输出参数,它被序列化成XML用于响应,并且它被当成响应包装元素的子元素,默认情况下这个名称是方法的名称结尾添上"Response"

      本来应该是"PurchaseOrderResponse",但这里是"PurchaseOrderReceipt"。也是因为有一个特性用于这个方法的返回值;使用XMLAttribute类,这个值就被设置

      成正确的值了。

      这中序列化的方法被称为Wrapped(包装的),因为方法名称被用于文档的根元素。

    2.

      [webMethod]

      [return:XmlElement("PurchaseOrderReceipt")]

      [SoapDocumentMethod(ParameterStyle=SoapParameterStyle.Bare)]

      public string PurchaseOrder(string ID,DateTime Date,int Amout)

      {

        return "5946";

      }

      这样做的结果是,方法被SOAP请求序列化时,将不会使用方法名称作为包装素(通白的将:就是不会把方法名作为根元素),称为Bare(没有包装的).

      通过使用SoapDocumentMethod特性,命名空间要引用:System.web.Services.Protocols

      3.

        通过第2个列子使用Bare参数风格,使得这些请求和响应都是非描述性的。但是仍然可以创建看起来像包装过的消息。可以创建反映你想创建的XML文档的类,

    这些类将会被以一种类似于方法的方式序列化。

      首先创建类

      public class Po

      {

         [XmlAttribute]

        public string ID;

        public DateTime Date;

        public int Amount;

      }

      再创建响应的类

      public Class PoReceipt

      {

          public string ReceiptID=“5649”;

      }

      

      [webMethod]

      [return:XmlAttribute("PurchaseOrderReceipt")]

      [SoapDoucmentMethod(ParameterStyle=SoapParameterSytle.Bare)]

      public string PurchaseOrder(Po purchaseOrder)

      {

        PoReceipt receipt=new PoReceipt();

        retrun receipt.ReceiptID;

      }

  构建文档编程服务

      综合上述,所举的例子都是基于文档;通白的讲就是文档在SOAP消息内传递。在webservices 中的这些文档被映射成方法,这纯粹只是一种编程模型思维,这是

请求-响应方式,但不同常规意义的远程方法调用。

      还有是基于模式,你可以在WSDL自动生成的类型部分中看到这个模式。模式包含序列化和反序列化XML所以信息时,WSDL将它称为字面(literal)消息。

    例如:

      要创建这个消息结构,需要在方法声明上改变一样东西,把SoapAttributeMethodAttribute特性的Use属性设置编码的(encoded)

      需要引入命名空间 System.web.services.Description

      [webMethod]

      [return:XmlElement("PurchaseOrderReceipt")]

      [SoapDocumentMethod(ParamentStyle=SoapParamentStyle.Bare,Use=SoapBindingUse.Encode)]

      public POReceipt PurchaseOrder(PO PurchaseOrder)

      {

          POReceipt receipt;

          return receipt;

      }

      使用编码的XML特性改成PO类,可以设置XML命名空间为:http://encode/

      [SoapType(Namespace="http://encode/")]

      [XmlRoot(Namespace="http://literal/")]

      public class PO

      {

        [XmlAttribute]

        public string ID;

        public DateTime Date;

        public int Amount;

      }

      注意,ID属性不再是XML属性。编码的SOAP不包括任何特性;全都是元素。

构建RPC编码服务

    什么是RPC先了解一下,RPC(Remote Procedure Call Protocol 远程过程调用协议),它是一种通过网络从远程计算机程序请求服务,而不需要了解底层网络技术的协议。

   有两种方法可以改变web services,使它从默认处理文档/籽面操作转变到处理RPC编码操作:SoapRpcServiceAttribute特性和SoapRpcMethodAttribute特性。

如果你使用SoapRpcServiceAttribute特性应用在类上,那么所以的方法都是Rpc编码的。但如果你想控制每一个方法,可以在每一个方法上用SoapRpcMethodAttribute特性。

  [webMethod]

  [SoapRpcMethod]

  public POReceipt PurchaseOrder(PO PurchaseOrder)

  {

    POReceipt receipt;

    return receipt;

  } 

构建单向服务

返回(202 Accepted);但不会有任何其他消息返回、

    返回值为Void的方法可以成为单向操作,除此之外,只需要把SoapDocumentMethodAttribute或者SoapRpcMethodAttribute属性的OneWay属性设置为True

  例如:

    [webMethod]

    [SoapRpcMethod(OneWay=true)]

    public void SubmitPurchaseOrder(PO PurchaseOrder)

    {

      retrun;

    }

  单向服务提供了一种快捷,激发并遗忘(fire-and-forget)的方式来发送消息的简单方法。它们还能更好地提高服务器的性能,因为在你的代码运行时,在保持打开的网咯连接上花费的时间更少。但是如果你要发送一个错误响应到客户端,将无法做到的。

控制路由  

    如果你有不止一个方法被标记为[webMethod],asp.net 如何来决定哪个方法应该接收和处理这个请求呢?Asp.net有两种选择机制,用于路由或分发:

      使用SoapAction HTTP标头

      使用<Body>元素的第一个元素

  你可以用SoapDocumentServic和SoapRpcService特性来控制路由的方法,默认的情况路由是使用SoapAction的值完成的。这需要服务中每个操作有一个唯一 的SOAPAction,如果做不到你可以是用<Body>元素的第一个元素来代替。

  例如:

    [SoapDocumentService(RoutingStyle=SoapServiceRoutingStyle.RequestElement)]

    public class routing:System.web.Services.webService

    {}

    还有就是要引入命名空间:System.web.Services.Protocols;

使用SOAP绑定

    webService描述语言(WSDL)是一种基于 XML的语法,用于描述XML WebService。 WSDL令人感兴趣的一个特征是它有对操作进行抽象的描述的能力,或者通常说的绑定(binding).

    使用webServiceBindingAttribute特性来指明一个webservice实现了一个众所周知的抽象绑定。

  这个特性会在自动生成的WSDL文档创建一个WSDL输入语句。然后通过SoapDocumentMethodAttribute或SoapRpcMethodAttribute,或者两者,指明在服务中那些方法实现在绑定中描述的那些操作。

异步实现一个服务器 

    使用SOAP标头,先不管它有什么用途。

     1.创建一个派生于System.Web.Services.Procotols.SoapHeader类的类,它就是你要的序列化成SOAP的类

     2.在类中添加前面这个类类型的一个成员变量

     3、在任何你想要使用SOAP标头的方法上应用[SoapHeader]特性

     4.使用这个成员变量读写数据到标头中

      类中要引用System.Web.Services.Procotols和System.Xml.Serialization

      public Class AuthHeader:SoapHeader

      {  

          public string UserName;

          public string PassWord;

          [XmlAttribute]

          public String Domain;

      }

      public Class HeaderTest

      {  

          public AuthHeader auth;

          [webMethod]

          [SoapHeader("auth")]

          public String WhoAmI()

          {

              retrun auth.UserName;

          }

      } 

    [SoapHeader]特性包含许多属性,包括描述标头的指示(Direction)属性,默认值为Out,或者 in或out。

     public Class HeaderTest

      {  

          public AuthHeader auth;

          [webMethod]

          [SoapHeader("auth",Direction=SoapHeaderDirection,InOut)]

          public String WhoAmI()

          {

              retrun auth.UserName;

          }

      } 

原文地址:https://www.cnblogs.com/jzhou/p/3152928.html