Introduction
The Windows Communication Foundation WCF is growing in popularity and becoming the mainstream method for creating web services. While WCF can provide a powerful interoperable service, which many different programs and languages can comminute with, it becomes increasingly important to be able to debug the web service’s action at the raw SOAP XML level. Microsoft provides a built-in tool for viewing WCF log files, although it lacks the simplicity of quickly displaying the raw XML sent to and from the WCF service. Luckily, we can utilize the .NET message inspector to add support for our WCF service to output the complete XML SOAP packets that are sent and received.
In this tutorial, we’ll create a basic WCF web service using plain-text username and password authentication. We’ll bypass using SSL and x.509 certificates to keep things simple. We’ll then add a custom attribute to our WCF class to output all incoming and outgoing XML SOAP packet messages to the Visual Studio Console window.
Creating a Simple WCF Web Service
To start off, we’ll create a basic WCF web service in Visual Studio by choosing the WCF Web Service template to begin a new project. The template will automatically generate a WCF svc class and a service contract interface. To keep things simple, we’ll implement a single method, called SayHelloWorld(), which will accept a composite type of HelloWorldType and return a string. The composite type will allow you to specify a name and a language. The WCF service contract interface appears as follows:
1 | namespace WcfService1 |
As you can see in the above code, our contract is fairly simple. We have a single method for performing SayHelloWorld() and a custom type to help make our SOAP XML a little more interesting. With the interface service contract defined, we can customize the main WCF class as follows:
1 | namespace WcfService1 |
In the code above, we simply examine the HelloWorldType and return a string based upon the name and language. With the initial code setup, we’ll now implement the plaintext username and password authentication.
PlainText Username and Password Authentication in a WCF Web Service
Normally, Windows expects all WCF services to use a security certificate and encrypted password for authentication. While this is certainly the preferred method for communicating over the un-trusted Internet, it is not always viable, especially in development environments or settings where other forms of security may be used.
WCF Authentication with a Plaintext Password
In our example WCF service, we’ll implement a plaintext username and password validation using a custom binding, named ClearUsernameBinding. We’ll actually configure the ClearUsernameBinding within the web.config for the WCF service (and the WCF client). As with any custom WCF authentication, we’ll need to provide a CustomUserNameValidator, as shown below:
1 | namespace WcfService1 |
In the above code, we have a very basic CustomUserNameValidator, which simply verifies the username and password against hard-coded values. You can easily enhance this to validate against a database or other authentication structures.
To use the plaintext username and password validation, you’ll also need to download and add a reference to ClearUsernameBinding.dll in your project.
With the authentication complete, we can move on to configuring the WCF service’s web.config settings.
WCF Configuration Flexibility Comes With a Price
Often, the trickiest part of developing a WCF web service is configuring the web.config settings. For our example, we’ll be adding a custom binding for the plaintext username and password authentication. We’ll also be adding a custom endpoint and service block, along with a custom behavior for usernameauthentication.
1 |
|
The important pieces to the above configuration begin with the binding extension clearUsernameBinding.
1 | <bindingExtensions> |
The above block tells our WCF web service to utilize the plaintext username and password authentication, provided by the custom binding reference. Along with the extension, we’ll also need to provide the binding definition, provided by the following block:
1 | <bindings> |
The remainder of the configuration defines the service behavior, credentials, endpoint, and finally the actual service definition.
Dun Dun Dun Dun Dun .. Inspector WCF!
With our WCF service defined you should be able to run the web service successfully and connect with a client to execute the SayHello() method. We can now move on to adding functionality to output the raw SOAP XML packets sent and received by the WCF service.
Accessing the incoming and outgoing XML SOAP packets can be a bit tricky with WCF, as we need to access a portion of the protocol stack. However, .NET helps ease this by providing the IDispatchMessageInspector interface. Using this feature, we can implement a custom endpoint and behavior extension to pre-process the SOAP message and output it to the console window. We can provide this functionality using the class shown below:
1 | using System.ServiceModel.Dispatcher; |
The first item to note above is the ConsoleHeaderOutputBehavior class, which inherits from the Attribute class. While this class implements the IServiceBehavior interface, to act as a service behavior in the web.config for the WCF web service, it also functions as a class attribute. This allows us to decorate our main WCF service class to provide the SOAP message output functionality.
The meat of the Inspector class is the BeforeSendReply() and AfterReceiveRequest() methods. These two methods pre-process and post-process the SOAP XML packets, allowing us to intercept and peek at the raw content. We can then output the resulting XML, in its entirety, to the Visual Studio Console window, a text file, or any other output method.
Note in the above code, we first make a copy of the MessageBuffer processed by the WCF service. The MessageBuffer contains the SOAP XML, including the header and body of the request or response. However, the body XML content of the SOAP message is further encoded. It’s also important to note that if we were to access the original MessageBuffer’s body content (without first making a copy), the body would be marked as processed and would no longer continue through the web service. Due to this, we first copy the MessageBuffer via CreateBufferedCopy() and then access the message. The message will contain a placeholder text of “… stream …” where the encoded body text is placed. To access the body of the SOAP XML, we call GetReaderAtBodyContents() and then read the outer XML, replacing it back into our output string. We now have the complete SOAP XML request and response for displaying.
The Inspector Needs Some Web.Config Too
With the Inspector class defined, we just need to add it to the WCF web service’s call stack as a custom endpoint behavior. We can do this by adding the following sections to our web.config:
1 | <extensions> |
With the web.config complete, we can finally add our new WCF Message Inspector to our main WCF class, as follows:
1 | namespace WcfService1 |
The above attribute tells WCF to process the custom SOAP message inspector, which will display all incoming and outgoing SOAP messages.
Testing with a WCF Client
A basic client can be developed in Visual Studio by creating a Console Application and adding a Service Reference pointing to the above WCF web service. Since the WCF service uses username authentication, you’ll need to provide a username and password. Upon executing any of the WCF service’s methods, you’ll see the raw SOAP XML packets output to the console window of the service.
To setup the test, first start the WCF service so that it is running. If you are in Debug mode, you can simply close the WCF Test tool to leave the service running in the background. Next, in Visual Studio for the WCF service, click Tools->Attach to Process and choose WebDev.WebServer.EXE (or w3p.exe etc) which is hosting the WCF service. Once attached, you’ll be able to view the console window output.
The WCF client code would appear as follows:
1 | static void Main(string[] args) |
Notice we instantiate the HelloWorldServiceClient and populate the ClientCredentials with a plaintext username and password. We can then execute the SayHelloWorld() method, which will allow us to view the incoming and outgoing SOAP messages in the WCF service debugger.
Note the WCF client will also need a reference to the ClearUsernameBinding.dll and appropriate app.config settings, as follows:
1 |
|
WCF Client Output:
Hello World, Jane Doe!
WCF Service Output:
Received:
1 | <s:Envelope xmlns:s=http://www.w3.org/2003/05/soap-envelope xmlns:u="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"> |
Sending:
1 | <s:Envelope xmlns:s="http://www.w3.org/2003/05/soap-envelope"> |
You can download the source code for this project here.
Conclusion
WCF is a powerful technology for creating interoperable web services. With the growing trend in inter-communication amongst applications, WCF is likely to continue growing and allow an even greater number of programs written in many different programming languages to communicate with one another. While configuration settings and debugging for WCF web services can become complicated, viewing the actual SOAP XML messages received and sent from the WCF service can help boost productivity and track down issues. By implementing a custom WCF SOAP message inspector, we can monitor SOAP messages from within the Visual Studio debug environment and help optimize the creation of future WCF web services.
About the Author
This article was written by Kory Becker, software developer and architect, skilled in a range of technologies, including web application development, machine learning, artificial intelligence, and data science.
Sponsor Me