1. Trang chủ
  2. » Công Nghệ Thông Tin

Building XML Web Services for the Microsoft .NET Platform phần 2 pps

38 238 0

Đang tải... (xem toàn văn)

Tài liệu hạn chế xem trước, để xem đầy đủ mời bạn chọn Tải xuống

THÔNG TIN TÀI LIỆU

Thông tin cơ bản

Tiêu đề Building Xml Web Services For The Microsoft .Net Platform Phần 2 Pps
Trường học University of Microsoft
Chuyên ngành Computer Science
Thể loại Bài báo
Năm xuất bản 2025
Thành phố Redmond
Định dạng
Số trang 38
Dung lượng 166,61 KB

Các công cụ chuyển đổi và chỉnh sửa cho tài liệu này

Nội dung

You can specify whether the message recipient must understand an element in the header by specifying the mustUnderstand attribute with a value of 1 in the root of the header element.. T

Trang 1

The SOAP message contains a Digest element in the header that the remote application can

use to ensure that the message has not been tampered with If the client is doing a routine check to see what her stock closed at, she might not be concerned about validating the

message But if the price of the stock triggers an event within the financial software package, she might be more interested in validating the message For example, it would be

unfortunate if the financial software package were to automatically liquidate her portfolio as the result of receiving a bogus message sent by some 14-year-old kid

mustUnderstand Attribute

Because headers are optional, the recipient of the message can choose to ignore them

However, some information that can be embedded in the header should not be ignored by

the intended recipient If the header is not understood or cannot be handled properly, the

application might not function properly Therefore, you need a way to distinguish between

header information that is informative and header information that is critical

You can specify whether the message recipient must understand an element in the header

by specifying the mustUnderstand attribute with a value of 1 in the root of the header

element For example, the SOAP message might request that a remote application perform

an action on the client’s behalf The following example updates a user’s account information within the scope of a transaction:

Trang 2

ID within the header and set the mustUnderstand attribute to 1 The remote application must

either honor the transaction or not process the message

actor Attribute

A SOAP message can be routed through many intermediaries before it reaches its final

destination For example, the previous document might be rout ed through an intermediary responsible for creating a transaction context In this case, you might want to clearly specify

that the TransactionId header is intended to be processed by the transaction intermediary

rather than by the default actor

The SOAP specification provides the actor attribute for annotating SOAP headers intended

for certain intermediaries The value of this attribute is the Uniform Resource Identifier (URI)

of the intermediary for which the portion of the message is intended If a header is intended

to be processed by the next intermediary to receive the SOAP message, the actor attribute

can be set to http://schemas.xmlsoap.org/soap/actor/next Otherwise the actor attribute can

be set to a URI that identifies a specific intermediary Here is an example:

Because the TransactionId header element is intended for the transaction coordinator

intermediary, its actor attribute is set to the intermediary’s URI The mustUnderstand

attribute has also been set so that if the transaction coordinator intermediary does not

understand the TransactionId header element, it must raise an error

If the message is passed to another recipient, any header elements designated for the

intermediary must be removed before the message is forwarded The intermediary can,

however, add additional header elements before forwarding the message to the next

recipient In this example, the transaction coordinator intermediary must remove the router element before forwarding it to the billing application

One important point to note is that routing the message directly to the default actor is not

considered an error Setting the mustUnderstand attribute to 1 in combination with setting

the actor attribute to urn:TransactionCoordinator does not ensure that the message will be

routed through the intermediary It means only that if the message does reach the

transaction coordinator intermediary, it must comprehend the TransactionId header entry or

throw an error

Trang 3

In the preceding example, the intermediary needs to perform a critical task before the

message is routed to the default actor Recall that if the message does reach the transaction

coordinator intermediary, it must remove the TransactionId header before forwarding the

message Therefore, the default actor can check to see whether the TransactionId header

exists, which would indicate that the message was not passed through its appropriate

intermediaries However, determining whether all of the headers were processed after the

