Posts tagged WCF

WCF 4 – Loosening the Chains of Configuration

If you have spent anytime in WCF land the first thing you learn about is the joys of configuration.  For the coming release of .NET 4 and WCF 4 the team heard that feedback and has made configuration much easier for the development experience.

Let’s take a look at what’s changed:

Sample 1 – WCF Configuration on .NET 3.5 SP1

  <system.serviceModel>
    <services>
      <service name="WcfServiceConfig35.Service1" behaviorConfiguration="WcfServiceConfig35.Service1Behavior">
        <!-- Service Endpoints -->
        <endpoint address="" binding="wsHttpBinding" contract="WcfServiceConfig35.IService1">
          <!--
              Upon deployment, the following identity element should be removed or replaced to reflect the
              identity under which the deployed service runs.  If removed, WCF will infer an appropriate identity
              automatically.
          -->
          <identity>
            <dns value="localhost"/>
          </identity>
        </endpoint>
        <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/>
      </service>
    </services>
    <behaviors>
      <serviceBehaviors>
        <behavior name="WcfServiceConfig35.Service1Behavior">
          <!-- To avoid disclosing metadata information, set the value below to false and remove the metadata endpoint above before deployment -->
          <serviceMetadata httpGetEnabled="true"/>
          <!-- To receive exception details in faults for debugging purposes, set the value below to true.  Set to false before deployment to avoid disclosing exception information -->
          <serviceDebug includeExceptionDetailInFaults="false"/>
        </behavior>
      </serviceBehaviors>
    </behaviors>
  </system.serviceModel>

By the way, I left out about 100 lines of other configuration “stuff” that had to do with System.Web, etc.

Sample 2 – WCF Configuration for the same service as Sample 1, in .NET 4

<?xml version="1.0"?>
<configuration>
  <system.web>
    <compilation debug="true" targetFramework="4.0" />
  </system.web>
 <system.webServer>
    <modules runAllManagedModulesForAllRequests="true"/>
  </system.webServer>
</configuration>

Notice there is no (none, nada, zero) system.serviceModel element.  That said, if you start your service this way you have one teeny issue:

image

By default WCF disables metadata publishing (security through obscurity) so no one could query your service WSDL to build a client.  In order to do that, you simply need the default code that WCF 4 puts in your config.

Sample 3 – WCF Configuration to enable metadata publishing, in .NET 4

<?xml version="1.0"?>
<configuration>
  <system.web>
    <compilation debug="true" targetFramework="4.0" />
  </system.web>
  <system.serviceModel>
    <behaviors>
      <serviceBehaviors>
        <behavior>
          <!-- To avoid disclosing metadata information, set the value below to false and remove the metadata endpoint above before deployment -->
          <serviceMetadata httpGetEnabled="true"/>
          <!-- To receive exception details in faults for debugging purposes, set the value below to true.  Set to false before deployment to avoid disclosing exception information -->
          <serviceDebug includeExceptionDetailInFaults="false"/>
        </behavior>
      </serviceBehaviors>
    </behaviors>
    <serviceHostingEnvironment multipleSiteBindingsEnabled="true" />
  </system.serviceModel>
 <system.webServer>
    <modules runAllManagedModulesForAllRequests="true"/>
  </system.webServer>
</configuration>

I will certainly be looking forward to the easing of the configuration pains in WCF 4!

Reclaiming Your Identity with Windows Identity Foundation

Windows Identity Foundation is a new framework from Microsoft that helps to solve the identity crisis so many users face with multiple accounts for on-line services, applications, etc.  WIF (dub-eye-eff, not “wiff”), supports the notion of claims-based authentication where a user will authenticate with an external provider and return to your application with a set of claims (in the form of an encrypted token such as SAML) which you then verify and accept.  Delegating authentication is meant to remove the responsibility of authenticating from your application so that it can focus on doing what the app needs to do and not become full of logic to authenticate users.

What’s in a Claim Anyway?

