Share via


Service Station

The Service Factory for WCF

Aaron Skonnard

Contents

The Service Factory Development Process
Getting Started
Data Contracts
Message Contracts
Fault Contracts
Service Contracts and Implementations
Exposing Service Endpoints
WCF Security Guidance Package
Customizing Security Choices
Advanced Customizations
Wrapping It Up

In my last column, I introduced you to the concept of software factories and gave a tour of the new Web Service Software Factory (also known as Service Factory) produced by the patterns & practices (p&p) team at Microsoft. As I explained, a software factory is a collection of guidance assets that help speed up the process of building software using patterns and best practices. Before you read on, if you haven't already, you should check out my December 2006 column so you're familiar with the material.

This month I'll continue exploring software factories with a look at the Web Service Software Factory for Windows® Communication Foundation. Along the way I'll show you how to customize the guidance package, which provides a suite of code recipes that integrate with Visual Studio® 2005 and automate common development tasks.

There are two flavors of Service Factory guidance packages that you can use: one that generates ASP.NET Web services (ASMX) code and another that generates Windows Communication Foundation code. The ASMX version has already shipped on MSDN® while the Windows Communication Foundation version is still under development, as of this writing.

Last time, I looked at the ASMX guidance package but didn't have time to explore the Windows Communication Foundation version so I'll do that here. Be aware that the final details of the Windows Communication Foundation guidance package may change en route to the final release.

The Service Factory Development Process

First, I want to briefly describe the Service Factory development process. The p&p team has adopted a transparent and agile development approach. They ship regular drops to their online community and ask for feedback. But the best feature is how they actually use the community feedback to improve the next version of the product. I've seen first-hand how much influence the developer community can have on the outcome of the p&p deliverables. This adds significant value to developers who want to get involved and ultimately improves the quality of the deliverables, which is a benefit to all.

The other interesting aspect of the development process is how they rely on a reference implementation to drive their work. As illustrated by Figure 1, developing a realistic reference implementation can not only verify the applicability of the recommended practices under consideration but also help discover new practices that would have otherwise been missed. The final set of recommended practices ends up influencing everything that ships with Service Factory including the written patterns, how-to topics, and, of course, the guidance packages.

Figure 1 Software Factory Development Process

Figure 1** Software Factory Development Process **(Click the image for a larger view)

Getting Started

Once you've downloaded and installed the Windows Communication Foundation guidance package, you'll see it show up in the Visual Studio 2005 New Project dialog. You start using the Windows Communication Foundation guidance package by selecting the Windows Communication Foundation Service template and entering a name for your new solution. Then you press OK to launch the recipe that generates the initial solution structure. You'll notice that the initial solution structure is very similar to the one used in the ASMX guidance package.

The most significant differences are found in the service layer. The service layer contains four projects: DataContracts, FaultContracts, ServiceContracts, and ServiceImplementation. This provides a logical structure for organizing the corresponding Windows Communication Foundation artifacts you'll be building. The main change is the project for fault contracts, which is a new concept introduced by Windows Communication Foundation. Another change is that the service host is now placed in the Tests folder.

Remember, if this initial solution structure doesn't fit your exact needs and you'd like to make changes, you can do so by unlocking and reorganizing the solution. Once you've organized the solution to your liking, you can reassign project responsibilities, which essentially tells Service Factory which recipes to make available on each project. I discussed how to do this in my last column.

Now let's dig into some of the changes within the service layer. Implementing a Windows Communication Foundation service layer consists of several steps. First, you define the data contracts that you'll use within messages. Then you model the message, fault, and service contracts that will make up the operations. And finally you implement the service contract and expose the service endpoints.

The Windows Communication Foundation guidance package provides numerous recipes for accomplishing each of these tasks. Within Visual Studio, you can open the Guidance Navigator window (View | Other Windows) and see the various Windows Communication Foundation-specific recipes provided within the Windows Communication Foundation guidance package (see Figure 2).

Figure 2 Guidance Navigator

Figure 2** Guidance Navigator **

Data Contracts

The Windows Communication Foundation guidance package provides a few ways to generate data contracts. In cases where you already have XML schema definitions in place, you can generate data contract types from the XML schema definition (XSD) itself. The recipe is similar to the ASMX recipe called Create XML Serializable type from Schema, only it generates [DataContract] types when possible. The DataContractSerializer in Windows Communication Foundation only supports a subset of the XML schema language so if the schema uses something outside of that subset (like an XML attribute, for example), the recipe will fall back to generating XmlSerializer-compatible types.