message reached the default actor is not always ideal What if the SOAP request needs to

be routed through the intermediaries shown here?

The request to transfer funds must pass through a router intermediary before the funds are transferred Suppose the router charges the customer a processing fee for forwarding the

request to the appropriate banking Web service However, before funds are deducted, the

message should be routed through the transaction coordinator to initiate a transaction before any data is modified Therefore the router intermediary and the default actor should perform all work in the scope of the transaction Because the banking Web service is the default

actor, it can check the headers to see whether the message was routed through the

necessary intermediaries

But what if the banking Web service discovers that the message was never routed through the transaction manager intermediary? If an error occurred during the funds transfer, you

might not be able to undo the work performed by the router intermediary Worse yet, the

SOAP message might have been routed through the router intermediary before being routed through the transaction coordinator If this is the case, there might be no way to tell that the procurement application performed its work outside the scope of the transaction

Unfortunately, SOAP does not provide any mechanism to ensure that the message travels through all intended intermediaries in the proper order In the “Futures” chapter, I will discuss one of the emerging protocols for addressing this problem

The Body Element

A valid SOAP message must have one Body element The body contains the payload of the

message There are no restrictions on how the body can be encoded The message can be

a simple string of characters, an encoded byte array, or XML The only requirement is that the contents cannot have any characters that would invalidate the resulting XML document The SOAP specification describes a method of encoding that can be used to serialize the

data into the message’s body It is a good idea to conform to an established encoding

scheme such as this because it allows the sender to more easily interoperate with the

recipient using a well-known set of serialization rules (I describe this encoding method later

in the chapter.)

SOAP messages can generally be placed into two categories: procedure- oriented

messages and document-oriented messages Procedure-oriented messages provide

two-way communication and are commonly referred to as remote procedure call (RPC)

messages The body of an RPC message contains information about the requested action from the server and any input and output parameters Document-oriented messages

generally facilitate one-way communication Business documents such as purchase orders are examples of document-oriented messages Let’s take a closer look at each of these

document types

Trang 4

Two SOAP messages are paired together to facilitate an RPC method call with SOAP: the request message and the corresponding response message Information about the targeted method along with any input parameters is passed to the server via a request message The server then invokes some behavior on behalf of the client and returns the results and any

return parameters Most of the examples in this chapter relate to RPC method invocations, and they all follow the SOAP specification’s guidelines for encoding RPC messages

A business document such as a purchase order or an invoice can be encoded within the

body of a SOAP message and routed to its intended recipient The recipient of the document might or might not send an acknowledgment message back to the sender (The “SOAP

Encoding” section later in this chapter describes how to use serialization rules to encode the data contained within these business documents.) Because business documents often span across multiple companies, organizations such as BizTalk.org and RosettaNet serve as

facilitators and repositories for schemas that define common document exchanges

Later in the book, I will describe how to leverage the NET platform to create and consume both RPC and document -oriented messages

Fault Element

Everything does not always go as planned Sometimes the server will encounter an error

while processing the client’s message SOAP provides a standard way of communicating

error messages back to the client

Regardless of which encoding style was used to create the message, the SOAP

specification mandates the format for error reporting The body of the message must contain

a Fault element with the following structure:

Table 3-1: Base SOAP Fault Codes

Trang 5

Fault Code Description

VersionMismatch An invalid namespace for the SOAP envelope element was

specified

MustUnderstand An immediate child element within the SOAP header containing a

mustUnderstand attribute set to 1 was either not understood or not

obeyed by the server

Client The content of the message was found to be the root cause of the

error Possible root causes of errors resulting in a Client fault code

include a malformed message or incomplete information in the message

Server The root cause of the error was not directly attributable to the

content of the message Examples of errors resulting in a Server

fault code include the server not being able to obtain the appropriate resources (such as a database connection) to process the message

or a logical error during the processing of the message

You can append more specific fault codes to the core SOAP fault codes listed in the table by using the “dot” notation and ordering the individual fault codes from least specific to most

