6/3/2005
thinktecture’s Christian Weyer and Buddhike de Silva
Please download
the sample for a complete implementation.
In a Web services-based world communication is based on public contracts – the technical and partly semantic description of a Web service. The most common kind of contract, the technical interface definition, is today expressed in the form of WSDL. Developers can select either a code-first approach or contract-first approach for creating their contracts. Visual Studio .NET natively supports coding your types and classes and let the ASMX runtime generate the WSDL. There is also a way you can go a code-based contract-first route by using all the necessary attributes from the System.Web.Services and System.Xml.Serialization namespaces. However, schema-based contract-first design is in many cases the better approach because you define the service messages in XML type system of the SOAP standard, not the type system of any given programming language. This approach makes your services more interoperable and emphasizes the fact that a message is fundamentally different from a local class. In that sense it is seems more than natural to define your contract-first and generate the code skeleton for the different platforms and programming languages from it. Generally there are five distinguished steps in contract-first design.

Figure 1: Five steps for schema-based contract-first modelling
Five steps of a schema-based contract-first design approach:
This step involves defining data structures which should be exchanged in messages through your Web service interface.
In this step you define the messages you need to exchange by using XML Schema – ideally with an editor like Altova XmlSpy or the integrated VS.NET XSD editor.
Define which operations you want to offer to the Web service consumer. Operations are made up of message exchange patterns (e.g. one-way or request/response) and their associated messages.
Based on the data, message and interface contracts defined in the previous steps; generate your platform and programming language code as appropriate.
The biggest challenge for schema-based contract-first approach today is lack of modeling concepts and tools support. WSCF’s goal is to fill that gap and simplify schema-based contract-first design for developers and architects. The tool provides a handful of features to help you focus on the important steps, the message and operation design, instead of generating boiler-plate code. WSCF is tightly integrated into Visual Studio .NET 2003 as an add-in, so developers and architects continue to work within their favorite IDE. This document demonstrates how to use WSCF and its features for your Web services.
For this walkthrough we are going to create a Web service for browsing restaurants in your area. It also allows administrators to add new restaurants to the service.
First let’s create a blank Visual Studio .NET solution. We will add our projects into this solution afterwards. The following table shows the projects to add to the solution, the project type and their purposes.
|
Project |
Type |
Description |
|
ContractMetadata |
C# Empty Project |
Contains the metadata definitions for data, messages, and interfaces |
|
RestaurantService |
C# Empty Web Project |
Restaurant Web service implementation |
|
RestaurantClient |
C# Console Application |
Restaurant Web service client implementation |
Table 1: Projects in the sample solution
It is important to note that we do not add a typical ASP.NET Web Service project to our solution, but rather a C# Empty Web Project. This is obvious as we want to omit the automatic and template driven code generation of our Web service code in the first place. Instead, we want to take the contract-first route.
If all three projects are added to the solution, your Solution Explorer window might look like the following figure/ screenshot:

Figure 2: Sample VS.NET solution with empty projects
Now that we have organized our Visual Studio environment, we can start defining our contract. According to the steps we discussed above, our first step is to create an XML Schema which represents the data we want to use. For our RestaurantService Web service, we need two data structures to represent the Restaurant information and a collection of Restaurant information. The following figure depicts our XML schema data defined in a newly added RestaurantData.xsd file to the ContractMetadata project.

Figure 3: Data structures for Restaurant sample
As stated in the previous section, our service allows administrators to add new restaurants to the service. However, we want to allow access only to administrators we trust. Therefore it would be necessary for RestaurantService administrators to submit their credentials for authentication before adding a new restaurant. We want to use SOAP headers to transport the authentication credentials (hopefully over an SSL connection J). Thus we need another data structure to carry our user credentials. Since we want to separate the data structures used in the SOAP Headers from the ones used in the SOAP Body, let’s define the user credentials in a new XSD file called RestaurantHeaderData.xsd.

Figure 4: Header data for Restaurant sample
Next, we are defining the messages to exchange our data. Let’s start by adding a new XSD file called RestaurantMessages.xsd. So far, we have three messages for our RestaurantService Web service. In our case Visual Studio defined the messages as XML elements with embedded (anonymous) complex types. Alternatively we can first model our complex message types and then instantiate them by adding elements of the appropriate types to the message schema RestaurantMessages.xsd. It is very important to note that we have to <import> the XSD file which defines our data structure (RestaurantData.xsd in this case) into RestaurantMessages.xsd. This way we are reusing the XML types we modeled before. In real world projects your data type schemas might already exist in some other context, and you can just add it to your project and reference in the message schema. In our example we simply use the xsd:import mechanism.