When designing new data contracts from scratch, you can run the Create Data Contract recipe, which launches a wizard. The wizard asks you to specify the name of the class as well as the name of the data contract (the XML name) and the namespace. Then you specify the members of the data contract; notice you can specify various [DataContract] details such as Order and IsRequired (see Figure 3). Once you press Finish, a class like the one shown in Figure 4 will be generated.

Figure 4 WinePreference Class

[DataContractAttribute(
 Namespace = "https://CohoWinery.DataContracts/2006/09", 
 Name = "WinePreference")]
public class WinePreference
{
    private string country;
    private string region;
    private string type;

    [DataMemberAttribute(Name = "Country", Order = 1)]
    public string Country
    {
        get { return this.country; }
        set { this.country = value; }
    }
    ... // remaining properties omitted
}

Figure 3 Create Data Contract Recipe

Figure 3** Create Data Contract Recipe **(Click the image for a larger view)

You can also turn existing class definitions into data contracts by using the Decorate type as a DataContract recipe. This recipe automates the process of applying the various [DataContract] attributes on an existing class. There's also a recipe named Validate DataContract that analyzes a selected class to see if it's capable of being serialized by DataContractSerializer.

Message Contracts

Before you can start defining your service contracts, you also need to define the message contracts you'll use within each operation. The ASMX guidance package referred to this task as creating message types. In ASMX, a message type is simply an XmlSerializer type that represents the entire request or response message. If you used such a type with the ASMX unwrapped parameter style, the type itself defines the entire structure of the XML used in the SOAP body.

In Windows Communication Foundation, message types are first-class citizens. You define them with a different set of attributes ([MessageContract], [MessageHeader], and [MessageBodyHeader]). A message contract allows you to model the structure of the entire SOAP envelope. You can specify which fields go in the SOAP header and which go in the body. Message contracts also allow you to specify whether the message should be unwrapped (similar to the ASMX parameter style). Otherwise, Windows Communication Foundation wraps all messages within an element representing the operation name.

Windows Communication Foundation allows you to define operations using either data contract or message contract types. So a common question is when you should use one approach versus the other. The general guidance from p&p is that you should use data contracts anytime you're dealing with a reusable type (say, a type that needs to be used in five different messages). And you should use message contracts when you're defining types that represent request/response messages that won't be reused. Using a message contract also gives you the flexibility to introduce custom header processing down the road so that may also become a deciding factor during design.

If you want to define your message types in terms of data contracts, you can simply continue to use the data contract recipe. If you want to define Windows Communication Foundation message contracts, there is a recipe specifically for that. The message contract recipe walks you through the process of designing a message contract out of existing data contracts, and it generates class definitions with the [MessageContract] attributes.

Fault Contracts

If you plan to return custom SOAP faults to clients, you need to define the types you intend to return within the fault element. In Windows Communication Foundation, you define these fault types using data contract definitions. The data contract models the structure of the XML that will be serialized into the fault detail element. Then you annotate the operation contract with [FaultContract] specifying the detail type. You can apply [FaultContract] to an operation multiple times if it returns multiple fault types.

The [FaultContract] annotations give Windows Communication Foundation enough information to include the appropriate fault information in the service metadata-that is, the XSD and Web Services Description Language (WSDL) definitions, which lets clients generate the necessary client-side code to process the custom faults. This makes it possible for Windows Communication Foundation clients to catch user-defined exceptions using FaultException<T>.

The Windows Communication Foundation guidance package provides a recipe for generating custom faults. When you launch this recipe, it asks you to name the new fault type and indicate whether you want to use the DefaultFaultContract base class (see Figure 5).

Figure 5 DefaultFaultContract Base Class

[DataContractAttribute(
 Namespace="https://FaultContracts/Default/DefaultFaultContract", 
 Name="DefaultFaultContract")]
public class DefaultFaultContract
{
    int errorId;
    string errorMessage;
    Guid correlationId;

    public DefaultFaultContract() : this(-1, String.Empty, Guid.Empty)
    {
    }