specific For example, if the server is unable to open a database connection that is required

to process the client’s message, the following fault code might be generated:

<faultcode>Server.Database.Connection</faultcode>

Because the error was not the direct result of the client’s message, the base fault code is

Server A more descriptive fault code is appended to the end of the base fault code In my

example, I define a category of codes for the database and a fault code specific to

connection-related errors

The faultstring element should contain a human-readable string that describes the error

encountered Here is a faultstring value for the error connecting to the database:

<faultstring>Unable to open connection to the

database.</faultstring>

You can use the optional faultactor element to indicate the exact source of the error The

only exception is if an intermediary generated the error If the error was generated at any

point other than the final recipient of the SOAP message, the faultactor element must

contain a URI that identifies the source of the error Otherwise, the URI can be omitted

Using SOAP RPC Messages

One of the original design goals of SOAP was to provide an open and standard way to

facilitate RPCs using Internet technologies such as XML and HTTP In this section, I explain the method of encoding RPC-style messages described in version 1.1 of the SOAP

specification

As I stated earlier in the chapter, the SOAP specification does not dictate the way messages should be encoded, and encoding RPC-style messages is no exception Section 7 of the

SOAP 1.1 specification describes the recommended way to encode the request and

response messages The developer is free to create her own method of encoding RPC

communication In this section, however, I limit the discussion to the “standard” method of encoding RPC-style SOAP messages

Trang 6

To facilitate the request/response behavior needed by RPC, you need two SOAP messages: one for the request and one for the response Here is how the request message would be

encoded for a simple C# function that adds two numbers:

public int Add(int x, int y)

{

return x + y;

}

The Add method accepts two integers as input parameters and passes the result back to the

client as a return parameter The input parameters must be packaged within the body of the request message so that they can be sent to the target application This is accomplished by packaging the parameters in a struct-like format Here is the resulting request message for

The Body element contains an Add element Each of the input parameters is represented as

a subelement within the Add element The order of the x and y elements must match the

order in which the parameters are specified in the method signature In other words, placing

y before x would be invalid Furthermore, the names and the types of the Add, x, and y

elements must be the same as the target method and its parameters I will explain data

typing in the next chapter For now, suffice it to say that the body of the request message must be in a format expected by the remote application

Now that I have created a properly formatted request message, take a look at the response generated by the remote application:

The response message returned by the remote application contains the result of the Add

method The return parameter is once again encoded in a struct-like format within the body

of the SOAP message The naming convention of the subelement within the body is the

name of the method with Result appended to it However, this naming convention is not

Trang 7

dictated by the specification The first (and in this case, only) parameter contains the return

parameter of the method call As with the AddResult element, the name of the element that

contains the return parameter is not dictated by the specification

What if more than one parameter is returned to the client? Let’s take a look at a slight

variation of the Add method Add2 returns the sum of the two numbers via an output

Notice that the third parameter, sum , does not get encoded Because sum is declared as an

output parameter, there is no reason to send its initial value to the remote application Here

The response message contains the value of two parameters As I mentioned earlier, the

return parameter must always be listed first I called the element containing the return

parameter Add2Result to demonstrate that the name is not relevant The value of the sum

parameter is listed next

SOAP Encoding

Trang 8

SOAP Encoding defines the way data can be serialized within a SOAP message SOAP

Encoding builds on the types defined in the XML specification, which defines a standard way

of encoding data within an XML document SOAP Encoding clarifies how data should be

encoded and covers items not explicitly covered in the XML specification, such as arrays

and how to properly encode references

Simple Types

Simple types include strings, integers, date/time, Booleans, and so on The SOAP

specification defers to the “Built-in datatypes” section of the “XML Schema Part 2:

Datatypes” specification I will talk about the XML built-in data types in the next chapter

An instance of a data type is encoded as an XML element For example, an integer called

Age would be encoded as follows:

Structures

