WCF 4 Step By Step Chapter 10-12 Note (Reliable Sessions,ProgrammaticallyControlling, One-Way ...)

Chapter 10 Implementing Reliable Sessions

Strictly speaking, reliable messaging and reliable sessionsare different but related concepts. Reliable messaging is concerned with ensuring that messages are delivered exactly once, and a reliable session provides a context for sending and receiving a series of reliable messages. However, in WCF, reliable sessions have a dependency on reliable messaging; you use reliable messaging to provide an end-to-end reliable session between a client application and a service.

Using Reliable Messaging

To handle the problems of lost messages, or messagesarriving in the wrong order, the OASIS organization has proposed the WS-ReliableMessagingspecification. This specification defines an interoperable protocol for transmitting messages in areliable manner between a single source and a single destination.

 It is important to understand that reliable messaging asspecified by the WS-ReliableMessaging specification does not imply any form of message persistenceor message queuing. The protocol requires that both the source application sending themessage and the destination application receiving the message are running at the sametime.

 

The WS-ReliableMessaging protocol organizes messages in a conversation between a client application and a service by associating them with a unique identifier known as a sequence number. The first message in the protocol is this CreateSequence message,

sent by the WCF runtime on the client computer. This message initiates the reliable session.

<s:Body>
<CreateSequencexmlns="http://schemas.xmlsoap.org/ws/2005/02/rm">
<AcksTo>
<a:Address>http://www.w3.org/2005/08/addressing/anonymous</a:Address>
</AcksTo>
<Offer>
<Identifier>urn:uuid:e170f8ff-4715-4ace-bc81-76a2a6e63245</Identifier>
</Offer>
</CreateSequence>
</s:Body>

This is the CreateSequenceResponse message, sent back to the client by the WCF run time on the service computer.

<s:Body>
<CreateSequenceResponsexmlns="http://schemas.xmlsoap.org/ws/2005/02/rm">
<Identifier>urn:uuid:efae0f85-cd33-438e-a8f1-bc6e0818de1e</Identifier>
<Accept>
<AcksTo>
<a:Address>net.tcp://localhost:8080/ShoppingCartService</a:Address>
</AcksTo>
</Accept>
</CreateSequenceResponse>
</s:Body>

This is the first AddItemToCart message sent by the clientapplication. The key thing to notice in this message is the  <Sequence> block,in thiscase message “1”—which

enables the WCF runtime on the server computer to ensurethat messages are passed

to the service in the correct order.

<s:Header>
<r:AckRequested>
<r:Identifier>urn:uuid:efae0f85-cd33-438e-a8f1-bc6e0818de1e</r:Identifier>
</r:AckRequested>
<r:Sequence s:mustUnderstand=“1”>
<r:Identifier>urn:uuid:efae0f85-cd33-438e-a8f1-bc6e0818de1e</r:Identifier>
<r:MessageNumber>1</r:MessageNumber>
</r:Sequence>
...
</s:Header>


This is the  acknowledgment message sent from the WCF runtime on the server computer back to the WCF runtime on the client computer. The data in the <Sequence
Acknowledgement> block indicates that the service has verified that it has received the AddItemToCartMessage; it has acknowledged receipt of a message with the same
identifier and sequence number included in the AddItemToCart message.

<s:Envelope ...>
<s:Header>
<r:SequenceAcknowledgement>
<r:Identifier>urn:uuid:efae0f85-cd33-438e-a8f1-bc6e0818de1e</r:Identifier>
<r:AcknowledgementRange Lower="1" Upper="1"></r:AcknowledgementRange>
<netrm:BufferRemaining xmlns:netrm=
"http://schemas.microsoft.com/ws/2006/05/rm">8</netrm:BufferRemaining>
</r:SequenceAcknowledgement>
<a:Action s:mustUnderstand="1">http://schemas.xmlsoap.org/ws/2005/02/rm/
SequenceAcknowledgement</a:Action>
<a:To s:mustUnderstand="1">http://www.w3.org/2005/08/addressing/anonymous</a:To>
</s:Header>
<s:Body></s:Body>
</s:Envelope>


