Creating a Behavior to Inspect Messages on the Server


The following sections contain several exercises that enable the creation and use of behaviors on both the client and the service side. These examples use what is likely the most common type of behavior, a type of behavior that inspects and interacts with the messages passing between client and service.

There are various scenarios in which it may be important for the content of a message to be inspected and/or altered. In these examples, there is a simple communication program in use, and the business requirements dictate that messages from both the client and the server must be audited by another service for storage.

Here we're using a simple chat/echo service, but the real world presents numerous places where auditing would be required. Those include the ever-growing auditing requirements of government/industry compliance in the private sector and the need to monitor the online interactions of children out of safety concerns in the household. And that is just in the context of monitoring the content of the messages for auditing; as you can imagine, with the capability to access the message itself, there are a number of other situations for which to use these custom behaviors.

In these exercises, you will also be introduced to the two interfaces used to incorporate the MessageInspector functionality. These are IStubMessageInspector on the service side and IProxyMessageInspector on the client side.

Creating the Auditing Service

Both the service and the client applications that will be created will report the messages they transmit to an auditing service. That auditing service is a simple one with a single operation, ProcessMessage. Follow these steps to create the auditing service:

1.

Create a blank solution in Visual Studio called Custom Behaviors.

2.

Add a C# Windows console project named AuditingService to the solution.

3.

Add references to the System.ServiceModel and System.Configuration assemblies.

4.

Add a new class module named Contracts.cs.

5.

Define the contract for the chat application by replacing the code in the module with this code:

using System; using System.Collections.Generic; using System.Text; using System.ServiceModel; namespace AuditingService {    [ServiceContract]     public interface IAudit     {         [OperationContract(IsOneWay = true)]         void ProcessMessage(                             string reportedFrom,                             string messageType,                             string message);     } }


6.

Create the service type by adding a new class module named Audit.cs to the project and entering this code into that module:

namespace AuditingService {     public class Auditor : IAudit     {         public void ProcessMessage(                                    string reportedFrom,                                    string messageType,                                    string message)         {             Console.WriteLine("Received Message From:" + reportedFrom);             Console.WriteLine("Processing Message of Type:" + messageType);             Console.WriteLine("Message:");             Console.WriteLine(message);             Console.WriteLine("--------------------------------");             return;         }     } }


7.

Provide a host for the service by replacing the code in the Program.cs module with this code:

using System; using System.Collections.Generic; using System.Configuration; using System.Text; using System.ServiceModel; namespace AuditingService {     class Program     {       static void Main(string[] args)       {         Uri baseServiceAddress =           new Uri(             System.Configuration.ConfigurationManager.             AppSettings.Get("baseAddress"));         using (ServiceHost sh = new ServiceHost(           typeof(AuditingService.Auditor),           new Uri[]{baseServiceAddress}))       {        sh.Open();        Console.WriteLine("Auditing Service is now running.");        Console.ReadLine();       }    } }


8.

Configure the auditing service by adding an Application Configuration file named App.Config to the project, and replacing its contents with the following:

<?xml version="1.0" encoding="utf-8" ?> <configuration>   <appSettings>     <add key="baseAddress" value="http://localhost:8000/Auditor" />   </appSettings>   <system.serviceModel>   <services>     <service                            type="AuditingService.Auditor" >                    <endpoint behaviorConfiguration="ServiceBehavior"                                   address=""                                   binding="basicHttpBinding"                                   contract ="AuditingService.IAudit" />    </service>  </services>  <bindings>    <basicHttpBinding>    </basicHttpBinding>  </bindings>  <behaviors>       <behavior         name="ServiceBehavior"         returnUnknownExceptionsAsFaults="True">         <metadataPublishing           enableGetWsdl="True"           enableHelpPage="True"           enableMetadataExchange="True"               />       </behavior>   </behaviors>  </system.serviceModel> </configuration>


Creating the Dispatch Service Behavior

Follow these next steps to create the dispatch service behavior that will send copies of all messages received by a service to the auditing service:

1.

Add a new C# class library project to the solution and name it ServiceAuditBehavior.

2.

Add references to the System.ServiceModel and System.Runtime.Serialization assemblies.

3.

Add a version of the auditing service's contract to the service behavior project by adding a new class module called Contracts.cs, and replacing the code therein with this code:

using System; using System.Collections.Generic; using System.Text; using System.ServiceModel; namespace AuditingService {    [ServiceContract]     public interface IAudit     {         [OperationContract(IsOneWay = true)]         void ProcessMessage(                             string reportedFrom,                             string messageType,                             string message);     } }


4.

Define an attribute by which the service behavior can be attached to a service by adding a new class module called AuditAttribute.cs to the project, and replacing the default code in that module with this code:

using System; using System.Collections.Generic; using System.Text; using System.ServiceModel; using System.ServiceModel.Configuration; using System.Collections.ObjectModel; namespace ServiceAuditBehavior {     [AttributeUsage(AttributeTargets.Class)]     public class AuditAttribute : Attribute, IServiceBehavior     {         public void ApplyBehavior(                           ServiceDescription description,                           ServiceHostBase shBase,                      Collection<DispatchBehavior> behaviors,                      Collection<BindingParameterCollection> parameters)     {        foreach (DispatchBehavior behavior in behaviors)        {            ChannelFactory<IAudit> fact =               new ChannelFactory<IAudit>("ServiceAudit");            IAudit prt = fact.CreateChannel();            ServiceAuditMessageInspector insp =               new ServiceAuditMessageInspector(prt);            behavior.MessageInspectors.Add(insp);        }     }   } }


There are several points to note from this code. The class implements both the Attribute and the ServiceBehavior interfaces. The implementation of the ApplyBehavior() method of the ServiceBehavior interface is where the mechanism of the custom behavior gets inserted into the dispatch operations of the service, adding the custom behavior as an inspector of each incoming message that is to be dispatched.

5.

Begin creating the actual custom behavior by adding a new class named AuditMessageInspector.cs to the project, and replacing the default code in that module with this code:

using System; using System.Collections.Generic; using System.Text; using System.Xml; using System.IO; using System.ServiceModel; namespace ServiceAuditBehavior {     class ServiceAuditMessageInspector : IStubMessageInspector     {         private IAudit _proxy;         public ServiceAuditMessageInspector(IAudit prx)         {             _proxy = prx;         }              public object AfterReceiveRequest(                  ref Message request,                  IClientChannel channel,                  InstanceContext instanceContext)              {                 _proxy.ProcessMessage("Server", request.Headers.Action, request.ToString());                  return null;                  }                  public void BeforeSendReply(ref Message request, object correlationState)              {                   System.Console.WriteLine(request.Headers.MessageVersion.Envelope);              }        } }


This code defines a class that implements the IStubMessageInspector interface. That interface has two methods, AfterReceiveRequest() and BeforeSendReply(), which provide the opportunity to inspect and interact with incoming and outgoing messages. In this case, incoming messages are sent to the auditing service, and outgoing messages are simply registered in output to the console.

Creating the Service

Now the service behavior has been programmed. Follow these next few steps to create a simple chat/echo service to which that behavior will be applied:

1.

Add a new C# console application project called Service to the solution.

2.

Add references to the System.Configuration, System.ServiceModel, and System.Runtime.Serialization assemblies.

3.

Add a reference to the ServiceAuditBehavior project.

4.

Add a new class module, Contracts.cs, to the solution and replace the default code in that class with this code:

using System; using System.Collections.Generic; using System.Text; using System.ServiceModel; namespace Service {     [ServiceContract]     public interface IChat     {          [OperationContract]          string Talk(string chatText);     } }


5.

Replace the code in the Program.cs module with code for a service that implements the service contract defined in the preceding step:

using System; using System.Collections.Generic; using System.Text; using System.ServiceModel; namespace Service {     [ServiceAuditBehavior.Audit]     public class Chat : IChat     {         static void Main(string[] args)         {             Uri baseServiceAddress = new Uri(               System.Configuration.ConfigurationManager.AppSettings.Get(                 "baseAddress"));             ServiceHost sh = new ServiceHost(typeof(Chat),baseServiceAddress);             sh.Open();             Console.WriteLine("Service is now running.");             Console.ReadLine();         }         public string Talk(string chatText)         {             Console.WriteLine("Client said:" + chatText);             return ("Did you say " + chatText + " ?");         }     } }


This code defines a service type that implements the service contract defined in the preceding step. The custom audit behavior is added to the service type as an attribute.

6.

Configure the service by adding an application configuration file to the project with this content. Replace the code in the Program.cs module with code for a service that implements the service contract defined in the preceding step:

<configuration>   <appSettings>     <add key="baseAddress" value="http://localhost:8000/Behaviors" />   </appSettings>   <system.serviceModel>     <client>       <endpoint            name="ServiceAudit"            address="http://localhost:8000/Auditor"            binding="basicHttpBinding"            contract ="ServiceAuditBehavior.IAudit" />     </client>     <services>       <service type="Service.Chat">         <endpoint behaviorConfiguration="ServiceBehavior"           address=""           contract="IChat"           binding ="basicHttpBinding"/>       </service>     </services>   </system.serviceModel> </configuration>


This configuration includes the configuration of a client for the auditing service, because the custom behavior that has been added to the chat/echo service sends messages to the auditing service.




Presenting Microsoft Communication Foundation. Hands-on.
Microsoft Windows Communication Foundation: Hands-on
ISBN: 0672328771
EAN: 2147483647
Year: 2006
Pages: 132

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net