Extending WCF Services - WCF Multi-layer Services Development with Entity Framework Fourth Edition (2014)

WCF Multi-layer Services Development with Entity Framework Fourth Edition (2014)

Chapter 13. Extending WCF Services

As we have learned from previous chapters, WCF provides a unified programming model to build service-oriented applications. With WCF, you can build secure, reliable, transacted solutions that integrate well across different platforms and interoperate with existing solutions. The WCF programming model is very comprehensive, and yet, it is very flexible. You can extend this model to enhance the functionality or customize the framework for your specific needs. In this last chapter of this book, we will explore extension points of WCF services and learn how to extend a WCF service.

We will cover the following topics in this chapter:

· WCF runtime architecture

· Why extend a WCF service?

· WCF extension points

· Extending a WCF service

· Extending HelloWorldService

The WCF runtime architecture

The WCF runtime provides a set of classes responsible for sending and receiving messages. For example, formatting messages, applying security, transmitting and receiving messages by using various transport protocols, as well as dispatching received messages to the appropriate operations; all these fall within the WCF runtime scope.

The following diagram shows the WCF runtime (http://msdn.microsoft.com/en-us/magazine/cc163302.aspx):

The WCF runtime architecture

The sequence of a WCF service call might look as follows:

1. A client application calls a WCF service through a WCF proxy.

2. The proxy translates the call to one or more WCF messages.

3. The messages are passed through channels and transported to the service.

4. On the service side, the messages are transported through channels.

5. Service dispatchers pick up the messages, making calls to WCF services and then returning the results back to the client.

As you can see from this diagram, there are multiple layers and many entry points for a WCF service call. At almost every entry point, there is a possible extension interface that you, as a WCF developer, can extend. In fact, there are over 30 extension points in the WCF runtime. In this chapter, we will explore some common extension points and extend our HelloWorldService to log incoming/outgoing messages.

Note

For a comprehensive list of WCF extension points, look at the MSDN documentation on WCF extensions. Additionally, you might want to check out the blog at http://blogs.msdn.com/b/carlosfigueira/archive/2011/03/14/wcf-extensibility.aspx for WCF extension points. This blog explains many of the WCF extension points up to .NET Framework 4.0, but they are all also valid for .NET 4.5.

Why extend WCF services?

There are many reasons why you might need to extend a WCF service, such as the following:

· Message validation

· Parameter validation

· Message logging

· Message transformations

· Custom serialization formats

· Custom deserialization formats

· Output caching

· Object pooling

· Error handling

· Authorization

· Authentication

· Monitoring/auditing

· Service usage analysis/metrology

WCF extension points

The client and service runtimes expose various extensibility points that the developer can leverage. These extensibility points can be used to customize various WCF capabilities, such as encoding messages, intercepting parameters, or selecting the operations to invoke on the service side.

Client-side extension points

A client-side extension is also called a proxy extension. Some available client-side extensions are listed as follows:

· Parameter inspection: Performs custom validation, value modification, or special filtering for method parameters, before these method calls are translated to messages

· Message formatting for serialization: Customizes the serialization process by using a custom formatter object

· Message inspection: Implements cross-operation messaging features such as message logging, validation, or transformations functionality

· Result processing: Inspects the returned result, formats the message, and customizes the deserialization process after the service invocation is finished, but shortly before the result is returned to the client

The following diagram shows three extension points on the client side (http://msdn.microsoft.com/en-us/magazine/cc163302.aspx):

Client-side extension points

Service-side extension points

A service-side extension is also called a dispatcher extension. A service-side extension can be used to perform message inspection, message formatting, and parameter inspection. For the message formatting extension, it can customize the deserialization process for incoming messages and the serialization process for outgoing messages. In addition, there is an operation selector extension, which is to override the default operation selection behavior and an operation invoker extension to provide a custom operation invoker object.

The following diagram shows five extension points on the service side (http://msdn.microsoft.com/en-us/magazine/cc163302.aspx):

Service-side extension points

Extending a WCF service

As we have learned earlier, there are more than 30 extension points in the WCF runtime, but the most common situation is to customize the extension of a behavior. Discussion of all WCF extension points is beyond the context of this book, and from this point on, we will focus only on the behavior extension.

WCF behaviors are types that define how a WCF service behaves. A custom behavior can be applied to a WCF service to modify the default behavior and add custom extensions, to inspect and validate service configuration, or modify runtime behavior of the service.

To extend a behavior, DispatchRuntime and DispatchOperation need to be extended on the service side and ClientRuntime and ClientOperation need to be extended on the client side. This can be achieved by implementing corresponding interfaces such as IParameterInspector,IDispatchMessageInspector, and IClientMessageFormatter. These interfaces provide the necessary methods to allow parameters to be inspected, messages to be inspected, and to serialize and deserialize parameters to and from messages.

The following are standard procedures to extend a WCF 'margin-top:0cm;margin-right:0cm;margin-bottom:0cm; margin-left:18.0pt;margin-bottom:.0001pt;text-indent:-18.0pt;line-height:normal'>· Create an extension class, implementing the appropriate extension interface(s)

· Create a behavior class, implementing the appropriate behavior interface(s)

· Optionally create a behavior element class if extensions will be applied through a configuration file

· Add behaviors to the runtime through code, attribute, or configuration

WCF extension classes

To extend a WCF service, you first need to create an extension class. As each extension point is modeled by an interface, you need to choose the proper interface to implement when creating an extension class. An extension class can implement a service (dispatcher) interface, a client (proxy) interface, or in some cases, both interfaces. If the extension class implements both the client and service interfaces, this same extension class can be used to extend a WCF service on both the client and service sides.

All extension interfaces are defined in the System.ServiceModel.Dispatcher namespace. The following is a list of the commonly used extension interfaces:

· IParameterInspector: You can implement this interface to create a custom parameter inspector that can view and modify the contents of a call. The inspection can be done before or after the call in either client or service applications.

· IDispatchMessageFormatter/IClientMessageFormatter: You can implement this interface to create a custom formatter that serializes objects into messages and deserializes messages into objects for a particular operation.

· IDispatchMessageInspector/IClientMessageInspector: You can implement this interface to inspect or modify inbound or outbound application messages either prior to or after an operation is invoked.

· IDispatchOperationSelector/IClientOperationSelector: You can implement this interface to customize the selection of the operation to invoke.

· IOperationInvoker: You can implement this interface to control the conversion from an untyped object and array of parameters to a strongly typed method call on that object.

WCF behavior classes

In addition to an extension class, you also need to create a behavior class in order to extend a WCF service through behaviors.

There are four types of behaviors for a WCF service that you can extend:

· Service behavior

· Endpoint behavior

· Contract behavior

· Operation behavior

Each type allows you to apply extensions at different scopes. For example, IServiceBehavior can be applied at service, endpoint, contract, and operation level, but IOperationBehavior can only be applied at operation level.

Each type of behavior is modeled by a different interface. All interfaces contain the same set of methods, but each method has a different signature (with the exception of the ApplyClientBehavior method, as the service interface does not have this method). You need to choose the proper interface to implement when creating a behavior class.

The behavior class can also implement the attribute interface, so it can be applied through attributes in the code.

All behavior interfaces are defined in the System.ServiceModel.Description namespace. The following is a list of commonly used behavior interfaces with their scopes:

· IServiceBehavior: Service, endpoint, contract, and operation

· IEndpointBehavior: Endpoint, contract, and operation

· IContractBehavior: Contract and operation

· IOperationBehavior: Operation

WCF behavior element classes

If you want to add your extension class only through configuration, you need to create a behavior element class. A behavior extension element class represents a configuration element that contains subelements that specify behavior extensions, which enables the user to customize service or endpoint behaviors. You can override the CreateBehavior method and BehaviorType in this extension class to let the WCF runtime get the behavior extension definition through the behaviorExtensions element in the configuration file.

Note

If your WCF service is self-hosted, you can create your extension behavior in your host code. In this case, you don't need to create a behavior element class.

With a behavior element class, you can register your extension class in the config file (or machine.config file). It is strongly recommended that you use fully qualified assembly names when registering your extension types.

Applying the extensions

Once you have created the extension class, the behavior class, and optionally the behavior extension element class, you need to apply the extension to your WCF service.

The behaviors can be applied in three different ways:

· Code: The description of the service, endpoint, contract, and operation objects have a property with a collection of behaviors associated with that object. You can add your extension behaviors by using the code reference.

· Configuration: For service and endpoint behaviors, you can add your extensions via the behaviors section of the system.serviceModel node in the service configuration file.

· Attributes: For non-endpoint behaviors, you can create an attribute class, which implements one of the behavior interfaces, and then apply the attribute to the appropriate service element.

Extending HelloWorldService

Now that we have learned the basic concepts and theories of the WCF extension, let's do some practical work to further understand it. In this section, we will extend our HelloWorldService with a runtime behavior, inspecting and logging the incoming and outgoing messages of the service.

Setting up the service

First, we will set up a copy of HelloWorldService with no extensions. We will extend this service in the following sections to inspect and log all incoming and outgoing messages.

To set up the service, follow these steps:

1. You can refer to Chapter 1, Implementing a Basic HelloWorld WCF Service, and Chapter 2, Hosting the HelloWorld WCF Service, of this book to get the HelloWorld solution ready.

2. Create a new folder, HostIISExtended, under the C:\SOAwithWCFandEF\Projects\HelloWorld folder.

3. Copy all files from HostIIS to this new folder.

4. Start IIS Manager and add a new application HelloWorldServiceExtended, pointing to this new folder.

5. Test it with the following URL in a browser: http://localhost/HelloWorldServiceExtended/HelloWorldService.svc.

You should see the WSDL description page of the HelloWorldService service. Click on the link to make sure you get the WSDL of this new service.

Next, let's add this folder to the HelloWorld solution in Visual Studio:

1. Start Visual Studio and open the HelloWorld solution.

2. Add a new solution folder, HostIISExtended, to the solution.

3. Add the C:\SOAwithWCFandEF\Projects\HelloWorld\HostIISExtended\Web.config file to the new solution folder.

4. Add another solution folder, bin, under the HostIISExtended solution folder.

5. Add all files under the C:\SOAwithWCFandEF\Projects\HelloWorld\HostIISExtended\bin folder to this new solution folder.

6. Select the HelloWorldService project and go to the project's Properties page.

7. Add the following copy statements to the post-built events:

8. xcopy "$(AssemblyName).dll" "C:\SOAwithWCFandEF\Projects\HelloWorld\HostIISExtended\bin" /Y

xcopy "$(AssemblyName).pdb" "C:\SOAwithWCFandEF\Projects\HelloWorld\HostIISExtended\bin" /Y

This way it will make sure that the HelloWorldServiceExtended application will always have the latest HelloWorldService binary files.

Creating the extension project

To extend HelloWorldService, we need to create an extension class, a behavior class, and a behavior element class. We need to create an assembly for all of these classes so that later we can apply this extension to the WCF service.

You can follow these steps to create a project for this extension assembly:

1. Open the HelloWorld solution.

2. Add a new class library project named HelloWorldExtension.

3. Delete the Class1.cs file from this new project.

4. Add the following three references to the project:

5. System.Configuration

6. System.ServiceModel

System.Web

5. Go to the project's Properties page.

6. Add the following copy statements to the post-built events:

7. xcopy "$(AssemblyName).dll" ..\..\..\HostIISExtended\Bin /Y

xcopy "$(AssemblyName).pdb" ..\..\..\HostIISExtended\Bin /Y

This way we will make sure that the HostIISExtended application will always have the latest extension binary files. As you will see in the following sections, the WCF runtime will search the bin directory of the host application to discover the extension class.

Creating an extension class

As we mentioned earlier in this chapter, to extend a WCF service, we first need to create an extension class to define the extension actions that will be applied to the WCF service. Follow these steps to create this extension class:

1. Add a new class named MyMessageInspector to the HelloWorldExtension project.

2. Add the following five using statements to the new class:

3. using System.ServiceModel;

4. using System.ServiceModel.Dispatcher;

5. using System.ServiceModel.Channels;

6. using System.IO;

using System.Web.Hosting;

3. Make this class implement the IDispatchMessageInspector interface.

4. Add the following method to trace a message:

5. private Message TraceMessage(MessageBuffer buffer)

6. {

7. var msg = buffer.CreateMessage();

8. var appPath = HostingEnvironment.ApplicationPhysicalPath;

9. var logPath = appPath + "\\log.txt";

10. File.AppendAllText(logPath, DateTime.Now.ToString("G"));

11. File.AppendAllText(logPath, "\r\n");

12. File.AppendAllText(logPath,

13. "HelloWorldService is invoked");

14. File.AppendAllText(logPath, "\r\n");

15. File.AppendAllText(logPath, string.Format("Message={0}", msg));

16. File.AppendAllText(logPath, "\r\n");

17. return buffer.CreateMessage();

}

Note

Here, we are logging to a file. You might want to log to the Windows event logs or a database in your own project. You can also take advantage of some logging frameworks such as Log4Net to do the logging.

5. Give the IIS identity of the HostIISExtended application write access to the HostIISExtended application folder (C:\SOAwithWCFandEF\Projects\HelloWorld\HostIISExtended), as the extended WCF service will write to a file in this folder. You can find out the IIS identity of the application from IIS Manager | Application Pools. In the application pool of the HostIISExtended application, go to Advanced Settings | Process Model | Identity (if you use the default application pool identity, which is ApplicationPoolIdentity, the corresponding Windows username for your application pool identity will be IIS AppPool\<your application pool name>).

6. Now, add the following two methods to call the method we just created so that we can log each incoming and outgoing message:

7. public object AfterReceiveRequest(

8. ref Message request, IClientChannel channel,

9. InstanceContext instanceContext)

10.{

11.request =

12. TraceMessage(request.CreateBufferedCopy(int.MaxValue));

13. return null;

14.}

15.

16.public void BeforeSendReply(

17. ref Message reply,

18. object correlationState)

19.{

20. reply = TraceMessage(reply.CreateBufferedCopy(int.MaxValue));

}

In this extension class, we make it implement the IDispatchMessageInspector interface so that we can extend the service (dispatcher) to inspect the messages. Then, we have added two inspector methods to inspect the outgoing and incoming messages. In this case, we just log the messages, but you can even modify the messages according to your own requirements.

Note

As the body of the request/reply message can only be processed once, we have to pass a buffer of the original message to the TraceMessage method, create a new message from the buffer, and then return a new message to the original method, to ensure that the original methods do not get affected. Also, we make the AfterReceiveRequest method return null because we don't need to correlate between the two methods (the correlationState parameter in the BeforeSendReply method is the return result of the AfterReceiveRequest method).

The whole content of the MyMessageInspector.cs file is as follows:

using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

using System.Threading.Tasks;

using System.ServiceModel;

using System.ServiceModel.Dispatcher;

using System.ServiceModel.Channels;

using System.IO;

using System.Web.Hosting;

namespace HelloWorldExtension

{

class MyMessageInspector : IDispatchMessageInspector

{

private Message TraceMessage(MessageBuffer buffer)

{

var msg = buffer.CreateMessage();

var appPath =

HostingEnvironment.ApplicationPhysicalPath;

var logPath = appPath + "\\log.txt";

File.AppendAllText(logPath,

DateTime.Now.ToString("G"));

File.AppendAllText(logPath, "\r\n");

File.AppendAllText(logPath,

"HelloWorldService is invoked");

File.AppendAllText(logPath, "\r\n");

File.AppendAllText(logPath,

string.Format("Message={0}", msg));

File.AppendAllText(logPath, "\r\n");

return buffer.CreateMessage();

}

public object AfterReceiveRequest(

ref Message request, IClientChannel channel,

InstanceContext instanceContext)

{

request =

TraceMessage(request.CreateBufferedCopy(int.MaxValue));

return null;

}

public void BeforeSendReply(

ref Message reply,

object correlationState)

{

reply = TraceMessage(reply.CreateBufferedCopy(int.MaxValue));

}

}

}

Creating a behavior class

Next, we need to create a behavior class. In this behavior class, we will apply the extension class to the WCF runtime.

Follow these steps to create the behavior class:

1. Add a new class named MyMessageInspectorBehavior to the HelloWorldExtension project.

2. Add the following five using statements to the new class:

3. using System.ServiceModel;

4. using System.ServiceModel.Description;

5. using System.ServiceModel.Channels;

6. using System.ServiceModel.Dispatcher;

using System.Collections.ObjectModel;

3. Make this class inherit Attribute and implement the IServiceBehavior interface.

4. Add the following method to apply the 'margin-top:12.0pt;margin-right:0cm;margin-bottom: 7.5pt;margin-left:18.0pt;text-indent:-18.0pt;line-height:normal'>5. void IServiceBehavior.ApplyDispatchBehavior(

6. ServiceDescription serviceDescription,

7. ServiceHostBase serviceHostBase)

8. {

9. foreach (ChannelDispatcher cd in

10. serviceHostBase.ChannelDispatchers)

11. foreach (EndpointDispatcher ed in

12. cd.Endpoints)

13. ed.DispatchRuntime.MessageInspectors.Add

14. (new MyMessageInspector());

}

5. We also need to implement the following two methods, though in this example, we don't do anything within them:

6. void IServiceBehavior.AddBindingParameters(

7. ServiceDescription serviceDescription,

8. ServiceHostBase serviceHostBase,

9. Collection<ServiceEndpoint> endpoints,

10. BindingParameterCollection bindingParameters)

11.{

12. //do nothing

13.}

14.

15.void IServiceBehavior.Validate(

16. ServiceDescription serviceDescription,

17. ServiceHostBase serviceHostBase)

18.{

19. //do nothing

}

In this class, we make it implement the IServiceBehavior interface so that we can apply our extension behavior to the WCF runtime. We also make it inherit the Attribute class so that this extension behavior can be applied using attributes in code (though we are not going to take the code approach in this chapter).

The full content of the MyMessageInspectorBehavior.cs file will be as follows:

using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

using System.Threading.Tasks;

using System.ServiceModel;

using System.ServiceModel.Description;

using System.ServiceModel.Channels;

using System.ServiceModel.Dispatcher;

using System.Collections.ObjectModel;

namespace HelloWorldExtension

{

class MyMessageInspectorBehavior : Attribute, IServiceBehavior

{

void IServiceBehavior.AddBindingParameters(

ServiceDescription serviceDescription,

ServiceHostBase serviceHostBase,

Collection<ServiceEndpoint> endpoints,

BindingParameterCollection bindingParameters)

{

//do nothing

}

void IServiceBehavior.ApplyDispatchBehavior(

ServiceDescription serviceDescription,

ServiceHostBase serviceHostBase)

{

foreach (ChannelDispatcher cd in

serviceHostBase.ChannelDispatchers)

foreach (EndpointDispatcher ed in

cd.Endpoints)

ed.DispatchRuntime.MessageInspectors.Add

(new MyMessageInspector());

}

void IServiceBehavior.Validate(

ServiceDescription serviceDescription,

ServiceHostBase serviceHostBase)

{

//do nothing

}

}

}

Creating a behavior element class

To apply the extension though configuration, we need to create a behavior element class. This class will tell the WCF runtime how to discover and apply the extension class to the WCF runtime.

The following steps create this behavior element class:

1. Add a new class named MyMessageInspectorElement to the HelloWorldExtension project.

2. Add the following using statement to the new class:

using System.ServiceModel.Configuration;

3. Make this class inherit BehaviorExtensionElement.

4. Add the following code to define the 'margin-top:12.0pt;margin-right:0cm;margin-bottom: 7.5pt;margin-left:18.0pt;text-indent:-18.0pt;line-height:normal'>5. public override Type BehaviorType

6. {

7. get { return typeof(MyMessageInspectorBehavior); }

8. }

9.

10.protected override object CreateBehavior()

11.{

12. return new MyMessageInspectorBehavior();

}

In this element class, we just override one property and one method of the BehaviorExtensionElement class. The BehaviorType property will tell the WCF runtime what type our extension behavior is, and the CreateBehavior method will tell the WCF runtime how to create the extension behavior class.

The full content of the MyMessageInspectorElement.cs file will be as follows:

using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

using System.Threading.Tasks;

using System.ServiceModel.Configuration;

namespace HelloWorldExtension

{

class MyMessageInspectorElement : BehaviorExtensionElement

{

public override Type BehaviorType

{

get { return typeof(MyMessageInspectorBehavior); }

}

protected override object CreateBehavior()

{

return new MyMessageInspectorBehavior();

}

}

}

Applying the extension to HelloWorldService

The last step is to apply our newly created extension class to HelloWorldService. As we have created a behavior extension element class, we can apply this extension only through configuration.

1. Start Visual Studio.

2. Open the HelloWorld solution.

3. Open the Web.config file under the HostIISExtended folder.

4. Add the following extensions node to be a child node of the system.serviceModel node:

5. <extensions>

6. <behaviorExtensions>

7. <add name="myMessageInspectorBehavior"

8. type="HelloWorldExtension.MyMessageInspectorElement,

9. HelloWorldExtension, Version=1.0.0.0,

10. Culture=neutral, PublicKeyToken=null"/>

11. </behaviorExtensions>

</extensions>

Here, when specifying the extension element, we are fully qualifying it with the element name, name space, version, and culture. As we have said earlier in this chapter, this will make our extension more secure than just specifying its name. Here, we don't specify a public token, but to make it even more secure, you can assign a public key token to the element (first, you need to make your extension assembly strong-named, then put the public key token of the assembly here. See http://msdn.microsoft.com/en-us/library/xwb8f617(v=vs.110).aspx for more information about strong-named assemblies).

5. Add the following node as a child node of the behavior node:

<myMessageInspectorBehavior/>

So, the whole behaviors node should resemble the following:

<behaviors>

<serviceBehaviors>

<behavior>

<serviceMetadata httpGetEnabled="true"/>

<myMessageInspectorBehavior/>

</behavior>

</serviceBehaviors>

</behaviors>

This will apply the behavior extension that we have added in the preceding step to our HelloWorldService in this IIS application. This means that whenever this service is invoked, this extension will be applied. We will test this with a test program in the next section.

The following is the content of the system.serviceModel node:

<system.serviceModel>

<serviceHostingEnvironment >

<serviceActivations>

<add factory=

"System.ServiceModel.Activation.ServiceHostFactory"

relativeAddress="./HelloWorldService.svc"

service="HelloWorldService.HelloWorldService"/>

</serviceActivations>

</serviceHostingEnvironment>

<behaviors>

<serviceBehaviors>

<behavior>

<serviceMetadata httpGetEnabled="true"/>

<myMessageInspectorBehavior/>

</behavior>

</serviceBehaviors>

</behaviors>

<extensions>

<behaviorExtensions>

<add name="myMessageInspectorBehavior"

type="HelloWorldExtension.MyMessageInspectorElement,

HelloWorldExtension, Version=1.0.0.0,

Culture=neutral, PublicKeyToken=null"/>

</behaviorExtensions>

</extensions>

</system.serviceModel>

Testing the extended HelloWorldService

Now that we have the service extension applied to the service, we can test it with a program. In this section, we will reuse our HelloWorldClient to test the service. We will verify that the extension has been applied to the service successfully through the Web.config file.

However, before testing it with the HelloWorldClient application, you need to rebuild the solution so that all the related library files will be created. After you have rebuilt the solution successfully, you can test it via a web browser first. Just go tohttp://localhost/HelloWorldServiceExtended/HelloWorldService.svc, and you should see the WSDL description page of the extended HelloWorldService service.

Click on the link to make sure that you get the WSDL of this extended service.

If you didn't get the WSDL description page of the extended service and instead get an error page that says Internet Explorer cannot display the webpage or This page can't be displayed, it is because your IIS identity doesn't have write access to the HostIISExtended IIS application folder (C:\SOAwithWCFandEF\Projects\HelloWorld\HostIISExtended). You can refer back to the previous section Creating an extension class for more details about this.

If you get a The type 'HelloWorldExtension.MyMessageInspectorElement, HelloWorldExtension, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null' registered for extension 'myMessageInspectorBehavior' could not be loaded message, it is because you haven't rebuilt your solution. Rebuild the solution and try again.

Once you successfully get the WSDL of the extended service, you can follow these steps to test the service with the HelloWorldClient application:

1. In Visual Studio, open the App.config file from the HelloWorldClient project.

2. In the config file, change the address of the endpoint to http://localhost/HelloWorldServiceExtended/HelloWorldService.svc.

3. Now, rebuild the solution, set HelloWorldClient as the startup project, and run the program. You should see the same result as in Chapter 1, Implementing a Basic HelloWorld WCF Service.

4. Open Windows Explorer and go to the C:\SOAwithWCFandEF\Projects\HelloWorld\HostIISExtended folder. Here, you will find a log.txt file. Open it and you will see some logs like this:

5. 8/6/2014 8:25:20 PM

6. HelloWorldService is invoked

7. Message=<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">

8. <s:Header>

9. <Action s:mustUnderstand="1" xmlns="http://schemas.microsoft.com/ws/2005/05/addressing/none">http://tempuri.org/IHelloWorldService/GetMessageResponse</Action>

10. </s:Header>

11. <s:Body>

12. <GetMessageResponse xmlns="http://tempuri.org/">

13. <GetMessageResult>Hello world from Mike Liu!</GetMessageResult>

14. </GetMessageResponse>

15. </s:Body>

</s:Envelope>

5. To debug the extension, you can first set a breakpoint within the TraceMessage method in the MyMessageInspector.cs class and then step into the extension from the client program, or attach to the w3wp.exe process and then run the client program to hit the breakpoint (you must be running Visual Studio as administrator to step into the extension class).

This test proves that our TraceMessage service extension method has been invoked by the service for all incoming and outgoing messages. As you can see in this example, we didn't change any code in the service, we are still using the same client program as before, yet the extension has been applied by changing a few lines within the configuration file. You can use the same mechanisms to plug in your extensions in your environment to any existing services at any time.

Summary

In this chapter, we learned the basic concepts of the WCF extension and extended service behavior of the HelloWorld service. In this sample extension, we just logged all incoming and outgoing messages, but in your environment, you can do much more than just logging messages. There are many extension points and you should examine the needs of your WCF service and pick the most appropriate extension points according to your application requirements.

This is the last chapter of the book. Through this book, we learned how to create, host, and debug a WCF service, whether on-premise or in the cloud. We also learned WCF exception handling and applied best practice to our WCF service development. As Entity Framework is now the standard data access ORM, we explored Entity Framework, LINQ to Entities, and replaced our data access layer with LINQ to Entities. We also learned WCF transaction management by using LINQ to Entities and configured the security for our WCF service. In addition to this, we upgraded our SOAP WCF service to a RESTful WCF service and created a Windows 8 app to consume this RESTful WCF service through C#/XAML, jQuery, and WinJS. Then, in this last chapter, we extended our WCF service to log all incoming and outgoing messages. At this point, you should be very comfortable in creating and configuring your own WCF service, customizing its transaction and security settings, and extending it if needed. I hope you can apply your WCF knowledge to your real work and enjoy it.