This is a  LastMessage message. It i s sent by the WCF runtimeon the client computer to indicate that this is the final message in the sequence.This message is sent when the client application starts to close the session.

<r:Sequence s:mustUnderstand="1">
<r:Identifier>urn:uuid:efae0f85-cd33-438e-a8f1-bc6e0818de1e</r:Identifier>
<r:MessageNumber>6</r:MessageNumber>
<r:LastMessage></r:LastMessage>
</r:Sequence>

This is a  TerminateSequence message. The  WCF runtime on theserver computer sends this message to indicate that it is not going to send anymore messages using the sequence specified by the identifier and that the WCFruntime on the client computer can release any resources associated with this session.

<s:Body>
<TerminateSequencexmlns=“http://schemas.xmlsoap.org/ws/2005/02/rm”>
<Identifier>urn:uuid:e170f8ff-4715-4ace-bc81-76a2a6e63245</Identifier>
</TerminateSequence>
</s:Body>

These exercises should make two things apparent to you:

  1. It is easy to implement reliable messaging with WCF. Youneed only set a few binding configuration properties. You don’t need to write anyadditional code; it is all transparent to your client applications and services.

  2. Reliable sessions can generate a significant amount of additional network traffic, both in terms of the extra protocol messages and the increased sizeof each message. The more messages a client application sends in a session, thesmaller this overhead becomes, proportionally You should also be aware that not all binding configurationssupport the WS-ReliableMessaging protocol. The ones that do are netTcpBinding,wsDualHttpBinding (this binding always usesreliable messaging; you cannot disable it),wsFederationHttpBinding, and wsHttpBinding.

Detecting and Handling Replay Attacks

In a replay attack, a hacker intercepts and stores messagesflowing over the network and then sends them at some time in the future Using reliable sessions can help to mitigate simple replayattacks, because each message must provide a valid sequence identifier and a unique messagenumber. When the session has completed, the sequence identifier becomes invalid, so any subsequentattempt to replay the message should be rejected by the receiver。

You can configure transport-level security to encryptmessages as they traverse the network from machine to machine But remember that transport- level security operates on a point-to-point basis, and whena service receives the message, it has unrestricted access to its contents. The usual way to protect data, if you cannot trust any intermediate services,is to implement message-level security. However, message-level security is predominantly concernedwith protecting the body of a message rather than the data in message headers, which iswhere the sequence identifiers and message numbers are held.

So, to prevent a reply attack, the receiver requires a moresecure mechanism than simple sequence identifiers and message numbers that uniquelyidentify messages. Fortunately, WCF provides just such a mechanism in the replay detectionprotocol. 

Chapter 11 Programmatically Controlling the Configuration and Communications

The WCF Service Services and Channels You can think of a binding as a description of the channelsin a channel stack When a host application starts a service running,the WCF runtime uses the bindings defined for each endpoint to instantiate a ChannelListener object and a channelstack.A ChannelListener object connects an endpoint to the transport channel for the channel stack. When an incoming request message reaches the top of the channel stack, a Channel Dispatcher object takes the message, examines it, and passesit to an EndpointDispatcher object that invokes the appropriate method in the service,passing the data items in the message as parameters to the method. 

The WCF runtime on the client builds a structure similar tothat used by the service, but somewhat simpler, because the client does not have to listen for requests ormanage multiple instances of the application the way aservice does. The WCF client runtime creates a ChannelFactory object and uses this object toconstruct a channel from the binding definition.


Behaviors

You can customize the way that components in the WCFinfrastructure operate by applying behaviors

Behaviors have scope; you can apply them to an entireservice, a specific operation, a contract, or an endpoint. An example of a behavior element thatapplies to an entire service is serviceDebug.

Bear in mind that in a configuration file, behaviors can benamed or anonymousAnonymous behaviors are applied automatically to a service orendpoint, whereas named behaviors are applied only if they are referenced explicitly by a serviceor endpoint configuration.

