ServicesResourcesConferences Our TeamWeblogsAboutContact
     
  

Developer Resources

  Architecture Briefings
  .NET Remoting FAQ
  Articles
  Conversations
  Tools and Samples
    DynWsLib
    HttpSysCfg
    GACUtils
    .NET Remoting Projects
  Books

WSCF - Web services Contract-First, for real

Create data and message schema, design WSDL interface contract and generate code from WSDL

by thinktecture's Christian Weyer
Last update: 1/17/2005


In this article I will show you how you can live and breath the concepts of contract-first Web services - all inside your beloved Visual Studio .NET. The contents of the generated WSDL and generated code files will not be shown here - you can easily reproduce those results by following this walkthrough step-by-step - or go with the sample download.

Contract-First Approach

Just to make sure every reader knows about the basic concept of contract-first Web services and all steps involved in it, I am going to quickly recap what it means to design and develop Web services in a contract-first way.

First, there are two ways to do contract-first Web services development:

  • Code-based
  • Schema-based

The first option uses all the XML- and WSDL-related attributes inside the .NET Framework
However, I am a big friend of the latter approach, and therefore developed a tool for the .NET Framework and Visual Studio .NET to easen the schema-based approach to contract-first Web services.

But what do you exactly have to do you when following the contract-first paradigm? There are basically four steps to watch out for:

  1. Model your data.
    This step involves thinking about which data should be exchanged through your Web service interface. This is an explicit view on explicit data. One can think of it as the XML-ized way of defining data transfer objects (but without the object ;)).
  2. Model your messages.
    Write down which messages you will need to exchange the data you hav modeled in the previous steps. These messages will be used in your Web service interface later on.
  3. Model your operations.
    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 - those messages you have designed before, which use the data you have defined in first place.
  4. Generate code.
    Generate your platform and programming language code as appropriate - based on the message and interface contract defined in the previous steps.

So, after a bit of theory, we should get started and dive into the real guts.

Demo Scenario

For the puropose of this article we will take a look at a .NET user group that wants to make some of its member data available to the outside world. There will be a Web service that delivers and accepts data packed in SOAP messages and a client application talking to this Web service.

Visual Studio .NET Solution

First, let's create a blank Visual Studio .NET 2003 solution. We will add our projects to this blank solution afterwards.

Now we need to add our working projects to this solution.
In order to have all needed projects inside our solution we just add an empty C# project for all the contract metadata (i.e. all XSDs and WSDLs). Another project is for the Web service implementation - note we do not add a 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 services code in first place - we want to take the contract-first route. The last project is a C# Windows Forms application to realize a simple client app that consumes the Web service.

If all three projects are added to the solution, your Solution Explorer window might look like the following screenshot:

Modelling the Message Contract

Now let's get ready to rumble. Our first job is to go and model the data and the messages we want to leverage in our Web service. Therefore, we are now concentrating on the Contract Metadata project exclusively.

According to the steps to take in contract-first design, our first step is to create an XML Schema which resembles the data we want to use.
Please add an .xsd file called UGData.xsd to our Contract Metadata project (UG stands for User Group).

As you can see in the next picture we need to add some simple and complrx types to our schema file in order to have all the data in place we need. We have a complex type UGMember, a complex type UGMemberList, and a simple type DotnetExperience. I think the meaning of all data should be quite obvious by looking at the screenshot below (please do not blame me here for not having modeled everything real-world-like...)..

This is the data we will base our messages on. We will reference this data file in a new file where our messages structures will live in.

Please add another .xsd file to our project and name it UGMessages.xsd. Our next task is to model the messages that get exchanged through our Web services interface.

For this simple demo scenario we will have three messages: registerMemberMessage, getMemberDataRequest, and x. Again, I hope that the meaning of these messages are self-explanatory - you can see alle the completely defined messages in the next picture.

Note: in this case I use elements with embedded (anonymous) complex types for defining the messages. Alternatively, I could also first model my complex messages types and then 'instantiate' them by adding elements of the appropriate types.

A very important detail is that the contents of the other XSD file, our UGData.xsd, has to be imported into UGMessages.xsd. This way we are reusing the data we have modeled before (alternatively, your data might already exist in some other context, and you can just add it to your project and reference in in the message schema). For this to happen, we simply use the xsd:import mechanism:

Fine. The first two steps - modeling the data and the messages - seem to be done. Now let's go on to the next big step: defining our Web service's interface.

Modeling the Interface Contract