    public DefaultFaultContract(
        int errorId, string errorMessage, Guid correlationId)
    {
        this.errorId = errorId;
        this.errorMessage = errorMessage;
        this.correlationId = correlationId;
    }

    [DataMemberAttribute(IsRequired = true, Name = "ErrorId", Order = 1)]
    public int ErrorId
    {
        get { return errorId; }
        set { errorId = value; }
    }

    [DataMemberAttribute(IsRequired = true, Name = "ErrorMessage", 
        Order = 2)]
    public string ErrorMessage
    {
        get { return errorMessage; }
        set { errorMessage = value; }
    }

    [DataMemberAttribute(IsRequired = true, 
        Name = "CorrelationId", Order = 3)]
    public Guid CorrelationId
    {
        get { return correlationId; }
        set { correlationId = value; }
    }
}

The default bass class provides some common error-related fields that you might want to take advantage of in your exception handling scheme. You can also define additional members in the custom fault type. The recipe generates a new data contract type for you, like the one in Figure 6.

Figure 6 New Data Contract

[DataContractAttribute(
   Namespace = "https://CohoWinery.FaultContracts/2006/09", 
   Name = "RegistrationError")]
public class RegistrationError : DefaultFaultContract
{

    private string registrationDetails;

    [DataMemberAttribute(Name = "RegistrationDetails", Order = 1)]
    public string RegistrationDetails
    {
        get { return this.registrationDetails; }
        set { this.registrationDetails = value; }
    }
}

Once you have all of your data, message, and fault contracts in place, you can begin defining your service contracts.

Service Contracts and Implementations

As with data contracts, there are a few ways to define service contracts using the Windows Communication Foundation guidance package. When you already have a WSDL definition that you need to implement, you can run the recipe for generating the service contract from WSDL. This facilitates WSDL-driven scenarios in which collaboration around XSD and WSDL is absolutely necessary.

You can also define new service contracts from scratch by running the Create Service Contract recipe available within the Windows Communication Foundation guidance package. This recipe asks you for the .NET interface name as well as the service contract name (the WSDL name) and the namespace. It also asks you if you want to require sessions on the service contract.

Figure 7 Creating a Service Contract

Figure 7** Creating a Service Contract **(Click the image for a larger view)

Now you can define the operations (see Figure 7). For each operation, you can specify the action, the request and response types (which can be either data or message contract types), the fault types, whether it's one-way, and additional details relating to the session contract when Windows Communication Foundation sessions are being used. Once you've finished defining the operations, the recipe generates a Windows Communication Foundation service contract definition like this:

[ServiceContractAttribute(
    Namespace = "https://CohoWinery.ServiceContracts/2006/09", 
    Name = "ClubMembershipService")]
[ServiceKnownTypeAttribute(typeof(RegistrationError))]
public interface IClubMembershipService
{
    [OperationContractAttribute(Action = "RegisterNewMember")]
    [FaultContractAttribute(typeof(RegistrationError))]
    void RegisterNewMember(RegisterNewMember request);
    ...
}

You can implement this service contract by running the Implement Service Interface recipe. This recipe generates a class that implements the .NET interface representing the service contract and stubs out each method, as shown here:

public class ClubMembershipService : IClubMembershipService
{
    #region IClubMembershipService Members

    public void RegisterNewMember(RegisterNewMember request)
    {
        throw new Exception(
          "The method or operation is not implemented.");
    }

    #endregion
}

If you select XmlSerialzer-compatible types for the request and response types, the recipe will be smart enough to apply the [XmlSerializerFormat] attribute to that particular operation contract. This contract, in turn, instructs the Windows Communication Foundation dispatcher to use XmlSerializer at run time.

Then it's your job to finish implementing each service operation. This is where you can take advantage of the Create Service Contract Translator recipe to generate code that translates between the message types and the business entity types, which is, in fact, the primary role of the service implementation in the Service Factory architecture.

Exposing Service Endpoints

Finally, in order to test the service implementation, you must host it and expose at least one service endpoint. You can accomplish this by using the Expose Service recipe, which is made available to you on the Host project. When you run this recipe, simply specify the name of the service implementation class, choose a binding type, and press Finish. Currently, the Windows Communication Foundation guidance package only provides guidance for the main HTTP bindings (basicHttpBinding and WSHttpBinding). The recipe generates an .svc file, which references the service implementation class, as shown here:

<%@ServiceHost language="c#" Debug="true" 
 Service="CohoWinery.ServiceImplementation.ClubMembershipService" %>

It also generates the <system.serviceModel> configuration shown in Figure 8 within the host's web.config file. You'll notice that the recipe enables WSDL metadata retrieval and a WS-Metadata Exchange (MEX) endpoint by default. Hence, at this point you can browse to the .svc endpoint and view the generated metadata. Then you can also run the Add Service Reference recipe within the client test application. This recipe queries the service using MEX and asks you to choose an endpoint. Then it generates the client proxy code and configuration needed to call the selected endpoint.

Figure 8 Generated ServiceModel Configuration (Web.config)

<system.serviceModel>
  <behaviors>
   <serviceBehaviors>
    <behavior name=
      "CohoWinery.ServiceImplementation.ClubMembershipService_Behavior">
     <serviceDebug includeExceptionDetailInFaults="false" />
     <serviceMetadata httpGetEnabled="true" />
    </behavior>
   </serviceBehaviors>
  </behaviors>
  <bindings>
   <basicHttpBinding>
    <binding name="basicHttpBinding_
       CohoWinery.ServiceContracts.IClubMembershipService">
     <security mode="None" />
    </binding>
   </basicHttpBinding>
  </bindings>
  <services>
   <service behaviorConfiguration=
    "CohoWinery.ServiceImplementation.ClubMembershipService_Behavior"
    name="CohoWinery.ServiceImplementation.ClubMembershipService">
    <endpoint 
       binding="basicHttpBinding" bindingConfiguration=
        "basicHttpBinding_
         CohoWinery.ServiceContracts.IClubMembershipService"
       contract="CohoWinery.ServiceContracts.IClubMembershipService" />
    <endpoint address="mex" binding="mexHttpBinding" 
       contract="IMetadataExchange" />
   </service>
  </services>
 </system.serviceModel>

With Windows Communication Foundation you have a tremendous number of options available to you for the binding configuration, behaviors, and hosting environments. Security is one aspect of that configuration that requires extra attention.

WCF Security Guidance Package

Web service security has a large surface area. WS-Security and the related specifications offer numerous possibilities for securing services with different types of security tokens; this provides for great flexibility but also demands more security-related guidance and automation.

As a result, the Windows Communication Foundation service factory comes with another guidance package for Windows Communication Foundation security. You can enable this guidance package by opening the Guidance Package Manager within Visual Studio and selecting Enable / Disable Packages. Once enabled, you can browse the security-related guidance using the Guidance Navigator (see Figure 9).You'll also find a new context menu named Service Factory - Security when you right-click on the Host project.

Figure 9 Recipes for WCF Security

Figure 9** Recipes for WCF Security **(Click the image for a larger view)

You'll notice there are several recipes available to you that automate the most common security patterns and practices including mutual certificate authentication, Kerberos, and direct authentication using either Windows accounts, SQL Server™, or Active Directory® Application Mode (ADAM) as the identity store. They also provide a secure form of anonymous authentication where messages are protected with a server certificate, but no client authentication is required.

Let's take a look at a common scenario: direct authentication with SQL Server. When you run the recipe, the first thing you'll see is the wizard. The first screen of the wizard describes the security pattern this particular recipe implements and provides a link back to the p&p Web site, which describes the pattern in more detail. The rest of the wizard automates the process of specifying the Windows Communication Foundation endpoint, binding, and behavior details, along with the server certificate to use, the level of message protection required, and the SQL Server role provider details. When the wizard completes, it generates the appropriate Windows Communication Foundation configuration in the Host project's web.config file and it's ready to go. The other security recipes are just as easy to use.

Once you've secured the service, the next time you run the Add Service Reference recipe within the client application, the security settings will be imported into the client configuration and the recipe may ask you for any additional details such as credentials.

This type of security automation is extremely valuable. It allows architects and developers to know that they're following proven security patterns and practices. You can surely expect more advances around security as the Windows Communication Foundation guidance package continues to evolve.

Customizing Security Choices

Although the security recipes do provide valuable automation, developers must still choose the right security recipe in the first place, and once they do, they still have to make quite a few choices while walking through a particular recipe. As an architect, you may want to constrain the set of choices made available to your developers in order to further simplify the process and to enforce your own security standards.