Claims based security isn’t something new.  The idea behind claims is simple.  Users go to a centralized provider where they authenticate and are given a token which contains information about that user; their name, roles, and any other data the authentication store provides.  The user then takes those claims and presents them to the application.  The application verifies the authenticity of the claims and allows the user to access the resources which they are authorized to use.

Real World Claims

The identity problem hasn’t been eliminated in the real-world.  Think about how many cards you carry in your wallet that identify you to some other external party.  You have a drivers license, credit cards, video club cards, etc.  These cards are generally only trusted by the person issuing them.

Since I’ve been doing a lot of flying lately, let’s consider this example.  When you go through the airport now you are required to have a “government issued ID” in addition to your boarding pass.  In the United States alone there are 50 governments responsible for issuing IDs.  You can also print your own boarding pass and each of the airlines format is slightly different.  When you hand your ID and boarding pass to the TSA agent they are not going to verify who actually printed your ID or the legitimacy of your boarding pass.  They are looking for signs of fraud and that the person in the picture resembles the person standing in front of them.

You present the TSA agent your claims (valid boarding pass and government issued ID) and they verify your claims by checking against known signs of fraudulent IDs.

WIF Terms

Claim – Comes from the attribute store for a user.  Typically a key value pair.

Identity Provider – The service responsible for provisioning users & their attributes.

Relying party – The application which will rely on an STS to provide authentication and a token containing claims.

Security Token Service (STS) – The interface of the Identity Provider which allows you to interact with the Identity Provider as a web service.

Token – The “thing” that contains claims to be used by an application. Typically it is an encrypted cookie or xml file.

Getting Started with WIF

To build your first claims aware application you’ll need to grab the SDK here.  To use WIF you need to have IIS installed.  For instructions on installing IIS on Windows 7, check this post.  Included in the samples are several ways you can use WIF.  For this post we’ll look at the PassiveRedirectBasedClaimsAwareWebApp found in {Program Files}\Windows Identity Foundation SDK\v3.5\Samples\Quick Start\Web Application.

To get started with the samples after you installed IIS, be sure to run the SamplesPreReqSetup.bat in {Program Files}\Windows Identity Foundation SDK\v3.5\Samples\Utilities (You must run this “as administrator”)
image 

After running the pre-requisite setup, you need to run the Setup.bat in {Program Files}\Windows Identity Foundation SDK\v3.5\Samples\Quick Start\Web Application and once again be sure to run as administrator.

To test your app just point your browser to https://localhost/WebControlBasedClaimsAwareWebApp/default.aspx.  Log in with your windows account and you should see a page listing the claims in the token.  Note the https; during the pre-requisite setup the scripts will create an SSL cert and enable SSL on your machine. 

Let’s Add a Claim

The STS is located in the PassiveSTS project.  Open App_Code and then the MySecurityTokenService.cs file.  This is the STS implementation.  You can look through the code to get a feel for how the STS works.  To add claims, jump down to the GetOutputClaimsIdentityMethod.  To add a claim use the following snippet:

outputIdentity.Claims.Add(new Claim("http://christopherDeweese.com/Claims/Twitter", "@cdeweese"));

We’ll also need to alter the web applications to support the claim.  The code in the apps will ignore claims it is not expecting.  Open the default.aspx.cs in WebControlBasedClaimsAwareWebApp.  Add the following code near the top where the ExpectedClaims field is defined:

 string[] ExpectedClaims = new string[]  {   Microsoft.IdentityModel.Claims.ClaimTypes.Name,
"http://WindowsIdentityFoundationSamples/myID",
"http://WindowsIdentityFoundationSamples/2008/05/AgeClaim",
"http://christopherDeweese.com/Claims/Twitter"
                                            };

When you browse to the page your output should look something like:

image 

What Just Happened?

Nothing like learning about it by diving in head-first.  When we made our first request to the web app it could not locate our token with the claims and we were immediately redirected to the STS where we were prompted for our logon credentials.  After we were authenticated the STS built an identity which was returned in an encrypted token and we were redirected back to the web app.  This time the web app found our token and allowed us in, displaying the page we see above.

Conclusion