Figure 5:
Messages for the Restaurant sample

Figure 6: Illustration of the schema import mechanism for the data structures
As explained at the beginning of this article, interface contracts are expressed as WSDL documents. Obviously we do not want to hand-craft WSDL; nobody wants to because it’s very tedious and at some point staring at all the angle brackets blurs your vision. Even though there are several WSDL editors available, those editors just try to focus too much on the actual WSDL specification. What we need is a higher-level, a more abstracted view on the interface contract.
WSCF comes with its own WSDL generation wizard that tries to hide any suspicious details of the WSDL specification from the developer or architect. This wizard allows you to do all your interface contract creation work just inside the Visual Studio .NET IDE. It hides all the complex details of the specification and generates a WSDL document, which is totally compliant with the interoperability recommendations of WS–I BP (Basic Profile) 1.1.
The latest release of WSCF (version 0.5) allows the user to import multiple schema files to create a WSDL document. Not only that, it also provides a feature to automatically infer operations from your message schema definition. This saves a lot of time you might otherwise spend manually adding operations, even though they could be ‘guessed’ from the message names.
The following table shows the currently supported string patterns for operation inference.
|
Input Message Name Element |
Output Message Name Element |
Inferred Operation Name |
|
XYZ |
XYZResponse |
XYZ |
|
XYZRequest |
XYZResponse |
XYZ |
|
XYZRequestMessage |
XYZResponseMessage |
XYZ |
Table 2: Supported string patterns for operation inference
Last but not least, the wizard enables a simple kind of WSDL round-tripping, which means you can generate a WSDL, review it, and later modify it using the wizard. Let’s take a look at how the WSDL wizard generates the interface contract for the RestaurantService.
To start the WSDL wizard right click on your messages schema file (RestaurantMessages.xsd in this case) in the Visual Studio Solution Explorer and select the “Create WSDL Interface Description” menu item from the context menu.

Figure 7: Starting the Web service interface design Step
The wizard starts with a welcome message. Click on the “Next” button to collect some basic metadata for our Web service description. This includes the service name, the Web service’s XML namespace and an optional description.

Figure 8: Collecting basic metadata for the Web service interface description
The next step allows you to import additional schema files into the WSDL. In our example we have to import the schema file with the type definitions for our message headers, RestaurantHeaderData.xsd. It’s important to keep in mind that you cannot import two schema files which have the same target namespace.
Figure 9: Specifying additional XML schema imports
In step 3 you define the operations in your contract – the meat of this process. However, WSCF’s WSDL wizard is intelligent enough to infer the operations according to message name patterns in your message schemas. Click on the “Infer Operations” checkbox to automatically infer the operations.
Figure 10: Using operation inference
The following step allows you to optionally configure inbound and outbound messages in your operations. In this step you can select the message element for your message body from the schema. However, if you inferred the service operations, message body elements are automatically – and hopefully correctly - configured for you. Optionally you can customize the name for your inbound/outbound message.

Figure 11: Specifying messages and optional properties
The most interesting feature on Step 4 is the Message headers checkbox. When you check that box, you can select schema types for one or more message headers for your inbound/outbound messages from the drop-down underneath the checkbox. In this case we create a message header for addRestaurantIn inbound message to carry our user credentials. Check the “Message headers” checkbox and select Credentials from the dropdown.

Figure 12: Specifying message headers
In the next step you can select whether you want to have the <service> tag in your WSDL. <service> allows you to specify a default location of a Web service that implements the abstract interface you are currently modeling. Also, you can select whether you want to start the code generation immediately after the wizard finishes. The WSDL specification defines <service> as optional, but some Web services frameworks don’t work correctly unless the <service> element is present in the WSDL document.

Figure 13: Specifying additional options
Step number 6 allows you to modify the relative paths of your imported schema files. This may be needed if you have the real XSD files (e.g. for production use) at a different location, e.g. at a URL on a web server.

Figure 14: Changing the paths to the XSDs
Click the “Finish” button on the last screen and you will see the generated WSDL file in your solution explorer. Voila.

Figure 15: Generated WSDL inside the metadata project
For this walkthrough we want to focus on the .NET platform and Visual Studio .NET as our IDE. Thus, we now need to distribute – or ‘deploy’ - the contract metadata to both the client and the Web service developer as shown in the following picture.

