享受代码,享受人生

SOA is an integration solution. SOA is message oriented first.
The Key character of SOA is loosely coupled. SOA is enriched
by creating composite apps.
  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

Use Web Service Thought Message --- SoapClient

Posted on 2006-06-28 12:34  idior  阅读(3629)  评论(3编辑  收藏  举报

在本次实践中,我们将直接使用SOAP 消息来调用Web Service并从返回的SOAP 消息中获得结果。通过这种更底层的操作,你将了解到Web Service面向消息的本质,并加深对WS-Addressing规范的理解。

 
在本例中
, Web Service仍旧和上次实践中的一样,是一个和数学运算有关的Asmx类型的Web service。变化的只是Client端,通常情况下,我们都是通过添加Web引用生成Proxy类的方法来访问Web Service, 这里我们将直接采用发送并接受SOAP消息的方法。

 

WSE中提供了SoapClient这么一个抽象类,通过继承它,我们可以方便的向Service发送一个SOAP消息,从而触发Service端执行相应的操作(方法),并将结果返回。

下面就是为了使用MathService, SoapClient派生出来的MathClient

 1     public class MathClient:SoapClient
 2     {
 3         public MathClient(Uri destination):base(destination){}
 4 
 5         [SoapMethod("http://idior.cnblogs.com/mathservice/Add")]
 6         public double Add(double a,double b)
 7         {
 8             SoapEnvelope sendEnvelope = CreateMessage("Add",a,b);
 9 //          sendEnvelope.Context.Addressing.Action = "http://idior.cnblogs.com/mathservice/Add";
10             
11             SoapEnvelope receiveEnvelope = base.SendRequestResponse("Add", sendEnvelope);
12             double result = XmlConvert.ToDouble(receiveEnvelope.InnerText);
13             return result;
14         }
15         
16         private SoapEnvelope CreateMessage(string op,double a,double b)
17         {
18             // create SOAP message
19             SoapEnvelope envelope = new SoapEnvelope();
20             envelope.CreateBody(); // must create body before setting it
21             envelope.Body.InnerXml =string.Format(
22             @"<{0} xmlns='http://idior.cnblogs.com/mathservice/'>
23               <a>{1}</a>
24               <b>{2}</b>
25             </{0}>",op,a,b);
26             return envelope;
27         }
28     }

1     class Program
2     {
3         static void Main()
4         {
5             MathClient mathClient = new MathClient(new Uri("http://localhost:1274/MathService/MathService.asmx"));
6             double result = mathClient.Add(12,10);
7             Console.WriteLine(result);
8         }
9     }


如我在 WS-Addressing Message Addressing Properties 一文中所说,Soap消息中Message Addressing Properties的To以及Action属性决定了消息如何寻址到Service中的某个特定的方法。

在Line3中通过设定SoapClient的destination,间接的设定了利用该SoapClient发送的消息的To的值,而在Line5中我们为Add方法声明了它的Action属性的值,并且在Line11中SendRequestResponse方法的第一个参数中指定了使用Add方法,通过它和Line6中的声明,该消息的Action属性被确定下来。当然你也可以使用Line9的方法显式的设定消息的Action属性。

以下是最终产生的Request Message和Response Message,可以发现它们和使用Proxy访问Web Service基本一致。

Request Message:
<?xml version="1.0" encoding="utf-8" ?>
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"
              xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
              xmlns:xsd="http://www.w3.org/2001/XMLSchema"
              xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/08/addressing"
              xmlns:wsse="http://.../oasis-200401-wss-wssecurity-secext-1.0.xsd"
              xmlns:wsu="http://.../oasis-200401-wss-wssecurity-utility-1.0.xsd">
  <soap:Header>
    <wsa:Action>http://idior.cnblogs.com/mathservice/Add</wsa:Action>
    <wsa:MessageID>urn:uuid:84081759-3558-4718-b3ba-b08217a9d50f</wsa:MessageID>
    <wsa:ReplyTo>
       <wsa:Address>http://.../addressing/role/anonymous</wsa:Address>
    </wsa:ReplyTo>
    <wsa:To>http://localhost:1274/MathService/MathService.asmx</wsa:To>
    <wsse:Security>
       <wsu:Timestamp wsu:Id="Timestamp-ba231e59-2ac9-44f0-ba86-441dea7aebb6">
         <wsu:Created>2006-06-27T04:06:44Z</wsu:Created>
         <wsu:Expires>2006-06-27T04:11:44Z</wsu:Expires>
      </wsu:Timestamp>
    </wsse:Security>
  </soap:Header>
  <soap:Body>
    <Add xmlns="http://idior.cnblogs.com/mathservice/">
      <a>12</a>
      <b>10</b>
    </Add>
  </soap:Body>
</soap:Envelope>

Response Message:
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xmlns:xsd="http://www.w3.org/2001/XMLSchema"
             xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/08/addressing"
             xmlns:wsse="http://.../oasis-200401-wss-wssecurity-secext-1.0.xsd"
             xmlns:wsu="http://.../oasis-200401-wss-wssecurity-utility-1.0.xsd">
  <soap:Header>
     <wsa:Action>http://idior.cnblogs.com/mathservice/AddResponse</wsa:Action>
     <wsa:MessageID>urn:uuid:020a58d0-cdbf-437c-8cd1-dbbbbc6443f7</wsa:MessageID>
     <wsa:RelatesTo>urn:uuid:84081759-3558-4718-b3ba-b08217a9d50f</wsa:RelatesTo>
     <wsa:To>http://.../addressing/role/anonymous</wsa:To>
     <wsse:Security>
        <wsu:Timestamp wsu:Id="Timestamp-a95201b2-d3d1-40a9-9cc4-8632b10b438e">
           <wsu:Created>2006-06-27T04:06:47Z</wsu:Created>
           <wsu:Expires>2006-06-27T04:11:47Z</wsu:Expires>
        </wsu:Timestamp>
     </wsse:Security>
  </soap:Header>
  <soap:Body>
     <AddResponse xmlns="http://idior.cnblogs.com/mathservice/">
        <AddResult>22</SubResult>
     </AddResponse>
  </soap:Body>
</soap:Envelope>

参考资料:
WS-Addressing Message Addressing Properties


备注:
你可以通过下面的属性Line9,在代码中显式(explicit)设定Service中某个方法的SoapAction,并影响到最终的WSDL.不过由于该属性不属于WSE,所以你只能修改Input Ation.而无法修改Output Action, 而在WSE中有一个SoapMethod的属性可以同时设定两者。

 1     [WebServiceBinding(
 2       Name = "MathService",
 3       Namespace = "http://idior.cnblogs.com/mathservice/",
 4       ConformsTo = WsiProfiles.BasicProfile1_1,
 5       EmitConformanceClaims = true)]
 6     public interface IMathService
 7     {
 8         [WebMethod()]
 9         [SoapDocumentMethod("http://idior.cnblogs.com/mathservice/Add")]
10         double Add(double a, double b);
11 
12         [WebMethod()]
13         double Sub(double a, double b);
14     }