Sending and Receiving Messages

In the last section you learned how to create a new service that simply had the state consisting of a string with the value "Hello World." To accomplish this, the phrase was posted to a DSS port. Messages, which represent a DSS operation on a port, allow other services to read and update the state of a service. In the last example, the phrase "Hello World" represented the state of the service. This phrase was sent to a port, and the result was a SOAP message that appeared in an Internet browser.

Port

A DSS port provides a way for services to communicate by passing messages back and forth. A service can specify one or more ports, and each port contains a data structure that holds the messages sent to the port. By default, each service has access to one main port. It is possible to define an internal port that can be used for updating a privately held state.

Anatomy of a Message

The basic function of every service is to send and receive messages. This is what enables services to communicate with each other. Messages are strongly typed, and message types are specified within a service. DSS requires that a message must contain the following three elements:

  • Action. Typically, this is a verb that informs the runtime what operation should be performed. For example, the verb Get indicates that the service should get the latest version of the state, and Update indicates that the service should update the latest version of the state.

  • Body. This is the body of the request. It does not represent the text to be sent (i.e. "Hello World" because that is the state). The body represents the XML found in the Microsoft.ServiceModel.Dssp.GetRequestType instance. For example, the following XML is the body for a GetRequest:

    [DataContract]
    [XmlType(Namespace = "http://schemas.microsoft.com/xw/2004/10/dssp.html")]
    [XmlRoot("GetRequest", Namespace =
       "http://schemas.microsoft.com/xw/2004/10/dssp.html", IsNullable = false)]
  • Response Port. This is the port to which the response should be sent. If specified, a response should be sent regardless of whether the action results in a success or failure.

The "Hello World" phrase is returned by something known as a DSS transform file. The transform file, along with the service proxy, is generated when the service assembly is compiled. The state items for a service will pass through calls to the transform before being returned to the service.

Transform

A transform is an assembly that is created when the DSS proxy is generated. The proxy exposes the service contract, and the transform provides a mapping between the service and the proxy. It acts as a bridge between the service and proxy assemblies.

The proxy and transform files are generated automatically when you use the Visual Studio template. To see where this is called, on the Project menu, choose project_name Properties. Click the Build Events tab and you see the command line for the DssProxy utility in the post-build event command line. By default, the assemblies generated are stored in the bin subdirectory for the MSRS installation.

Tip

Tip

If your service is running on the DssHost, you will not be able to compile your service until the DssHost process has been stopped. You can do this by simply closing the command window that is launched when you run the DSS node.

When compiling a service, MSRS will generate three assemblies: one for the service, one for the proxy, and one for the transform. They will be named using the following naming convention: <service name>.Y<year>.M<month>.<Proxy, Transform, or blank>.dll. For example, the following three files will be generated based on the date the service named DssService1 is compiled:

  • C:Microsoft Robotics Studio (1.5)inDssService1.Y2007.M07.dll

  • C:Microsoft Robotics Studio (1.5)inDssService1.Y2007.M07.Proxy.dll

  • C:Microsoft Robotics Studio (1.5)inDssService1.Y2007.M07.Transform.dll

Using a PortSet

To understand how MSRS handles sending and receiving messages through DSS ports, let’s take a closer look at the code that is generated when you create a new service using the Visual Studio template. In the DssService1.cs file, there is a declaration for the main port (as shown below):

[ServicePort("/dssservice1", AllowMultipleInstances=false)]
private DssService1Operations _mainPort = new DssService1Operations();

This code indicates that the main port does not allow multiple instances and that the service will be located in a subdirectory named dssservice1. Given this information, you can determine the URL of the service, http://localhost:50000/dssservice1. If the port allowed for multiple instances, each instance would be appended with a globally unique identifier (GUID).

The code also indicates that the port can perform Decentralized Software Services Protocol (DSSP) operations defined in the DssService1Operations class. You might recall from Chapter 1 that DSSP is the SOAP-based protocol used by DSS to handle messages. The DssService1Operations class is located in the DssService1Types.cs file and looks like the following:

[ServicePort()]
public class DssService1Operations : PortSet<DsspDefaultLookup,DsspDefaultDrop, Get>
{
}

The DssService1Operations class defines a PortSet, and this PortSet is used to indicate what types of DSSP or HTTP messages are allowed. All services are required to include the DsspDefaultLoopkup operation, which defines a default message handler for a Lookup message. The Lookup message is used to return the service context, which contains information about how to communicate with the service. DsspDefaultDrop is not required, but it allows the service to support the Drop message. Finally, the Get message allows the service to respond with its current state.