A structure is a collection of types that serve as a template for logically grouping data For example, let’s say you need to create a function that calculates the volume of a rectangular solid Instead of passing the length, the width, and the height of the cube as separate

parameters, you can logically group the dimensional data into a RectSolid structure Then the method that calculates the volume of the solid can accept an instance of the RectSolid

structure Here is an example:

public struct Rect Solid

{

public int length;

public int width;

public int height;

First I define a structure that contains the dimensions of a solid Then I define the area A

request to calculate the volume of a rectangular solid that has a length of 2, a width of 3, and

a height of 1 can be encoded as follows:

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

Trang 9

As you can see, structures map nicely to XML Each of the variables contained within the

instance of the RectSolid structure is serialized as a child element of r As you will see in the

next chapter, this follows the method of encoding structures defined in Part 1 of the XML

specification

Arrays

Another common compound data type is the array As of this writing, the XML specification does not specify how an array should be encoded The SOAP 1.1 specification fills in the

gaps Here is an example:

public int AddArray(int[] numbers)

Trang 10

The array is represented by a single element within the body tag The element must contain

the soap-enc:arrayType attribute The value of the attribute describes the contents of the

array and its dimensions In the preceding example, xsi:int[3] specifies that the array

contains three integers In the next chapter, I will describe XML Schema and type definitions

in more detail

Each value in the array is listed as a subelement The names of the subelements are not

relevant, but often the names of the elements within the array will correlate with the type of data they contain

SOAP-encoded arrays can contain different elements of different types The following code returns an array containing an integer, a float, and a string:

object[] stuff = new object[3];

An array of objects called stuff is created, and then values of three different types are

assigned to each of its three elements The resulting response SOAP message is encoded

as follows:

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

Trang 11

The things array is defined as type xsi:ur-type, which means that the elements can contain

data of any type In the next chapter, you will learn how to declare the type of data in each element

The final two array types I will cover are multidimensional and jagged arrays

Multidimensional arrays are rectangular by nature You can think of a jagged array as an

array contained within an array SOAP defines a method for encoding both types of arrays This example creates a multidimensional array:

// Create a block of seats 3 rows deep and 4 seats wide

string[,] seats = new string[3, 4];

A multidimensional array of labels is created, and then the array is passed to

PrintSeatLabels The resulting message is encoded as follows:

Trang 12

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

<string>row 1, seat 1</string>

<string>row 1, seat 2</string>

<string>row 1, seat 3</string>

<string>row 1, seat 4</string>

<string>row 2, seat 1</string>

<string>row 2, seat 2</string>

<string>row 2, seat 3</string>

<string>row 2, seat 4</string>

<string>row 3, seat 1</string>

<string>row 3, seat 2</string>

<string>row 3, seat 3</string>

<string>row 3, seat 4</string>

In a jagged array, which you can think of as an array of arrays, each element can contain an array of varying lengths Here is an example:

string[][] teams = new string[3][];

teams[0] = new string[3];

Trang 13

teams[2] = new String[4];

The RegisterTeams function accepts a list of teams Because teams can vary in the number

of players, a two-dimensional jagged array of strings is passed to the function Each element

of the array represents a team and contains an array of player names on that team Here is how the jagged array is encoded:

Trang 14

</RegisterTeams>

</soap:Body>

</soap:Envelope>

Consistent with the array encoding rules I discussed earlier, the name of the individual

elements is not important For clarity, I named each element in the teams array team and named each element in the team array player In jagged arrays, not only does the teams

element contain a soap-enc:arrayType attribute, but each of the elements within the array of teams contains a soap- enc:arrayType attribute as well

Let’s say you create an array that can hold the names of up to 1000 registrants for an

upcoming event Periodically, the list of attendees needs to be sent to various interested

parties Soon after the event has been announced, there might be only 5 people registered

If you send the list of registrants, it is not very efficient to encode all 1000 elements because only the first 5 will contain values:

// Create an array of attendees, record the first five,

// and then pass the array to RegisteredAttendees

string[] attendees[1000];

attendees[0] = "Bill Clinton";

attendees[1] = "Jimmy Carter";

attendees[2] = "Ronald Reagan";

attendees[3] = "George Bush";

attendees[4] = "Al Gore";

Trang 15

As you can see in the resulting message, the soap-enc:arrayType attribute indicates that the

array contains 1000 elements even though only the first 5 were encoded If you want to

encode a portion of the array that does not start with the first element, you can specify the

starting element by using the soap- enc:offset attribute For example, if you want to encode

the next five attendees that registered for the event, the resulting message would be as

As you can see, the soap-enc:offset element specifies that the array has been offset by five

Therefore, the contents of the array contain the sixth through the tenth elements

Trang 16

What if the elements to be encoded within the array are not adjacent to each other? Another means of partially encoding arrays is to use the sparse array syntax For example, say you want to create a message that contains the names of all the registered attendees that did not show up for the event The ordinal of each attendee has significance, so you are once again creating 1000 elements in an array and populating only a subset of the elements with data This time, the data will not be located in a sequential set of elements Instead, it will be

contained in elements throughout the array You can solve this problem by encoding an

array of no-shows by using the sparse array syntax Here is the resulting message:

<string soap-enc:position="[10]">Dan Quayle</string>

<string soap-enc:position="[231]">Newt Gingrich</string> <string soap-enc:position="[357]">Trent Lott</string>

<string soap-enc:position="[842]">Hillary Rodham Clinton </string>

</registrants>

</NoShows>

</soap:Body>

</soap:Envelope>

Once again, the soap-enc:arrayType attribute is used to specify that the array contains a

total of 1000 elements However, the elements that contain data are the only ones encoded within the SOAP message Because the position of the element within the array is relevant,

the soap-enc:position attribute is used to indicate where the element resides within the array

Passing Parameters by Reference

Up to this point, I have been explaining how to encode parameters that are passed by value

to a Web service But it is often necessary to pass parameters by reference For example, a client might pass information about a customer to the server so that the server can update the information on behalf of the client If the client structure were passed by value, changes made to the client’s information would not be visible to the client

Let’s take a look at how parameters that are passed by reference are encoded in a SOAP message In the first example, I create a series of Fibonacci numbers A number in a

Fibonacci series is determined by adding the two numbers directly preceding it For

example, if n1 = 1 and n2 = 1, then n3 = 1 + 1 = 2 and n4 = 1 + 2 = 3 Here is the method I

use to output a series of Fibonacci numbers:

public void FibonacciIncrement(ref int n1, ref int n2)

{

Trang 17

FibonacciIncrement accepts the last two numbers and then returns the next two numbers in

the series Here are the request and response messages for the first call to

Trang 18

</FibonacciIncrementResponse>

</soap:Body>

</soap:Envelope>

There is nothing surprising about the first message The two parameters are encoded as

usual What distinguishes a parameter passed by reference from one that is passed by value

is that the client needs to be notified of any changes to the value Therefore, the new values

of n1 and n2 are encoded in the response message Notice that I also follow the convention

of appending Response to the method element within the body

Another reason for passing parameters by reference is to maintain the identity of the variable being passed Consider the following example:

// Server Code:

public struct Person

{

public double Height;

public int Weight;

public int Age;

public string Hobby;

Trang 19

FibonacciIncrement, the Introduce method behaves differently depending on whether the

two parameters are equal or identical (point to the same instance of Person)

The way I encode the parameters passed by reference in the Fibonacci example is not

sufficient for the Introduce method because it does not maintain the identity of the

parameters SOAP provides the id/href pattern for maintaining the identity of the parameters Here is how the call to Introduce would be encoded:

The encoded parameters do not contain any data Instead, because both parameters

reference the same instance of the Person type, the data is encoded once within the body of

Ngày đăng: 14/08/2014, 10:22

TỪ KHÓA LIÊN QUAN