For this, we do not want to hand-craft our WSDL. Obviously, there are some nice and quite usable WSDL editors out there - but we want to stay inside the Visual Studio.NET IDE and want to have everything integrated. Additionally, it would be very nice and comfortable to hide away all the details of WSDL (1.1) that one really does not need to know and fight with. At last, we want our WSDL to be totally compliant to the WS-I BP 1.0a, which means we have to deal with some rules and guidelines.

Let's take WSCF 0.4 to create the WSDL interface description from our already present message schemas. Simply right-click on the UGMessages.xsd file and choose 'Create WSDL Interface Description...' from the context menu as shown below.

The whole process of creating a WSDL for our Web service is wizard-driven.

In Step 1 we need to specify some metadata for our Web service description. This includes the service name, the Web service's XML namespace and an optional description.

In Step 2 we can finally add all the operations we need to our interface. Simply click the 'Add operation' link button at the buttom of the dialog and add operations as appropriate. For our demo we just need two operations: GetMemberData and RegisterNewMember.

Do not forget to select the correct message exchange pattern (MEP) for your operations. In our case, the RegisterNewMember operation is a one-way operation, whereas the other one is a typical request/response operation.

Before we are finished, we need to map all available messages in our message schema file to our operations. As an example, in the screenshot below we just select registerMemberMessage from the first combobox in order to map the right message to the in message parameter of the RegisterNewMember operation.

Optionally, we could also specify a message header, but we do not need or want one in this case.

Final spurt... the next page of the wizard offers two additional options. Here you can select whether you want to specify where the message schema you are intending to use is located somewhere else, and whether you want to open the code generation dialog right after the WSDL wizard closes.

... and finally we are done.

We now happen to see a newly generated file added to our project: DotnetUserGroupWebService.wsdl - our Web service interface description metadata.

This and the two XSDs are all we need in order to generate code for nearly any platform and programming language.

Code Generation from Contract

For this walkthrough, we want to focus on the .NET platform and on Visual Studio .NET as our IDE. Thus, we  now need to distribute the contract metadata to the client and the Web service developer - as can be seen in the next picture.

Client-side Code Generation

The client and the Web services programmers are totally independent (OK, in our walkthrough everything is contained in one solution- but I think you get it...).

We can start the code generation process for our client by simply right-clicking the .wsdl file we previously created through the wizard and which we received either by copy and pasting it from an email, from UDDI or ... you name it. Choose 'Generate Web service Code...' and off we go with the code generation options dialog.

Select all options as shown in the next picture. As we want to create a client-side proxy class for our Web service consumer, so we just need to activate this option.

All other options are actually optional. They are selected in order to show the power of the code generation engine as it can produce much more usable and productive .NET code than the .NET Framework's intrinsic tools wsdl.exe and 'Add Web Reference...' can do.

After hitting the 'Generate' button, we will see our updated client project. Two new files are generated: App.config and WebServiceProxy.cs

Now it is not very nice to have these two files in a sub folder (actually, the App.config has to be at the project root level). So please move these files to the project root and make sure your project looks like the following:

The Web services endpoint must be configured via an entry in the App.config file - the Visual Studio .NET IDE reminds you of this fact by adding a new task to the task list.

It is fine that we now have the proxy in place for the client app - so now the client programmer can go on and implement all the nice GUI stuff and connect the data from the Web service to its user interface process logic.

Web service-side Code Generation

In the meantime, the Web services developer already started to consume the contact metadata he has been supplied with.

Likewise, he right-clicks on the WSDL and fires up the code generation options dialog.

He selects 'Service-side interface' and chooses to have all the nice code generation features applied to his Web service stub class.

For him, the IDE generates a new task item to remember the developer that the ASMX help and documentation page has been disabled in the web.config file. That means you cannot test the Web service via the built-in mechanisms - and more important: you cannot call ?WSDL on the Web service endpoint.

The following files have been generated by WSCF for a Web service project (which originally was not a Web service project but am empty Web project).

But Visual Studio .NET hides some of the more interesting things from the developer. To see all the files in the project click the 'Show All Files' button right at the top of the Solution Explorer.

So we have four files in total. All we need to do here is move the generated files web.config, WebService.cs, WebService.asmx, and WebService.asmx.cs to the project's root level. Done.

That's it! Schema-based contract-first Web services design and development - for real.
All happens completely inside the Visual Studio .NET 2003 IDE - by leveraging the existing XSD Designer and WSCF adding a WSDL wizard and code generation options to the IDE's feature set.

 






 

© 2002-2006 by Thinktecture, Ingo Rammer and Christian Weyer. All rights reserved. | Contact | Impressum