Windows Identity Foundation is a different way to solve your identity problems.  WIF focuses on a model that focuses on how the problem is dealt with in the “real-world”; though we haven’t solved it there yet either.  This will hopefully be part one of many posts that will cover WIF and the good, bad, and ugly of using it to tackle identity problems head-first.

Calling SharePoint Services with WCF and Impersonation

After battling with error 0×80004004 the WCF client I was testing started received a new error.

Could not load file or assembly ‘System.Web.Services, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a’ or one of its dependencies. Either a required impersonation level was not provided, or the provided impersonation level is invalid. (Exception from HRESULT: 0×80070542)

A search yielded this post, which contained some key information.  Interestingly enough, we were seeing the “White Screen” issue on our local instance under similar circumstances: a WCF client calling the list service.

Since the behaviors section is not specifying the clientCredentials, the allowedImpersonationLevel is set to Identification.  This means that the server can get the Identity of the user, but it is unable to impersonate the user.

This was almost identical circumstances to our problem except that we were not running in the context of Biztalk.  The solution was to allow Impersonation by adding an endpoint behavior.

<endpointBehaviors>
  <behavior name="ImpersonationBehavior">
    <clientCredentials>
      <windows allowedImpersonationLevel="Impersonation" />
    </clientCredentials>
  </behavior>
</endpointBehaviors>

Once this was set the service client began working and it was back to the SharePoint dev races.  For more on calling SharePoint Services with WCF check out this post.

Calling SharePoint Services Over SSL with WCF (WSS 3.0)

While troubleshooting another SharePoint WSS issue (related to DCOM permissions) I had to test calling the List Service against an Instance of SharePoint that was running over SSL.  I was using WCF as the client and the biggest pain was the configuration (which is usually the case with WCF).  Based on several other posts, here is what I tried.

1. Added Service Reference which generated configuration info for the service

2. Changed the config and set the security model to “Transport” and clientCredentialType to “Ntlm”.  “Transport” is required when calling over SSL.

    <system.serviceModel>
        <bindings>
            <basicHttpBinding>
                <binding name="ListsSoap" closeTimeout="00:01:00" openTimeout="00:01:00"
                    receiveTimeout="00:10:00" sendTimeout="00:01:00" allowCookies="false"
                    bypassProxyOnLocal="false" hostNameComparisonMode="StrongWildcard"
                    maxBufferSize="65536" maxBufferPoolSize="524288" maxReceivedMessageSize="65536"
                    messageEncoding="Text" textEncoding="utf-8" transferMode="Buffered"
                    useDefaultWebProxy="true">
                    <readerQuotas maxDepth="32" maxStringContentLength="8192" maxArrayLength="16384"
                        maxBytesPerRead="4096" maxNameTableCharCount="16384" />
                    <security mode="Transport">
                      <transport clientCredentialType="Ntlm"/>
                    </security>
                </binding>

            </basicHttpBinding>
        </bindings>
        <client>
            <endpoint address="https://someserver/somesite/_vti_bin/lists.asmx"
                binding="basicHttpBinding" bindingConfiguration="ListsSoap"
                contract="SharePointServices.ListsSoap" name="ListsSoap" />
        </client>
    </system.serviceModel>

3. In code, the only trick I had to use was to AllowNtlm by setting the property on the ClientCredential object.


            using (var client = new SharePointServices.ListsSoapClient())
            {
                try
                {
                    client.ClientCredentials.Windows.ClientCredential 

                 = new NetworkCredential("username", "password", "domain");
                    client.ClientCredentials.Windows.AllowNtlm = true;
                    var lists = client.GetListCollection();
                    var listsXElement = XElement.Parse(lists.OuterXml);
                    Console.WriteLine(listsXElement);
                }
                catch (Exception ex)
                {
                    client.Abort();
                    Console.WriteLine(ex.ToString());
                }
            }

Troubleshooting 0×80004004 in WSS 3.0 (SharePoint)

Today I spent some time working through a few issues with SharePoint and DCOM permissions.  Hopefully this helps another developer on a quest to solve this issue.

