Web service management using T4 – Web service declaration
As we have seen in the introduction blog post, managing web services can be a repetitive and error-prone task, as it requires many manual steps from the developer. The only parts where he adds some real value to the project are when:
- He defines what the service do (usually by defining the contract)
- He implements the service.
We have decided that we will develop some tools that help the developer and improve his productivity. These tools will be based on an interface in which the developer can manage his web services (CRUD operations). This interface will need a common “model”, an in-memory representation of his web services. This is what we will focus on this post.
Usually, a developer declare web services and operations, he starts by writing the service contract. For simplicity purpose, we will using another way to write what the service is about, in a way that is more inclined to be parsed by a script file: we will describe the web service in an XML file. In order to determine how our XML will be structured, we first have to think about what we want to manipulate and answer to that question : “what is a web service?” (Note: we will use a simplified vision of web services).
The most basic definition of a web service is an entity that has a name (e.g. FileService) and many operations. Each operation has a name, some parameters, and an optional return type. Each parameter consists on a name, and a type.
If we transcript this definition to XML, we could use an xml like this to describe a basic web service that manages upload and download of files.
<?xml version="1.0" encoding="utf-8"?> <WebService Name="FileService"> <WebServiceOperation Name="UploadFile" ReturnType="void"> <WebServiceOperationArgument Name="Filename" Type="string"/> <WebServiceOperationArgument Name="Content" Type="byte[]"/> <WebServiceOperationArgument Name="RelativePath" Type="string"/> </WebServiceOperation> <WebServiceOperation Name="DownloadFile" ReturnType="byte[]"> <WebServiceOperationArgument Name="Filename" Type="string"/> <WebServiceOperationArgument Name="RelativePath" Type="string"/> </WebServiceOperation> </WebService>
We could even encapsulate those WebServices into a WebServiceModel tag in order to be able to describe all services of our solution in one XML file.
<WebServiceModel> <WebService Name="FileService"> <WebServiceOperation Name="UploadFile" ReturnType="void"> <WebServiceOperationArgument Name="Filename" Type="string"/> <WebServiceOperationArgument Name="Content" Type="byte[]"/> <WebServiceOperationArgument Name="RelativePath" Type="string"/> </WebServiceOperation> <WebServiceOperation Name="DownloadFile" ReturnType="byte[]"> <WebServiceOperationArgument Name="Filename" Type="string"/> <WebServiceOperationArgument Name="RelativePath" Type="string"/> </WebServiceOperation> </WebService> <WebService Name="AuthenticationService"> <WebServiceOperation Name="Connect" ReturnType="Guid"> <WebServiceOperationArgument Name="Login" Type="string"/> <WebServiceOperationArgument Name="Password" Type="string"/> </WebServiceOperation> <WebServiceOperation Name="Disconnect" ReturnType="void"> <WebServiceOperationArgument Name="ConnectionID" Type="Guid"/> </WebServiceOperation> </WebService> </WebServiceModel>
Notice that this XML file does not follow an existing standard to describe web services. It was written in Visual Studio without an existing XML schema. Keywords used here are not relevant, nor the fact that it is encrypted in XML. You could switch to JSON, CSV or even SQL database, change all the tag names to translated ones etc. The important part is that now all web services are described in one place in a way that it is easily readable by software. It permits us to use it as a model that a script can load and manipulate to generate outputs. The XML schema used here depends on what you want to achieve, and can be (must be in fact) customized to your needs. For example, if you need (and you probably do) to comment all your web services operations and arguments, just add a “Comment” attributes to your WebServiceOperation and WebServiceOperationArgument tags.
XML is interesting for many reasons. The first is that it is relatively easily readable for the human eyes, really easily readable from C# using Linq to XML, and there are many tools to assist the developer writing it, including Visual Studio. If you give to Visual Studio the right XSD, you can even have some kind of auto completion and validation of the XML.
Instead of managing services through XML, we could even load CLR assemblies via reflexion to find all the exported web service contracts. This can be really powerfull, and I usually go this way. But for simplicity sake, we will keep with the XML approach.