Web Service Interface Design in Practice
Your first want to model the metadata for your Web service's interface. You'll design your data and messages with XML Schema and you'll use Visual Studio's XML editor. You'll set up an initial project structure for your Visual Studio .NET solution. You'll name the empty solution UserGroupService
and you'll add the projects to it in order to complete the sample.
The first project (named ContractMetadata)
is an empty C# project that will just hold all of the original XML metadata files. The second project is a Windows Forms application that implements the Web service consumer (called UGClient
). Last but not least, you'll create an empty ASP.NET Web project. This project will be the home of your user group Web service, but you'll start with an empty project. Please refer to Figure 3
to see the initial solution setup.
Data and Message Contract
In the very first step you need to start modeling the data that you'll use in the service interface. You'll model the data in XML Schema and in this case it consists of simple and complex types. For the purpose of an integrated development experience you'll stay completely inside the Visual Studio .NET IDE and therefore use its intrinsic XSD editor. Listing 1
, the file that contains the data. You can see one simple and two complex schema types in there. The enumeration DotnetExperience
is the simple type, whereas the "structs" UgMember
represent complex types. For those of you who are not too familiar with XML and XSD: imagine those data structures as an XML-ized variant of Fowler's data transfer objects (DTO).
Next you want to define the messages that you'll exchange through the service interface. Those messages will re-use the data structures modeled in the first step. So technically, this means that your schema file UgMessages.xsd
needs an xsd:import
statement for the UgData.xsd
This simple line imports a certain XML namespace into the current document which makes all data types available inside the message schema definition file.
This example uses three messages: RegisterMemberMessage
, and GetMemberDataResponse
(see Listing 2
). Those messages are just loosely placed inside the schema file and do not yet have any correlation amongst them. If you like, they are just raw messages.
|Figure 4: Starting the WSDL Wizard from a message XSD.|
In the third step you'll have to design the actual service interface with its operations. This means you need to map the single messages to operations inside an interface. This phase is obviously the most tedious to complete. Here you won't just use XSD, but rather the quite complex WSDL dialect. Whereas tool support for XSD is extremely good for .NET developers, I haven't found good WSDL editors or designers. This is one of the major reasons why I started to develop and distribute the free WSCF tool. WSCF has a WSDL Wizard component to design the service interface contract of a Web service, as well as enhanced code generation features. Let me now walk you through how to use WSCF to create a WSDL description without having to grok every single detail of this specification or to even handcraft WSDL in Notepad.
In order to get started using the WSDL Wizard you need to add the two existing XSD files for the data and the message types to your contract metadata project. Based on the messages you have designed, you now want to set up the interface. You just have to right-click on the UgMessages.xsd
inside your Visual Studio .NET project and select "Create WSDL Interface Description..." from the context menu (see Figure 4
). The WSCF WSDL Wizard opens with a welcome page. On the following page the user has to provide some basic information about the interface including the name, XML namespace and an optional comment. The next page in the wizard allows you to add additional message XML Schema files. Because sometimes you can start right away with one file, but actually have different kinds of message types distributed across several XSD files (see Figure 5
|Figure 5: Specifying message schema imports.|
Now on to the real meat. Page three of the WSDL Wizard offers a ListView component that allows you to add the interface's operations. For your user group scenario you decide to specify two operations named GetMemberData
. But this is not enough information to complete this step. There needs to be an explicit configuration of the message exchange pattern (MEP) to employ for each operation. Currently, there are two possible values for the MEP: One-Way
. The former expresses that this is a one-shot action, which means you do not want any message sent back to the original sender. The latter indicates that there has to be an answer to the request message (see Figure 6
). If you are following certain naming patterns for the modeled messages, the wizard will be able to infer the operations from the messages. Just like GetMemberDataRequest
will result in the GetMemberData
operation when using inference.
You're nearly done. The last important step lets you specify the operation's message parameters. On this page the user simply needs to map the appropriate message from the message XSD files to the message part of each operation. If you were using operation inference in the previous step the wizard has already set the right values here. Optionally, you can also set any number of message headers on this wizard page. Message headers accord to SOAP headers and you can use them to communicate out-of-band data and information like security credentials or transaction IDs (see Figure 7
). Although there are still some options on the last page of the wizard, you normally do not need them. That's it! Now you should have all the necessary data to actually get the service interface description generated by the tool. When you finish the wizard you have a newly added WSDL file called DotnetUserGroupWebService.wsdl
in your project (see Figure 8
|Figure 6: Declaring the Web service's operations - with operation inference.||
|Figure 7: Configuring message body and headers.||
|Figure 8: Generated WSDL in the metadata project.|
Speaking of the WSDL, WSCF tries to follow the best practices and rules from the WS-I Basic Profile 1.1. For example, it only generates Document/literal style WSDL and creates one portType
per service description (Table 2 lists the features supplied by the wizard). A more thorough look at the generated WSDL (see Listing 3
) unearths a small but very powerful implementation detail. The message schemas are not embedded in the WSDL but rather just imported.
Table 2: WSCF WSDL Wizard's WSDL generation features.
The wizard can infer operations from existing message schema. Based on string pattern matching.
WS-I BP conformance
Generated WSDL conforms to the best practices and rules of the WS-I's Basic Profile.
Existing WSDL files can be edited in the WSDL Wizard.
Multiple XSD imports
Multiple XML Schema message files can be added to a service interface description.
This approach has several advantages. The most obvious one is reusability and the second most obvious is that it lets you independently work on the message schemas and the interface contract. So you can easily use or re-use already existing schema for your service's messages.
All in all this makes three important metadata files. Both the Web service implementer as well as the client programmer will now need to receive the UGData.xsd
files to start their work. You can add all three files to the respective projects for the Web service and the Windows Forms client application. Now you can head into the code generation process.