Get is just one of several DSSP operations allowed (refer to Table 2-3 for a list of additional DSSP operations). It will return state in the format of a SOAP message as required by DSSP. To return the state as raw XML, you would need to add an HTTP operation such as HttpGet to the PortSet list. An example of this is provided in Service Tutorial 1 and is available at http://msdn2.microsoft.com/library/bb905437.

Table 2-3. DSSP Operations Provided with MSRS

Operation

Default Implementation

Description

Create

DsspDefaultCreate

Creates a new service. You do not have to call this directly because it is handled by the DsspServiceCreationPort, which is specified in the default service constructor.

Delete

DsspDefaultDelete

Deletes the part of the state identified in the Delete operation. This only deletes state and not the service itself.

Drop

DsspDefaultDrop

Shuts down the service. This must be the final message sent to the service.

Get

DsspDefaultGet

Used to get the entire state for a service. If the state consists of multiple elements, then they will all be returned. To access specific elements, you need to use the Query operation.

Insert

DsspDefaultInsert

State that is included with the request is added to the state belonging to the service.

Lookup

DsspDefaultLookup

Returns the service context for a service. This operation is required for all messages.

Query

No default provided

Retrieves state based on a specific parameter-based request. Only a specific portion of the services state is returned. DSSP does not require a structured query language to be used. The service performing the query must know what the service containing the state expects in terms of schema and query language.

Replace

DsspDefaultReplace

Replaces all elements in the service state.

Submit

No default provided

Similar to an execute statement, submit will perform computations that do not alter the state of a service.

Subscribe

No default provided

Allows a service to receive event notifications regarding state changes with another service.

Update

DsspDefaultUpdate

Used to specify a portion of the state to update. The update request will perform a delete and insert wrapped in a transaction to ensure both operations succeed.

Upsert

No default provided

Combination of an Insert and an Update. If the state already exists, then the state is updated. Otherwise, the state is inserted.

Table 2-3 lists the DSSP operations that can be added to a PortSet. The DSS Service Model provides built-in classes that define and implement default code for some of these operations. You can get started by using these defaults instead of adding the code to your service. Ultimately, you will only want to use the defaults when the state for a service is not known or when the implementation is generic. In most cases, you will only use the defaults for the Lookup and Drop operations.

Keep in mind that you can add your own custom messages, which derive from the DsspOperation class. Most services you write will include at least one custom operation implementation. An example of this is seen with the IncrementTick message defined in Service Tutorial 2 (which is available at http://msdn2.microsoft.com/library/bb905437). In addition to the DSSP operations, you can also use HTTP-based operations (as shown in Table 2-4).

More Info

More information about interacting with services using SOAP and HTTP is available through the following URL: http://msdn2.microsoft.com/library/bb727264. This includes how to access services using a Web browser.

Table 2-4. HTTP Operations Provided with MSRS

Operation

Changes State? (Yes/No)

Description

HttpDelete

Yes

Used to delete the state element requested.

HttpGet

No

Returns state using a URL. This works the same as when you retrieve documents by browsing the Web.

HttpOptions

No

Represents a request for information about the communication options available.

HttpPost

Yes

A post passes parameters inside the actual HTTP request message. This is typically used when dealing with HTML form data.

HttpPut

Yes

A request that the state of the service is replaced with the data included in the request.

HttpQuery

No

Similar to an HttpGet, but with query parameters passed in with the URI.

Using Service Handlers

A service handler is responsible for handling incoming messages on a port. A service can have more than one service handler, and each one will pertain to a different DSSP, HTTP, or custom operation. The only exceptions to this are the DsspDefaultLookup and DsspDefaultDrop operations because these are typically handled by the DSS runtime but can be overwritten by the service if needed.

The Visual Studio template, which is used to create a new DSS service, provides only one service handler. The service handler (shown as follows) is used to handle DSSP Get messages:

[ServiceHandler(ServiceHandlerBehavior.Concurrent)]
public virtual IEnumerator<ITask> GetHandler(Get get)
{
    get.ResponsePort.Post(_state);
    yield break;
}

The GetHandler does not do much. It simply posts the state as a SOAP message to the response port. The code in this handler could contain additional code that performs computations or sends messages to other services.

Each service handler allows you to define how it will be processed. For example, GetHandler is set to run concurrently. This behavior should be set for handlers that do not modify state. For handlers that modify state, the Exclusive service handler behavior attribute should be used. Other attributes include Teardown, which is executed once and shuts down the service, and DsspOperationDefault, which picks the behavior based on the operation type.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.12.120.202