Composing Channels into Bindings

You can also create your own custom bindings by combining binding elements and setting the properties of each of these binding elements to determine exactly which channels the WCF runtimeuses.

The order of the binding elements in a custom binding isimportant. It has been mentioned before that the transport channel must be at the bottom ofthe stack, followed by the encoding channel. Microsoft recommends that you layer channelsaccording to the function they perform. 


 

static void Main(string[] args)
        {
           CustomBinding customBinding = new CustomBinding();
           TransactionFlowBindingElement txFlowBindElement =
new TransactionFlowBindingElement();
           txFlowBindElement.TransactionProtocol =TransactionProtocol.OleTransactions;
           customBinding.Elements.Add(txFlowBindElement);
            ReliableSessionBindingElement rsBindElement= new ReliableSessionBindingElement();
           rsBindElement.FlowControlEnabled = true;
           rsBindElement.Ordered = true;
           customBinding.Elements.Add(rsBindElement);
            SecurityBindingElementsecBindElement =
SecurityBindingElement.CreateSecureConversationBindingElement(
SecurityBindingElement.CreateSspiNegotiationBindingElement());
           secBindElement.LocalServiceSettings.DetectReplays = true;
           customBinding.Elements.Add(secBindElement);
           customBinding.Elements.Add(new TextMessageEncodingBindingElement());
           TcpTransportBindingElement tcpBindElement = newTcpTransportBindingElement();
           tcpBindElement.TransferMode = TransferMode.Buffered;
           customBinding.Elements.Add(tcpBindElement);
           ServiceHost host = new ServiceHost(
typeof(ShoppingCartService.ShoppingCartServiceImpl));
           host.AddServiceEndpoint(typeof(ShoppingCartService.IShoppingCartService),
customBinding,"net.tcp://localhost:8090/ShoppingCartService");
 
           host.Open();
           Console.WriteLine("Service running");
           Console.WriteLine("Press ENTER to stop the service");
           Console.ReadLine();
 
        }

                     

Inspecting Messages

An interesting feature of the WCF service model is theability to intercept messages. Using message interception, you can examine messages as they are sent andreceived. You can also modify an incoming message prior to it being processed by a service orbefore an outgoing message is transmitted to a client.

You can intercept messages by creating a message inspector;you create a class that implements the IDispatchMessageInspector interface and insert it intothe WCF infrastructure by defining a behavior.

 

    public classShoppingCartInspector : IDispatchMessageInspector
    {
        public objectAfterReceiveRequest(ref System.ServiceModel.Channels.Message request,System.ServiceModel.IClientChannel channel, System.ServiceModel.InstanceContextinstanceContext)
        {
           Console.WriteLine("Message received: {0}\n{1}\n\n",
request.Headers.Action, request.ToString());
            returnnull;
        }
 
        public voidBeforeSendReply(ref System.ServiceModel.Channels.Message reply, objectcorrelationState)
        {
           Console.WriteLine("Reply sent: {0}\n{1}\n\n",
reply.Headers.Action, reply.ToString());
        }
    }

Creating a Custom Behavior

public class ShoppingCartBehavior : IServiceBehavior
    {
        public voidAddBindingParameters(ServiceDescription serviceDescription,System.ServiceModel.ServiceHostBase serviceHostBase,System.Collections.ObjectModel.Collection<ServiceEndpoint> endpoints,System.ServiceModel.Channels.BindingParameterCollection bindingParameters)
        {
            //thrownew NotImplementedException();
        }

        public voidApplyDispatchBehavior(ServiceDescription serviceDescription,System.ServiceModel.ServiceHostBase serviceHostBase)
        {
            foreach(ChannelDispatcher chanDispatcher in serviceHostBase.ChannelDispatchers)
            {
               foreach (EndpointDispatcher epDispatcher in chanDispatcher.Endpoints)
                {
                   epDispatcher.DispatchRuntime.MessageInspectors.Add
                   (new ShoppingCartInspector());
                }
            }
        }
 
        public voidValidate(ServiceDescription serviceDescription,System.ServiceModel.ServiceHostBase serviceHostBase)
        {
            //thrownew NotImplementedException();
        }
    }
 