If you’ve found 0×80004004 then you are already pretty far along to the solution.  While testing calls to the List service in SharePoint using WCF for the client I received the following error from the List service which I captured by enabling tracing on my WCF client.

<soap:Fault>
    <faultCode xmlns="">soap:Server</faultCode>
    <faultString xmlns="">Exception of type 'Microsoft.SharePoint.SoapServer.SoapServerException' was thrown.</faultString>
    <detail xmlns="">
      <errorstring xmlns="http://schemas.microsoft.com/sharepoint/soap">Operation aborted (Exception from HRESULT: 0x80004004 (E_ABORT))</errorstring>
      <errorcode xmlns="http://schemas.microsoft.com/sharepoint/soap">0x80004004</errorcode>
    </detail>
  </soap:Fault>

Repeated searches on Bing and Google yielded nothing with a direct solution.  But I did find a few pointers that helped my quest.

Digging through program files\common files\Microsoft Shared\Web Server Extensions\12\LOGS I found log files with rows looking similar to this:

w3wp.exe (0×1718) 0×1418 Windows SharePoint Services General 8e2s Medium Unknown SPRequest error occurred.  More Information: 0×80004004

This confirmed the error, but wasn’t helpful.  However, the line just above that was slightly more revealing:

w3wp (0×1718) 0×1418 Windows SharePoint Services Database 6f8g Unexpected Unexpected query execution failure, error code 11.  Additional error information from SQL Server is included below. “[DBNETLIB][ConnectionWrite (WrapperWrite()).]General network error.  Check your network documentation.” Query text (if available): “{?=call proc_GetTpWebMetaDataAndListMetaData( [some values here] ) }

My immediate thought was, “ok, database permissions”.  I was able to locate the stored procedure in question as belonging to the Administration database (SharePoint_AdminContent).  I tweaked a few permissions to no avail.

The project architect suggested I try the same code against a different SharePoint instance.  Sadly, when I tried that the only problem I had to fight was getting the NTLM credentials to work using WCF and SSL.  Things worked flawlessly after that.

With the assistance of our IT pro, he found this article which discusses DCOM permission issues with SP.  Unfortunately we found ourselves unable to change the IIS WAMREG permissions until we found this article which helped us slay that problem.  After taking ownership of the appropriate registry key, we were able to change permissions on the IIS WAMREG DCOM component to allow the SharePoint WPG groups to have Local Launch and Local Activate.

Apparently this issue stems from how the local SharePoint install was configured.  Seems that many people run into this issue when trying to consume SharePoint services on a local machine.

After a reboot and an IIS reset the problem went away.  Sadly, my WCF client received a new error which I will cover in a future post. 

Five Things to Know About the WCF Runtime

Since working with WCF I have gleaned quite a bit about how the runtime works through reading various blogs and writing proofs-of-concept/experiments.  One thing that has become apparent to me is that many people working with WCF do not fully understand how it works because Visual Studio makes it very easy to create & consume WCF services.  In most cases there is no need to understand the “guts” of WCF, but you may reach a point where you want to extend WCF.  Here are five things that will help you know where to begin your quest for extension.

.Svc file are the activators that kick off the WCF runtime.  In IIS or WAS, .Svc files are what activates a service host which in turn creates a service host and calls your service.  The .Svc file specifies the full name of your class and an optional service host factory.  If you are self-hosting a service you are responsible for implementing the same functionality in code.