Figure 16: Deploying the Web service's metadata to the developers
Now that we have our service contract in place we can start building our service implementation. WSCF comes with a code generation engine for C# and Visual Basic.NET. Let’s start by generating the service-side code first. To start the code generation, we have to right click on the WSDL file in our RestaurantService project and select the “Generate Web Service Code” menu item from the context menu.

Figure 17: Generating code for the service side
This action will bring up the code generation options dialog box which allows you to control the code generation.

Figure 18: Code generation options for the Web service
Since we generate the code for the service, we select the “Service-side stub” radio button in the “General” group box. Various checkboxes in the “Options” group box let you generate the code according to what you actually need. We will take a look at each of those options in a moment. Now it is important to notice that some options are available for both client-side and service-side code generation, whereas some others are only available for client-side or service-side.
Clicking the “Public properties” checkbox commands the code generator to generate property getters and setters for our data fields. For example instead of generating a public field called Name in the RestaurantInfo class (Listing 1), WSCF’s code generation will create a property getter and setter (Listing 2).
|
public class RestaurantInfo { public string Name; } |
Listing 1: Public fields in data transfer object
|
public class RestaurantInfo { private string name;
public string Name { get { return this.name; } set { this.name = value; } } } |
Listing 2: Private fields and get/set properties in data transfer objects
Selecting the “Serializable classes” option will cause the code generator to annotate our types with the [Serializable] attribute (Listing 3). This makes them runtime serializable (by using e.g. System.Runtime.Serialization.Formatters.Binary.BinaryFormatter) as opposed to being just XML serializable by the XmlSerializer.
|
[Serializable()] public class RestaurantInfo { //… } |
Listing 3: Serializable data transfer objects
The “Collections” option instructs the code generator to generate a .NET collection type instead of arrays where necessary. For example, the GetRestaurantResponse class could contain a list of RestaurantInfo objects as an array. By default WSCF would generate an array of RestaurantInfo objects (Listing 4).
|
public class GetRestaurantsResponse { public RestaurantInfo[] restaurants; } |
Listing 4: List-like data as arrays
By selecting “Collections” the code generator produces a strongly-types collection class which inherits from CollectionBase instead of the array. Code generation also switches all array declarations to use the new collection type (Listing 5).
|
// Collection type generated. public class RestaurantInfoCollection : System.Collections.CollectionBase { … }
public class GetRestaurantsResponse { //
Array declaration is modified to use the newly created public RestaurantInfoCollection restaurants; } |
Listing 5: List-like data in generated collection types
The last option in the common list, “Separate Files”, generates types into individual .cs/.vb files. In many situations this will make code organization easier as it generates a separate file for each type. Furthermore it generates AsmxHelpModule.cs, RestaurantService.asmx, AsmxHelpPage.aspx and Web.config files. AsmxHelpModule.cs contains an implementation of an Http module which avoids users from viewing the WSDL by passing “wsdl” parameter to the Service endpoint URL. This Http module is hooked up to the ASP.net plumbing via the configuration settings in the Web.config file. As its name implies RestaurantService.asmx has the ASMX endpoint code. Web.config file contains the configuration settings of the Web Service. For example it will have the necessary entries to avoid accessing AsmxHelpPage.aspx, which contains the implementation for Web Service Help and Documentation page. Since we selected all the common options for service-side code generation our solution explorer will look something like the following picture.

Figure 19: Generated code for the service side
Optionally we could have also selected the “Validate messages” option in the code generation dialog box. This would wire up a custom SoapExtension to the ASP.NET request processing plumbing to validate the messages received by the Web service against our contract schema.
Last but not least, we can specify the desired names for the ASMX file and the .NET code namespace for the generated code by using the “Service filename” and “Service namespace” textboxes, respectively.
We start generating the code for the client side by selecting the code generation option for the RestaurantService.wsdl file in the RestaurantClient project.

Figure 20: Starting up code generation for the client side
This action will bring up the same code generation dialog box we saw earlier when generating the code for the service side. However, this time we are going to select the “Client-side proxy” radio button in the “General” group box.

Figure 21: Code generation options for the client
The behavior of the common options is the same as described in the service-side code generation section. We also have two additional options for proxy code generation. “Configure endpoint” option will generate an entry in the app.config or web.config file to configure the service’s communication endpoint URL.
Optionally we can select the “Access messages” option and access the SOAP messages we exchange with the service through read-only properties on the proxy class.
We can specify the proxy filename and the namespace name for the generated code by using “Proxy filename” and “Proxy namespace” textboxes respectively.
Finally hitting the “Generate” button will output the code and our Solution Explorer will look something like the following picture.

Figure 22: Generated code for the Web service client
It is also interesting to notice that WSCF will generate a new task in the Task List to remind you to configure your actual Web service endpoint.

Figure 23: Task indicating to check the Web service's endpoint in config
Now that we have the skeleton for our code we can continue with our actual service and client implementations. Essentially the service developer will open the code behind file of the .asmx file (RestaurantService.asmx.cs in this case) and implement each of the methods which throw a NotImplementedException. The developer of the client side will instantiate an instance of the proxy class and call its methods in order to communicate with the service. Please download the Visual Studio .NET solution for the complete implementation.
It is quite obvious that nobody in the world will create a 100% accurate contract at the first time. WSCF comes with WSDL round-tripping feature which allows you to modify your existing contracts with the minimum effort. Please note that we are not talking about modifying a published and released contract but rather working in an iterative fashion on one instance of a WSDL-based interface description during development.
Let’s take a look at how we can use this feature in our application. Let’s start adding a new simple data type to resemble the newly introduced rating information into the RestaurantData.xsd file in the ContractMetadata project.

Figure 24: Adding a rating data structure to the metadata
Now we have to change our message schema as well and define a new message to exchange our RatingInfo data.

Figure 25: Updated messages schema for rating restaurants
Our next step is to add a new operation to our interface contract. Again, we do not want to hand-craft the WSDL. This time we use the WSDL round-tripping feature to alter our existing RestaurantService.wsdl file. We can start round-tripping by right clicking and selecting the “Edit WSDL Interface Description” menu item from the context menu.

Figure 26: Starting up WSDL round-tripping
This brings up the same WSDL wizard we used to create our original service description with. However, this time it is pre-populated with the values from the RestaurantService.wsdl file. When we select the “Infer Operations” checkbox in step 3 we can see a newly added operation called rateRestaurant in our operations list.

Figure 27: Interface with update operations list
In step 5 the WSDL wizard forces you to generate the code because if doing any changes in the WSDL means you really should regenerate the code. However, in this case we just omit the code generation as we modify the contract inside the ContractMetadata project.
Now that we have our modified contract we must copy it to the RestaurantService and RestaurantClient projects, respectively. We generate the code for each project like we did in the previous sections. However this time we can select the “Overwrite existing files” option, while generating code for both client side and service side. This will replace the existing files by the newly generated files. Otherwise the code generation will automatically produce unique file names to preserve your existing code.

Figure 28: Overwriting existing code files while generating code
In our demo application walkthrough we saw how straight-forward it is to build our web services with WSCF in a contract-first way. However, in this section we are going to show you some more interesting things that WSCF code generation does for you.
If you take a look at the generated code for our restaurant service application, you will see that the code generation generates a CLR interface for our web service interface. Developers can use this interface and implement it in various layers in their application. For instance, one can take this interface and implement it in an Enterprise Services component which handles the business logic for the restaurant service.
|
public interface IRestaurantServicePort { GetRestaurantsResponse GetRestaurants( GetRestaurants getRestaurants1); void AddRestaurant(AddRestaurant addRestaurant1); } |
Listing 6: Generated CLR interface
Generated code for the service side automatically adds a statement to throw a NotImplementedException from all WebMethods. This ensures that the code compiles successfully and also complies with the .NET Framework design guidelines.
|
public virtual GetRestaurantsResponse GetRestaurants( Namespace= "urn:thinktecture-com:demos:restaurantservice:messages:v1")] GetRestaurants getRestaurants1) { throw new System.NotImplementedException(); } |
Listing 7: NotImplementedExceptions in WebMethods
.NET and XML have unique naming conventions in their type definitions. Usually XML type names use camel casing where as .NET type names use pascal casing. WSCF code generation applies the .NET naming conventions in the generated code and therefore all the generated type names use pascal case.
Unlike WSCF 0.4, the service-side code generation now creates a modified ASMX documentation page. It avoids viewing the WSDL by using “wsdl” parameter in the URL by returning an HTTP 404 error.
WSCF is
also offering a command line interface to the code generation engine (wscf.exe). All code generation can thus be
included in your batch scripts and/or build process. The following screenshot
shows all available options of wscf.exe.

Figure 29: wscf.exe – WSCF’s command line tool parameters
Well, not
everybody will buy the schema-based contract-first approach. This is fine. This
is what we expect. But we surely know out of our own experience and from
customers’ feedback so far: Yes! This is what we are doing since years – and
WSCF just makes it a bit easier.
Thanks.
For
feedback, please send email to the WSCF
team at thinktecture.