Defining a Behavior Extension Element

To support configuring a behavior in a configuration file,you must provide a behavior extension element. A behavior extension element is a class that theWCF runtime uses to configure a behavior when it starts a service running and reads theconfiguration file.

 

 <system.serviceModel>
    <behaviors>
     <serviceBehaviors>
        <behaviorname="">
         <messageInspector />
       </behavior>
     </serviceBehaviors>
    </behaviors>
    <extensions>
     <behaviorExtensions>
        <addname="messageInspector"type="ShoppingCartService.ShoppingCartBehaviorExtensionElement,ShoppingCartService, Version=1.0.0.0, Culture=neutral,PublicKeyToken=null" />
     </behaviorExtensions>
   </extensions>
             </system.serviceModel>

Controlling Client Communications

You have now seen how to configure the channel stack for aservice and how to create a behavior that can modify the way in which the WCF runtimeprocesses messages.

Connecting to a Service Programmatically

When a client application runs and connects to a service,the WCF runtime creates an infrastructure that is a simplified mirror of that created for the service.When you use a proxy object to connect to a service, behind the scenes the WCFruntime creates a binding object using the binding elements specified in the configurationfile and an endpoint based on the selected endpoint definition. It then uses these items toconstruct a ChannelFactory object. The WCF runtime uses the ChannelFactory object toinstantiate the channel stack and connect it to the URI specified by the endpointWhen the clientapplication invokes operations through the proxy object, the WCF runtime routes theserequests through the channel stack and transmits them to the service. When a response messagearrives from the service, it passes back up through the channel stack to the WCF runtime,and the proxy object then passes it back to the client application code.