ServiceHosts control your service instances and dispatch calls to your service using ChannelDispatchers.  The ServiceHost is the central actor and you can control a lot of behavior by altering the service host or extending it.  If you want to use an Inversion of Control container with WCF the best place to stick it is on a custom ServiceHost.  The service host also maintains listeners that enable your service to receive calls over the wire at the specified endpoint (e.g., http://mydomain.com/services/myservice.svc). 

ServiceHostFactory creates a ServiceHost.  If you want to create a custom service host you’ll need a ServiceHostFactory to return an instance of your service host to the WCF runtime.

Everything can be done through configuration or code.  I used to be a huge configuration fan, but after dealing with WCF configuration in .NET 3.5 it can get hairy, especially when you have dozens of services.  Favor code where you can and save configuration for the stuff that could really change.  WCF in .NET 4 has far less configuration, especially in development (which is good because the last thing you want to fight is configuration problems during development of your service).

By default service instances are created per call.  This is typically OK and helps you avoid most threading problems.  Try to avoid creating expensive objects within your services constructor or any of its dependencies as this could delay your services response time.  You can change this using the InstanceContextMode on your service class. Tip: If you are using a container to resolve service instances then you need to remove the InstanceContextMode attribute and let the container manage instances.

(Bonus, a 6th thing to know!) WCF has many extension points, the biggest one being behaviors.  Behaviors allow you to control how the service executes at runtime.  This applies to anything from instancing to message inspection, and much more.  Here are a few posts to get you started:

Put Up your Shields: Shielding Exceptions in WCF Services

When using services an important best practice is to keep details of exceptions from leaking beyond the service boundary.  Letting such details out of the boundary could create unnecessary coupling between the service callers and the service and would expose internal details of the service that you may wish to keep hidden.

Microsoft Patterns & Practices Enterprise Library (EL) provides an extension to the Exception Handling Application Block that hooks directly into WCF to provide the capability to replace service exceptions with custom faults.

Configuring Shielding

Exception shielding requires you to configure a Exception Handling Application Block with an exception policy.  The policy consists of the exceptions you want to handle and a post-handling action for each exception.  To work with the WCF Exception Shielding you need to set each exceptions post-handling action to ThrowNewException.

image

Once you have your basic policy set up you need to add a Fault Contract Exception Handler to each exception in your policy.

image

You can map properties from the exception thrown to the Fault you return.  This is set up in the PropertyMapping as the following screenshot indicates.  Source represents the source property on the Exception and Name is the property name on your fault to map to the source.  In this case the WidgetNotFoundException has a “Message” property which we will map to the “Details” property on our WidgetNotFoundFault.

image

Lastly, you need to mark your Service Class with the ExceptionShielding Attribute and give it the name of your exception policy.

image

Once everything is wired up you can test the service to see your exceptions get replaced by the fault contract types. 

A Quick Integration Test

When I fired up the service in Visual Studio 2010 and used the WCF Test Client, I ran a quick test to find a widget with the name of “Whatzit”.  The service had something to say about that request:

<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
  <s:Header />
  <s:Body>
    <s:Fault>
      <faultcode>s:Client</faultcode>
      <faultstring xml:lang="en-US">Widget Whatzit not found!</faultstring>
      <detail>
        <WidgetNotFoundFault           xmlns="http://schemas.datacontract.org/2004/07/ExceptionShieldingService2"
          xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
          <Details>Widget Whatzit not found!</Details>
        </WidgetNotFoundFault>
      </detail>
    </s:Fault>
  </s:Body>
</s:Envelope>

You can also test this using something like MSTest and decorating your integration test with [ExcpectedException(typeof(FaultContract<MyServiceReference.MyFaultType>)].  Just point the FaultContract<TDetail> to the type from your ServiceReference.  You can’t test fault contracts (to my knowledge) by calling the service imlementation class directly, you’ll need to do this by adding a service reference and calling the service that way.

Tips & Common Errors

After setting up a few of these I have run into some configuration problems which seem to be the most common issue hit with any of the EL blocks.

  • Use the Enterprise Library “Load from assembly” option to select your Exception and Fault Contract types.  EL seems particularly sensitive to using the fully-qualified assembly name including version & public key token.
  • Turn on some type of logging while testing your policy.  This will help you troubleshoot problems with the policy (mismatched types, etc).
  • “The current build operation (…) failed: Value cannot be null” Parameter name: faultContractType – This error stems from EL not being able to resolve your Fault Contract Type.  This is typically due to a bad mapping of your Fault Contract Type.  Check the Type Name, Assembly and version info to make sure it is correct.  Your best bet is to use the EL Config Editor to browse and select your fault type.

What Do You Call It? Naming WCF Operations & Messages

WCF is a great addition to the .NET framework.  Like all parts of the framework it introduces a lot of new concepts to learn.  Sometimes it’s hard to separate those technical concepts from the decisions like, “What is the best way to architect this service” or “How should I name things?”

Simon Segal, a fellow .NET and SOA junkie posted back in November about how he names operations and messages within WCF and the nServiceBus framework (an open-source Enterprise Service Bus).  Simon, like I do, follows a convention of naming in relation to the business events the operations and messages represent.

When it comes to naming operations we not only imply some intent of the operation we also imply what data might be needed.  When designing services that are more coarsely grained you often run into issues with what data is really required for the service to perform its work.  Simon linked to an article from Thomas Erl, a respected authority on SOA, in which Thomas made the following statement (my emphasis):

Although it is practical and extensible, the use of optional parameters should be limited within Web services. Optional parameters can lead to convoluted service interface designs and a myriad of confusing data exchange scenarios. Additionally, the extent to which optional values can be accommodated is often limited by the underlying XML schemas that define the message structures. Standardized schemas that represent established corporate documents may impose rigid data structures.

Coming from the NIEM world I often emphasized that data exchanges only need 80% of what we think is needed.  There were times when people would want to exchange flags or indicators that could be derived from other fields or were not necessarily needed at all.  Any time we strayed away from the 80% the services became more difficult to consume and maintain.

Let’s Look at An Example

Factoring all of this in, let’s consider an example of how we might name service operations and messages.

Definitions:
Service Operation – A method you call on a service. 
Message – An input/output of a call to a service operation.
Message Parts – Data elements that are included in the message.

Problem: You need to name messages and service operations for a service that will allow customers to place orders for widgets.  This service should also allow orders to be cancelled.  Orders consist of a unique ID, a customer Id, and widgets. 

Request/Response example:

  • Service Operation PlaceWidgetOrder, Message: PlaceWidgetOrderRequest, Message Parts: WidgetOrder (Id, Customer Id, Widgets[] (or WidgetCollection))
  • Service Operation CancelWidgetOrder, Message: CancelWidgetOrderRequest, Message Parts: OrderId

Event-Driven example:

  • Service Operation: CustomerPlacedWidgetOrder, Message: CustomerPlacedWidgetOrderMessage, Message Parts: same as request/response example
  • Service Operation: CustomerCancelledWidgetOrder, Message: CustomerCancelledWidgetOrderMessage, Message Parts: same as request/response example

Notice the difference between the two styles.  In the event-driven style we talk about something that has happened (or is happening) and in the Request/Response style we talk in terms of what we want to do.  Each style has it’s merit and the style you choose will depend on the situation and the maturity of the partners involved in the service collaboration/data exchange.

Also notice that the event-driven example does not imply any type of response to the operation.  Typically event-driven systems will be asynchronously designed and the service operations will reflect that.

Why Messages?

Messages allow us to encapsulate the data needed for the domain as well as data we may need because of technical requirements.  Technical requirements may dictate that we have to log messages or protect messages in other ways (which could require message IDs, encryption keys, etc).  By encapsulating data in a message we also leave room to include the technical requirements within the same message and keep our domain model free of technical bits that aren’t really part of the domain.

How do you name your service operations and messages?

Simon and I would love to hear.  Leave a comment or tweet it!

WCF Test Client in VS 2010

The other day I fired up a WCF service for the “Take Control of Messages” post and to my surprise a test client opened up which felt very similar to SoapUI.

Loading & Adding the service reference (happens auto-magically)

image

Double-clicking on a service operation brings up the test form.

image 

Fill out the data elements and press invoke to test the service.

image

The client was also able to support when I transitioned to a message contract. 

image

After selecting the type, you can then expand the element to view it’s members.

image

This is a great addition to VS and will greatly help testing services!

Take Control of Messages in WCF

With WCF you can control many aspects of how service behave and how you interact with them.  Let’s take a look at Data & Message Contracts and how each behaves on the wire.

Data Contracts – The Basics

Data contracts are the default method for serializing in WCF.  To leverage data contracts you simply markup the classes you wish to expose from the service with the DataContractAttribute.  The data contract serializer does not support all the features of Xml Serialization which yields some performance boosts.  However, the data contract serializer has some default behaviors which may not suit your needs.

The Contract

 [DataContract]
    public class CompositeType
    {
        bool boolValue = true;
        string stringValue = "Hello ";

        [DataMember]
        public bool BoolValue
        {
            get { return boolValue; }
            set { boolValue = value; }
        }

        [DataMember]
        public string StringValue
        {
            get { return stringValue; }
            set { stringValue = value; }
        }
    }

The SOAP Message

Request (Showing soap:body only)

<s:Body>
<GetDataUsingDataContract xmlns="http://tempuri.org/">
<composite xmlns:a="http://schemas.datacontract.org/2004/07/ContractExamples" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
<a:BoolValue>true</a:BoolValue>
<a:StringValue>Hello Service!</a:StringValue>
</composite>
</GetDataUsingDataContract>
</s:Body>

Response

<s:Body>
<GetDataUsingDataContractResponse xmlns="http://tempuri.org/">
<GetDataUsingDataContractResult xmlns:a="http://schemas.datacontract.org/2004/07/ContractExamples" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
<a:BoolValue>true</a:BoolValue>
<a:StringValue>Hello Service!Suffix</a:StringValue>
</GetDataUsingDataContractResult>
</GetDataUsingDataContractResponse>
</s:Body>

With the data contract, notice how our messages are actually wrapped in an outer element in the Xml.  For the request, the CompositeType is wrapped in a “GetDataUsingDataContract” element which is derived from the operation name.  The response is where it is interesting, our message is actually double wrapped. 

How do we change this default behavior?  Enter Message Contracts.

Message Contracts – For Control Freaks

Message contracts are another way to work with WCF to take more control of how the messages are serialized in the SOAP envelope.  These can be a key strategy to creating services that can support better interoperability with other stacks such as Java.  You define message contracts with the MessageContractAttribute.

The Message Contract

     [MessageContract(IsWrapped=true, WrapperNamespace=http://christopherDeweese.com/WCF/Examples)]
    public class CompositeTypeRequest
    {
        [MessageBodyMember]
        public CompositeType CompositeData { get; set; }
    }

    [MessageContract(IsWrapped=true, WrapperNamespace=http://christopherDeweese.com/WCF/Examples)]
    public class CompositeTypeResponse
    {
        [MessageBodyMember]
        public CompositeType CompositeData { get; set; }
    }

Here we have defined a request and a response message which contains our CompositeType.  What result does this yield?

The SOAP Message

Request

<s:Body>
<CompositeTypeRequest xmlns="http://christopherDeweese.com/WCF/Examples">
<CompositeData xmlns="http://tempuri.org/" xmlns:a="http://schemas.datacontract.org/2004/07/ContractExamples" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
<a:BoolValue>true</a:BoolValue>
<a:StringValue>Hello Service with messages! </a:StringValue>
</CompositeData>
</CompositeTypeRequest>
</s:Body>

Response

<s:Body>
<CompositeTypeResponse xmlns="http://christopherDeweese.com/WCF/Examples">
<CompositeData xmlns="http://tempuri.org/" xmlns:a="http://schemas.datacontract.org/2004/07/ContractExamples" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
<a:BoolValue>true</a:BoolValue>
<a:StringValue>Hello Service with messages! Suffix</a:StringValue>
</CompositeData>
</CompositeTypeResponse>
</s:Body>

A Little ‘Philosophy’

In past posts on services I’ve discussed the opinion that you interact with services through messages.  Encapsulating inputs and outputs to the service using messages allows for a clearer semantic representation of the what the capabilities the service provides access to.

Using Message contracts in WCF lets you explicitly control how the messages are serialized and allows you to build services from canonical data models created in raw Xml.  This also provides the greatest interoperability and you don’t have to deal with the default behaviors of the data contract serializer.

Final Thought

You may not always need this type of control.  For instance if your service is only being consumed by other .NET clients the messages may not be that important to you.  But if you are designing services for an Enterprise SOA, then message contracts will be a great help.