私はしばらく WebService を書いてきましたが、WebService の動作原理について収集し理解した内容をまとめます。
WebService は主に、Tcp/Ip に基づくアプリケーション層プロトコルである Http プロトコルを使用します。 : 現在の WebService 開発のほとんどはソケットのリアルタイム通信を非常にうまくサポートできていますが、それでも http はその本質です。)
HTTP は "request-----response" モードを採用しています;
HTTP 通信はシリアル化されます。 XML を介した通信 The...
Http 通信プロセス: .asmx ハンドルの呼び出し、XML、XSD、SOAP および WSDL 処理、
XML には 3 つの主要な側面があります: (次の記事は http:// から引用) dev.csdn .net/article/19/19185.shtm)
個人的には、SOAPリクエストメッセージとレスポンスメッセージのxml形式をマスターするのがメインだと感じています...
メッセージディスパッチ
のとき。 asmx ハンドルは、HTTP パイプラインによって呼び出されます。.asmx ファイル内の WebService 宣言によって、どの .NET クラスがチェックされるかが決まります。次に、受信 HTTP メッセージ内の情報を監視し、参照クラス内のどのメソッドを呼び出すかを決定します。前の例で Add メソッドを呼び出すには、HTTP リクエスト メッセージは次のようになります。
上記の HTTP リクエスト メッセージには、クラス内のどのメソッドを決定するために使用できる 2 つの情報があります。呼び出す対象: リクエストの SOAPAction ヘッダーまたは SOAP 本体 要素の名前。この例では、各メソッドは送信者が呼び出したいメソッドの名前を示します。
.asmx ハンドルは、SOAPAction ヘッダーの値を使用してメッセージ ディスパッチを実装します。したがって、.asmx ハンドルはメッセージ内の SOAPAction ヘッダーを調べ、.NET マッピングを使用して参照されたクラス内のメソッドをチェックします。 [WebMethod] 属性でマークされたメソッドのみが考慮されますが、各メソッドの SOAPAction 値を確認することで、どのメソッドを呼び出すかが具体的に決定されます。クラスで SOAPAction の値を明示的に指定していないため、.asmx ハンドルは、SOAPAction の値が Web サービスの名前空間とメソッド名を加算したものであると想定します。また、名前空間を指定しなかったため、ハンドラーはデフォルトで http://tempuri.org になります。このように、Add メソッドのデフォルトの SOAPAction 値は http://tempuri.org/Add になります。
Webサービスの名前空間は次のようにカスタマイズできます。クラスを [WebService] 属性でマークし、WebMethods を [SoapDocumentMethod] 属性でマークして、特定の SOAPAction 値を指定します。例は次のとおりです。
using System.Web.Services; using System.Web.Services.Protocols; [WebService(Namespace="http://example.org/math")] public class MathService { [WebMethod] public double Add(double x, double y) { return x + y; } [WebMethod] [SoapDocumentMethod(Action="urn:math:subtract")] public double Subtract(double x, double y) { return x - y; } ... }
これで、.asmx ハンドルは、Add メソッドの SOAPAction 値が http://example.org/math/Add であり、SubTract メソッドの SOAPAction 値が urn:math:subtract であると見なします。クラス内で明示的に定義しました)。たとえば、次の HTTP リクエスト メッセージは Subtract を呼び出します。
.asmx ハンドルが HTTP リクエスト メッセージに一致する SOAPAction を見つけられない場合、例外がスローされます。メッセージのディスパッチに SOAPAction ヘッダーに依存したくない場合は、リクエスト要素名を使用するように .asmx ハンドルを指示できます。この方法を使用するには、[SoapDocumentService] 属性の RoutingStyle 属性でクラスをマークする必要があります。また、WebMethods には SOAPAction 値が必要ないことにも注意してください (クラス内でその値を空に設定します)。以下に示すように:
using System.Web.Services; using System.Web.Services.Protocols; [WebService(Namespace="http://example.org/math")] [SoapDocumentService( RoutingStyle=SoapServiceRoutingStyle.RequestElement)] public class MathService { [WebMethod] [SoapDocumentMethod(Action="")] public double Add(double x, double y) { return x + y; } [WebMethod] [SoapDocumentMethod(Action="")] public double Subtract(double x, double y) { return x - y; } ... }
この場合、ハンドラーは SOAPAction の値を気にせず、リクエスト要素の名前を使用して呼び出しメソッドを決定します。たとえば、次の HTTP リクエスト メッセージでは、Add メソッドを呼び出すリクエスト要素の名前が Add であることを望んでいます:
したがって、.asmx ハンドルが HTTP メッセージを受信すると、最初に行うことは、どのように処理するかを決定することです。メッセージを対応する WebMethod にディスパッチします。実際にメソッドを呼び出す前に、受信 XML を .NET オブジェクトにマップする必要もあります。
XML からオブジェクトへのマッピング
WebMethod ハンドルは、呼び出すメソッドを決定すると、XML メッセージを .NET オブジェクトに逆シリアル化します。メッセージがディスパッチされると、ハンドラーはリフレクションを介してクラスをチェックし、XML メッセージの処理方法を決定します。 XmlSerializer クラスは、System.Xml.Serialization 名前空間内のクラスへの XML のマッピングを自動的に完了します。
XmlSerializer は、任意の .NET パブリック型を XML スキーマ型にマッピングでき、この適切なマッピングを使用して、.NET オブジェクトを XML インスタンス ドキュメントに自動的にマッピングできます (図 4 を参照)。 XmlSerializer は、XML スキーマによってサポートされる関数によって制限されます。すべての複雑な最新のオブジェクト モデル (非ツリー オブジェクト グラフなど) を処理できるわけではありませんが、開発者が一般的に使用する複雑な型は処理できます。
前の Add の例を見ると、XmlSerializer は x 要素と y 要素を .NET の double 値にマップします (Add メソッドを呼び出すときに指定する必要があります)。 Add メソッドは呼び出し元に double 型の値を返します。これも SOAP 応答メッセージ内の XML 要素にシリアル化する必要があります。
図 4. XML のオブジェクトへのマッピング
XmlSerializer也能自动处理一些复杂类型(除了上面说到的一些限制)。比如,下面的WebMethod计算两个点结构之间的距离。
using System; using System.Web.Services; public class Point { public double x; public double y; } [WebService(Namespace="urn:geometry")] public class Geometry { [WebMethod] public double Distance(Point orig, Point dest) { return Math.Sqrt(Math.Pow(orig.x-dest.x, 2) + Math.Pow(orig.y-dest.y, 2)); } }
请求此操作的SOAP消息将包含一个Distance元素,它包含了两个子元素,一个称作orig,另一个是dest,每一个都包括了x和y元素,如下所示:
这种情况下SOAP应答消息将包含一个DistanceResponse元素,它包含一个double 类型的DistanceResult子元素。
缺省的XML映射使用方法名作为请求元素名,参数名作为子元素名。每个参数的结构依赖于类型的结构。公共字段和属性的名字简单映射为子元素,如Point类中的x和y。应答元素的名字缺省为请求元素的名字后面附加上“Response”,应答元素也包含一个子元素,是请求元素名字后面附加“Result”。也有可能使用一些固定的映射属性来打破标准的XML映射。比如,你可以使用[XmlType]属性来定制类型的名字和名称空间,使用[XmlElement]和[XmlAttribute]属性来控制如何将参数或类成员分别映射为元素或属性,也可以使用[SoapDocumentMethod]属性控制怎样把方法本身映射为请求/响应消息中的元素名。比如,检查下面重新定义的Distance。
using System; using System.Web.Services; using System.Web.Services.Protocols; using System.Xml.Serialization; public class Point { [XmlAttribute] public double x; [XmlAttribute] public double y; } [WebService(Namespace="urn:geometry")] public class Geometry { [WebMethod] [SoapDocumentMethod(RequestElementName="CalcDistance", ResponseElementName="CalculatedDistance")] [return: XmlElement("result")] public double Distance( [XmlElement("o")]Point orig, [XmlElement("d")]Point dest) { return Math.Sqrt(Math.Pow(orig.x-dest.x, 2) + Math.Pow(orig.y-dest.y, 2)); } }
它所期望的SOAP请求消息如下:
.asmx句柄使用SOAP document/literal风格来实现和描述上面显示的默认映射。意思上说WSDL定义将包含literal XML schema定义,它描述了SOAP消息中用到的请求和响应元素。
.asmx句柄也能使用SOAP rpc/encoded风格。这意味着SOAP体中包含一个RPC调用的XML代表(representation),参数用SOAP编码规则来串行化。实现这些仅需将[SoapDocumentService] and [SoapDocumentMethod]替换为[SoapRpcService] and [SoapRpcMethod]属性。
正如你所看到的,我们可能完全定制一个从给定方法到SOAP消息的映射。XmlSerializer提供了一个强大的串行化引擎。
除了处理参数的反串行化,.asmx句柄也能串行化/反串行化SOAP头。SOAP头的处理不同于参数,因为它们被认为是典型的无法控制的信息,和具体的方法没有直接的联系。由于这些,头处理主要是通过中间层(interception layers),完全为WebMethods屏蔽了头处理。
然而如果想涉足于WebMethod中的头信息,你必须提供一个.NET类,从SoapHeader派生而来,它代表了头的XML schema类型。然后定义一个此类型的成员变量作为每一个头实例的占位符。最后标记每个要访问头的WebMethod,指定你想要到达的域名。
比如,下面的SOAP请求包括一个用来进行身份验证的UsernameToken头。
更多Webサービスの動作原理相关文章请关注PHP中文网!