You can create a client proxy class for a service by usingthe svcutil utility or Add Service Reference Wizard to query the metadata for the service andgenerate an assembly that you can add to the client project For security reasons, the administrator managing the hostcomputer running a WCF service can elect to disable service metadatapublishing. However, the WCF service developer can distribute an assembly containing theservice contract, and you can use this to create the channel stack dynamically

 
try
            {
               WS2007HttpBinding httpBinding = newWS2007HttpBinding(SecurityMode.Message);
               WSHttpSecurity httpSec = httpBinding.Security;
               httpSec.Message.AlgorithmSuite = SecurityAlgorithmSuite.Basic128;
               httpSec.Message.ClientCredentialType = MessageCredentialType.Windows;
               EndpointAddress address = newEndpointAddress("http://localhost:8010/ProductsService/Service.svc");
               Products.IProductsServiceV2 channel =
ChannelFactory<Products.IProductsServiceV2>.CreateChannel(
httpBinding, address);
               Console.WriteLine("Test 1: List all bicycle frames");
               List<string> productNumbers = channel.ListMatchingProducts("Frame");
               foreach (string productNumber in productNumbers)
                {
                   Console.WriteLine("Number: {0}", productNumber);
                }
               Console.WriteLine();
               channel = null;

                                             

Sending Messages Programmatically

When you use Java or other non-WCF technology in clien side, if the administrator of the computer hosting the service disables service metadata publishing, the service developeris unlikely to be able to provide you with C# code or a .NET Framework assembly containing theservice contract. However, if you have documentation describing the SOAP messages that theservice can accept and the responses the service emits, you can still access theservice from a WCF client application; you can send messages directly through the channel

 

 try
            {
                //Create a default HTTP binding
               BasicHttpBinding httpBinding = new BasicHttpBinding();
 
                // Createan endpoint
               EndpointAddress address = new EndpointAddress(
                   "http://localhost:8010/SimpleProductsService/Service.svc");
               IChannelFactory<IRequestChannel> factory =
httpBinding.BuildChannelFactory<IRequestChannel>();
               factory.Open();
               IRequestChannel channel = factory.CreateChannel(address);
               channel.Open();
               Message request = Message.CreateMessage(MessageVersion.Soap11,
"http://adventure-works.com/2010/06/29/SimpleProductsService/ListProducts");
               Message reply = channel.Request(request);
               Console.WriteLine(reply);
               request.Close();
               reply.Close();
                channel.Close();
               factory.Close();
            }

Chapter 12 Implementing One-Way and Asynchronous Operations                               

If the client application does not require the service tosend a response, then waiting for one is a waste of time and can impact the responsivenessof the client application.

In this situation, you might find that a one-way operationcan improve performance of the client application.If the client application does require a response but cansafely perform other tasks while waiting for this response, then you should implement asynchronousmethod invocation. Using this technique, the client application can send a requestand then continue execution. When a reply message arrives from the service, a separate thread inthe client application handles the response.                                One-way operations and asynchronous operations both requirethe client application and the service to be running at the same time. If this is not thecase, then you should consider using message queues as the transport medium between the clientapplication and the service. A message queue can provide durable storage for messages.

Implementing One-Way Operations

you can invoke the one-way operation in a reliable session. Theservice will send back an acknowledgment to the client when it starts processing the message,

 

public interface IAdventureWorksAdmin
{
   [OperationContract(IsOneWay = true)]
    voidGenerateDailySalesReport(string id);
}
  

Tip If you need to implement one-way operations but cannotguarantee the thread-safe status of the corresponding methods, you should not set theConcurrencyMode attribute of the service to ConcurrencyMode.Multiple. Just enable reliable sessions. When you enable reliable sessions, the client will not waitfor a single-threaded service to accept each message before continuing; instead, the client will beable to carry on as soon as the service  has acknowledged the message. Message acknowledgments aregenerated by the WCF runtime hosting the service before the message is dispatched to theservice instance; they are not blocked by a single-threaded service instance.

 

Recommendations for Using One-Way Operations

You have seen that one-way operations are a very usefulmechanism for improving the responsiveness of a client application by allowing it tocontinue executing without waiting for the service to complete processing operation requests

            -Servicesthat don’t use sessions provide the greatest degree of parallelism by default

            -Servicesthat use sessions can set the concurrency mode to enable multi-threading,butyou must ensure that the operations in the service are thread-safe

            -Usingreliable sessions enables a client application to close a connection to aservice before the service has completed processing of alloutstanding requests.

 

Invoking and Implementing Operations Asynchronously

A one-way operation is useful for “fire and forget”scenarios Invoking an Operation Asynchronously in a Client Application

An asynchronous proxy provides begin and end pairs ofmethods for each operation.The client application can invoke the begin method to initiatethe operation. The begin method returns after sending the request, but a new thread createdby the .NET Framework runtime in the client waits for the response. When you invoke thebegin method, you also provide the name of a callback method. When the service finishes theoperation and returns the results to the client proxy, the callback method executes on thisnew thread.It is important to understand that you do not need to modify theservice in any way to support.

Implementing an Operation Asynchronously in a WCF Service

Important You should understand the important distinctionbetween asynchronous operation invocation in the client application and asynchronousoperation implementation in the service.Asynchronous invocation in the client application enablesthe client to initiate the operation and

then continue its own processing while waiting for aresponse. Asynchronous implementation in the service enables the service to offload the processing toanother thread or sleep while waiting for some background process to complete. A clientapplication invoking an operation implemented asynchronously by the service still waits for the operationto complete before continuing.

 

public interface IAdventureWorksAdmin
{
   [OperationContract(IsOneWay = true)]
    voidGenerateDailySalesReport(string id);
 
   [OperationContract(AsyncPattern = true)]
    IAsyncResultBeginCalculateTotalValueOfStock(string id, AsyncCallback cb,
    object s);
    intEndCalculateTotalValueOfStock(IAsyncResult r);
}

this form of asynchronous programming. Indeed, the serviceitself does not necessarily need to be a WCF service; it could be a service implementedby using other technologies.

 

 

 

 

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值