The Windows Communication Foundation security guidance package makes this possible by providing a recipe for modifying the available security settings. If you right-click on the solution, select Service Factory - Security, and then Modify security settings, you'll get a wizard that lets you reduce the set of security scenarios made available to users. For example, if you only want your developers to be able to use Kerberos or X.509 credentials, simply deselect the other options. You can also constrain the message protection level options. If you only want your developers to use the Sign and Encrypt option, for example, uncheck everything else.

Once you're done, the wizard updates your solution configuration and from that point on, only the security options you specified will be made available by the guidance package. For example, if you return to the Guidance Navigator or the Service Factory context menu, only the Kerberos and X.509 recipes will appear in the list. Furthermore, when you walk through one of the available recipes, only the Sign and Encrypt option will appear in the message protection options.

Security choices become very important when you need to ensure interoperability across toolkits. Hence, in order to further simplify common interop scenarios, the Windows Communication Foundation security guidance package provides another wizard that constrains security choices with a specific interoperability scenario in mind. You can launch this wizard by selecting Modify interop settings from the solution context menu.

If your system needs to ensure that all of your Windows Communication Foundation services can be called by Web Services Enhancements (WSE) 3.0 clients without fail, you'd only want your developers to see the Windows Communication Foundation security options that will make that possible. You can accomplish this by selecting the WSE 3.0 | Windows Communication Foundation option, and you can further constrain the security choices around the individual specifications that both toolkits support. Then, next time you run a security recipe, only the specified choices will be made available. Eventually, more interoperability scenarios will be supported (even scenarios like "a Windows Communication Foundation service consumed by a BEA WebLogic Portal 9.2 Client").

Both of these wizards generate a file named SecurityConfiguration.xml that is associated with the solution. This file tells the Windows Communication Foundation security guidance package what options to make available. This file can be redeployed as part of a custom guidance package to ensure everyone sees the same options.

Advanced Customizations

In my opinion, the crown jewel of the Microsoft software factory initiative is the ability to create custom guidance packages for your own organizations. Being able to leverage the common recipes produced by p&p along with your own domain-specific recipes makes for a compelling combination. Automating as many of your common tasks as possible will ultimately result in improved productivity and better quality, consistency, and predictability throughout your organization.

As you've seen in these columns, the ASMX and Windows Communication Foundation guidance packages allow for some simple customizations, such as modifying the solution structure and reassigning project responsibilities, as well as modifying the security/interop settings made available by the package. But for anything more advanced, you'll need to become familiar with the Guidance Automation Toolkit (GAT) and learn how to build and deploy your own guidance packages.

There are several articles and other resources available on the Web that will help you become more familiar with the GAT. However, if you have the Service Factory for ASMX installed, you'll find a detailed document that describes the step-by-step process for creating a new guidance package. It's called "How to: Create a New Guidance Package that Includes your Configuration Settings." If you're interested in this level of customization, be sure to start there.

Wrapping It Up

The Service Factory for Windows Communication Foundation brings valuable guidance assets to the emerging landscape of the .NET Framework 3.0 where guidance is sorely needed. The Windows Communication Foundation guidance will help you more quickly develop Windows Communication Foundation services that conform to accepted security patterns. Look for the official release around the time that the .NET Framework 3.0 ships.

The final version is likely to provide some new features that aren't available as of this writing, such as guidance around contract design (data, message, and service), contract versioning, message validation, deployment, handling large messages, and even patterns around incorporating workflows into your Windows Communication Foundation service implementations. They're also working on a feature that will validate the security settings for a particular service configuration (similar to the WSE Policy Advisor). By the time this column goes to press, many of these features may already be in place.

If you have feedback on what you've seen or would like to provide input on future features, get involved by joining the Service Factory Community on CodePlex. For more information see the "Additional References" sidebar.

Additional References

Send your questions and comments for Aaron to  sstation@microsoft.com.

Aaron Skonnard is a cofounder of Pluralsight, a Microsoft .NET training provider. Aaron is the author of Pluralsight’s Applied Web Services 2.0, Applied BizTalk Server 2006, and Introducing Windows Communication Foundation courses. Aaron has spent years developing courses, speaking at conferences, and teaching professional developers.