Web Service Software Factory 2010 (Service Factory 2010)

kick it on DotNetKicks.com
StumbleUpon.com
Save to delicious Saved by 0 users



The purpose of this post is to demonstrate how to make use of the modeling feature in the Web Service Software Factory 2010 also known as Service Factory 2010 that is produced by Microsoft Patterns and Practices Team to help developers to develop WCF application quickly and consistently that adheres to well known architecture and design patterns. The Service Factory 2010 itself is integrated with the Visual Studio 2010 and provides code generation through the web service modeling.


Preface

There have been months I didn’t come out with any new post after my last post on ASP.NET MVC Framework 2 Execution Process – Part 2. I am still thinking of further my writing on ASP.NET MVC with sample project that’s leverages on the Repository pattern with Entity Framework 4.0 which I have already done but haven't posted on the blog yet. Anywhere, there have been lot of topics and articles on ASP.NET MVC over the net since its inception which you can easily find as references.

I has received an email from one of the reader mentioning about the approaches to be used while developing the WCF application. So, I have decided to write something on developing WCF application using the Service Factory 2010 which was just released on 4 May 2010. I will show the steps to use the service modeling the Service Factory 2010 to produce the necessary projects structures and code skeletons through the respective graphical designer for the service contract model, data contract model and the host model. These three DSL models form the Web Service Domain Model which is the core of the automation components in the service factory.

Before we go on , I will assume that you already have some knowledge on the WCF (Windows Communication Foundation). If you are a newbie, I would suggest you to read this article, Windows Communication Foundation FAQ - Part 1 to get yourself started or you can get a good book on WCF.

A bit of history on the Service Factory. The first version of the Service Factory was released in 2006 and the download on codeplex can be found here. However, it has been deprecated and this version doesn't support the service modeling. This is my first experience with Software Factory from Microsoft. It supports code generation through wizard and the problem with wizard is that if there is any changes in the generated code such as renaming the operation of the generated service, then we have to redo the wizard or to change the name of the generated code. This is not really productive as it is time-consuming to walk through the wizard again. Later, the Service Factory 2008 - Modeling Edition was released in Feb 2008. This version actually takes advantage of the DSL (Domain Specific Language) toolkit that ships with the Visual Studio 2008 SDK Version 1.0 .

Service Factory 2010 is the latest version as of this writing. As usual, this version still has the 3 DSL models but with dependency on the Visual Studio 2010 Visualization and Modeling SDK (previously known as DSL Toolkit). However, you only need to install this if you are compiling against the Service Factory 2010 source code.
 
Requirements for running the sample projects comes with this post are as follow:
You will need Guidance Automation Toolkit 2010 and Visual Studio 2010 Visualization and Modeling SDK if you are building the Service Factory 2010 source code.

This post is not meant to be the complete coverage of the Service Factory 2010 but merely serves as a brief walk through. It is advisable to refer to Web Service Software Factory 2010 chm documentation on MSDN or CodePlex for more further details or if you are in doubt. The Hands on Lab - Building a Web Service (VS2010) is good enough to give you a good start.

As usual, I will make use of the sample projects for my previous post on Repository, Specification, Unit of Work, Persistence Ignorance POCO with Microsoft ADO.NET Entity Framework 4.0 Beta 2 - Code Update as the resource access and business layers for the demo application that will expose the Create, Read, Update, Delete operations on the Northwind database's customer table as WCF services.

Using Service Factory to create web service enabled solution is about designing with the Models (Service Contract, Data Contract and Host) then followed by choosing the required technology either ASMX or WCF available from the Service Factory. Finally, the projects and codes are generated into them. It is assumed that you have some working knowledge on WCF and this walk through focuses specifically on WCF. Here we go.



Service Contract Model

First we are going to build our service contract for our Northwind's Customer. So we are going to add the service contract model into our sample solution. Service contract model allows us to perform a number of activities such as defining Service Contracts, Operations and Messages. In WCF, we use the System.ServiceModel.ServiceContractAttribute to mark interface or class that will be exposed as service. The practice is to use Interface as it represents a contract without implementation and it makes more sense as the party who consumes our service is more interested to know about the contract instead of the implementation. It represents what a service endpoint communicates to the outside world. At the lower level, a service contract consists of  logically related operations that exchange messages. Each of this operation is marked with the System.ServiceModel.OperationContractAttribute in WCF. Only the operation that is marked OperationContractAttribute is exposed to the outside world. The pattern of the message exchange (MEP) can be request/reply, one-way or duplex. Since operation exchanges message, we need to define the message types and the data types the message carries. The activities in service contract modelling revolves around defining service contracts, operation and messages. Let start creating the Service Factory enabled solution, make sure you open the Visual Studio 2010 in administrator mode if you are on Windows Vista/7.



Figure 1.1 Creating the Service Factory Enabled Solution from Scratch.

Here we create the Project Solution from scratch. Navigate to File --> New --> Project, then you will see be prompt the new project form. Under the Installed Templates, go to the Guidance Packages, you will see the Web Service Factory 2010(C#) solution template if you have successfully installed the Web Service Factory 2010.  I have chosen the MyCompany.Service.Model.AppName as my solution name under the directory :\\Blog\MyCompany\Branches\Source\ServiceProject\Source. The service name as a prefix to the Model in the solution name indicates this is a service modeling solution for a project AppName under MyCompany. Anyway, it is up to you to use your own convention that make sense to you. Click OK, once you have filled in the name and the location to create your solution. Figure 1.2 show the solution layout, project and files created by the Service Factory.



Figure 1.2 Initial Solution Layout, Project and Files

Service Factory will create a project with the name, MyCompany.Service.Model.AppName.Model. Since Service Factory appends the Model suffix again, I have to rename it manually back to MyCompany.Service.Model.AppName to meet my need. This is the project where you will need to place your models (Service Contract Model, Data Contract Model, Host Contract Model). There is a ProjectMapping file under the Solution Items folder. It decouples the model from the projects. In other words, you can customize this file to control the way it unfolds your solution structure which we will see in the later section.

Let get start designing the service contract. Right click on the MyCompany.Service.Model.AppName project --> Add --> New Service Contract as shown in the following figure 1.3.



Figure 1.3 Create a New Service Contract Model

Let name the service contract model as CustomerService. Service Factory will prefix your service contract file with the .servicecontract extension. So, by looking at the extension, you will know it is a service contract model file. After specifying the service contract name and click the Add button, we are presented the service contract design surface as in figure 1.4 where you actually can model the service contract, operations and the messages that make up your single service.



Figure 1.4 Service Contract Design Surface with the Available Tools

To view the tools available for the service contract model, you can access the toolbox when the service contract design surface is open through View --> Toolbox (Ctrl + W , X). From the figure 1.4, we have Connector, Message, Operation, Service Contract, Service and XSD Message in the toolbox.

The Connector shape as its name implies is used to make valid connection between the shapes on the design surface to show and establish their relationships. The Message shape represent a request or response related to a single operation. It contains the data contracts and primitive types (except those from XSD schema file). The Operation shape represents the method that can be invoked on a service. The Service Contract shape represent the service interface which can have multiple operations. The Service shape represent the actual implementation of the Service Contract. Finally, there is this XSD Message shape. The Message and XSD Message shape both represent a request or response. But XSD is used to represent the complex type found within the XSD schema file.

Before adding the shapes on to the design surface, let change the XML namespace for the Service Contract Model. This can be done by right click on the design surface of the service contract model to bring up the properties window. I have set the  XML namespace to http://www.kitchaiyong.net/service/northwind/2010/06, so when the new shapes are added to the model later, they will share the same URI namespace.

Let add four Operation shapes onto the design surface by dragging the Operation shape from the toolbox. They provides the Create, Read, Update and Delete operation respectively on the customer through the Customer Service Contract. They are named Create, GetById, Update and Delete respectively through the properties window of the Operation Shape. As you type the name for the Operation shape, the value of the Action property changes accordingly. Figure 1.5 shows the 4 completed Operation shapes on the design surface.

Also, the data contract fault, CustomerNotEstablishedFault  is added to each Operation shape. The data contract fault is used to communicate the error processing information occurs in the service to the client. Not all error processing information needed to be communicated back but those that are meaningful and important to the client. In order to have the error processing information related to the CRUD on the customer object that cannot be performed, we need a custom type or data structure that can be serialized and deserialized. So that the error processing information can be transferred to the client in custom SOAP fault. This is where the System.Runtime.Serialization.DataContractAttribute to decorate the type and System.Runtime.Serialization.DataMemberAttribute to decorate the type's members/properties as serializable come into play. The service operation that may communicate the error condition in a custom SOAP fault part of the method invocation will have its method signature decorated with the System.ServiceModel.FaultContractAttribute and the custom fault type (CustomerNotEstablishedFault) is passed as argument. So, the client will know the operation contract throws declared SOAP fault of type CustomerNotEstablishedFault and will be able to handle it in its try catch block. It is called declared SOAP fault because the custom SOAP fault type (CustomerNotEstablishedFault) is specified in the FaultContractAttribute of the operation contract. Undeclared SOAP faults are those not being specified in the FaultContractAttribute and is generally used for the debugging and diagnostic purpose.



Figure 1.5 Operation Shapes on the Service Contract Modeling Design Surface.

Next, we drag the Service Contract shape and give the value of CustomerServiceContract for its name property through the properties window shown in figure 1.6



Figure 1.6 Service Contract Shape on the Service Contract Modeling Design Surface.

Next, we drag the Service shape and give the value of CustomerService to the name property through the properties window shown in figure 1.7. This Service shape actually represents the real implementation of the Service Contract shape.



Figure 1.7 Service Shape on the Service Contract Modeling Design Surface

Now we are going to link up the Service, Service Contract and Operation shapes with the Connector shape. First, we drag the connector from the toolbox and connect the CustomerServiceContract to each of the Operation shape one by one. As you make the connection, the Service Contract property of the Operation shapes (Create, GetById, Update and Delete) will be populated with the value of the Name property of the Service Contract (CustomerServiceContract). Alternatively, you can select from the drop down values of the Service Contract property of the Operation shape to associate its with the Service Contract shape (CustomerServiceContract) and a connector shape will be automatically made to link up both the Service Contract and the Operation shape.

We also do the same for the Service (CustomerService) and Service Contract (CustomerServiceContract) shape and the Service property of the Service Contract (CustomerServiceContract) shape will be populated with the value of the Name property of the Service (CustomerService) shape and the Service Contract property of the Service (CustomerService) shape will be populated with the value of the Name property of the Service Contract (CustomerServiceContract) shape. At the end we will have something shown in figure 1.8.



Figure 1.8 Connector Shapes applied to the Service, Service Contract and Operation Shapes

Finally, we have to define the message types for the operations that we have associated to the service contract. If you follow the Web Service Software Factory 2010 chm guide or the hand on labs, after each operation shape is added, the request and response message type is added if any. I prefer to do it last here.

Drag a Message shape from the toolbox and place it on the design surface and set its name property value to CreateCustomerRequest to indicate this is a request message for Create operation. Right click on the Message shape to add a new data contract message part as shown in figure 1.9 and give the name, Customer to the message part.



Figure 1.9 Add New Data Contract Message Part

To establish a request relation between the Create operation shape and the CreateCustomerRequest Message shape, click the connector shape on the toolbox and then drag the connector from the CreateCustomerRequest Message shape to the Create Operation shape. The direction you drag will determine whether the Message shape is a request or response message. In other words, if the direction flows from the Message shape to the Operation shape then it is a request message and if the direction flows from the Operation shape to the Message shape then it is a response message.

We repeat the same processes for the request and response messages for other Operation shapes on the design surface until we are done in figure 1.10. Notice the arrow of the connector for the request and response message.



Figure 1.10 Complete Service Contract Model

We can save the service contract model. During the save, service factory will try to validate the service contract model and report back with validation errors. At this point, we can just ignore whatever the errors and confirm the save operation. These errors will be eliminated once we have defined our data contract and specifying the implementation projects we want later.

Before we go on further, I would like to highlight that the Service Factory by default use the message contract (System.ServiceModel.MessageContractAttribute) in WCF to exchange messages through the operations on the service contract. WCF itself supports operations modelled on RPC - Remote Procedure Call or messaging style. In RPC style, developers can use any serializable types in any numbers in the operations without concerning on how the data are being carried in the SOAP message. So, the form of serialization will depend on the operation parameters which will determine how the structure of the data carried in the SOAP message that will be created by the WCF runtime to support the operations. RPC style is what most developers are familiar with because they don't need to concern about the message structure. Data contracts and .NET primitive types are what they need in the operation's parameters.

Message style gives developers better controls on the structure of the SOAP message but there is only one parameter and one return value allowed from the operation. Since message contract is used as parameter to the operations defined on the service contract, then the operation has at most one parameter and one return value because they serialized directly into a SOAP message structure. Both the request and response message types must be either decorated with the System.ServiceModel.MessageContractAttribute or it is of type Message. Within the message contract, we can include our data contract message part (message whose type is decorated with the System.Runtime.Serialization.DataContractAttribute) and primitive message part (message whose type is .NET primitive type such as int, byte, string and etc which are inherently serializable whereby you don't need to decorate them with attributes such as DataContractAttribute to tell .NET it is serializable because .NET knows how to handle their serialization and deserialization). The rationale behind using the message contract is that it allows us to exercise better control on the resultant SOAP message structure for interoperability and security reasons. The SOAP message itself consists of the message header and message body. Through the System.ServiceModel.MessageHeaderAttribute and System.ServiceModel.MessageBodyMemberAttribute we can control where a particular element of data belong to. This is useful when we have to integrate with different SOAP application which has requirement on where a particular element of data should go to. Please click Using Message Contracts for more information on RPC style and messaging style.

In WCF, there are numbers of way we can actually use to describe the messages that are exchanged through the operations on the service contract. To know more about this, you can follow the MSDN link, Specifying Data Transfer in Service Contracts. WCF uses Data Contract Serializer as its default serialization engine to convert data into XML data and vice versa.



Data Contract Model

The main purpose of the data contract model is to model the data types for the message part(s) we have added into the Message shapes on the design surface of the service contract model which we have completed prior to this. Just to remind you that we only need to model the data type for the data contract message part. The type that make up the data contract message part is really a custom/user defined type that need to be decorated with DataContractAttribute to make it a serializable type. There is no need to model the primitive message part which is only formed by the .NET primitive type.

Let create a new data contract model through Solution explorer --> Right click MyCompany.Service.Model.AppName --> Point to Add --> New Data Contract as in figure 1.11. Let name the data contract model name to CustomerService.datacontract when the Add New Data Contract dialog prompts as shown in figure 1.12


Figure 1.11 Create a New Data Contract Model


Figure 1.12 Add New Data Contract Model Dialog

After Add button is clicked, we are presented the data contract model design surface. Before we start adding new shapes to the design surface, let set the value of XML Namespace property of the data contract model design surface to URI, http://www.kitchaiyong.net/service/northwind/2010/06 which is same as what I have set for the XML Namespace property of the service contract model design surface. Any new shapes that are added to the design surface will share the same URI namespace. The properties window for the data contract design surface can be brought up by right click on the design surface and click properties.

 

Figure 1.13 Data Contract Model Design Surface and its Toolbox Shapes

From the toolbox you can actually see a number of shapes which are actually used to define serializable types that can be shared and reused across services and operations in your service enabled solution.

Aggregation - To define aggregation relationships between data contracts.
Data Contract Collection - To define a serializable collection type.
Data Contract Enumeration - To define a serializable enumeration type.
Data Contract - To define a serializable type.
Fault Contract - To define a serializable SOAP fault type.
Primitive Data Type Collection -To define a serialization collection type of a primitive type.

Let start by dragging a Data Contract shape from the toolbox to the design surface and set the value of its Name property to Customer. This is the data contract that will be finally associated with the data contract message part, customer for all the Message shapes we have defined in our service contract model. We are going to add some properties/members for this customer data contract shape. On the Customer data contract shape, right click on it and click Add New Primitive Data Type and then name it CustomerId as shown in figure 1.14


Figure 1.14 Customer Data Contract and its Members, CustomerId

If you notice from the properties window of the CustomerId, a primitive data type member will always be default to the System.String. Since this is the .NET primitive type I want, just leave it as it is. If you want to associate a different .NET type, then you can click the
button next to the property to bring up the Browse and Select a .NET Type dialog as shown in figure 1.15 to associate the .NET type you want.



Figure 1.15 Browse and Select a .NET Type Dialog

From the properties window in figure 1.14, you will also notice that the Is Data Member property of  the CustomerId member will always be default to true. This will ensure the CustomerId is serializable in the final code generation. You will find in the final code that the CustomerId data member of the Customer data contract decorated with System.Runtime.Serialization.DataMemberAttribute. It will look something like this,


Customer Data Contract

In .NET framework, there are 2 message design approaches being supported namely, implicit message design and explicit message design. Please don't confuse these with the RPC style and messaging style which I have mentioned earlier.

In the implicit message design, the developers are not required to specify each public property needed to be serialized except those need to be excluded from the serialization. This approach has its root in XmlSerializer. This is the serializer for object to XML (serialization) and XML to object (deserialization) that we have been working with before the inception of DataContractSerializer in .NET framework 3.0. In order to exclude a property from serialization, it is must be decorated with System.Xml.Serialization.XmlIgnoreAttribute. So, that the XmlSerializer won't include it in the serialization process. In the world of .ASMX web service, this serializer has played a vital role in the XML serialization and deserialization. Please click using the XmlSerializer for more information.

With the advent of System.Runtime.Serialization.DataContractSerializer in .NET framework 3.0 and WCF in particular, it has made the XML serialization explicit whereby you have to explicitly decorate each property that you want to include in the serialization with the System.Runtime.Serialization.DataMemberAttribute . So, those you want to exclude from the serialization can be left alone. You can even apply this attribute to any field and property regardless of their access modifier. DataContractSerializer supports the types supported by XmlSerializer except the System.Xml.Serialization.XmlElementAttribute and System.Xml.Serialization.XmlAttributeAttribute which are commonly used in the .ASMX web service. If your serializable types contain properties decorated with these two attributes, then XmlSerializer is the best bet. To know the complete list of types that can be serialized and deserialized by data contract serializer, see Types Supported by the Data Contract Serializer.

If you want to know more on the comparison between XmlSerializer and DataContractSerializer, you can follow Dan Rigsby's XmlSerializer vs DataContractSerializer: Serialization in Wcf.

Let continue our data contact model. After adding CustomerId, we continue to add new primitive data type member for Customer data contract which includes CompanyName, ContactTitle, Phone and Fax of which they all belong to System.String type.

We add another data contract enumeration by clicking it on the toolbox and click it again on the design surface. We name it CustomerType. On the CustomerType data contract enumeration shape, right click on it and click Add New Value. We are going to add Good, Normal and Vip for the enum values. This CustomerType data contract enumeration is added for the purpose of demonstration. In fact, this CustomerType is not found in the Northwind's Customer table.

To make the CustomerType data contract enumeration part of the Customer data contract, we are going to use the Aggregation shape. Click on the Aggregation shape on the toolbox and drag it from the CustomerType data contract enumeration to the Customer data contract. This will make the CustomerType enumeration as a member of the Customer data contract as shown in figure 1.16.



Figure 1.16 Customer Data Contract and CustomerType Data Contract Enumeration

For the purpose of the demonstration, we add another data contract called, CustomerAddress with the following primitive data type members; Address, City, Region, PostalCode and Country. They are all of the System.String type. We click the Aggregation shape on the toolbox to establish a relationship between Customer and CustomerAddress contract by dragging the Aggregation shape from the CustomerAddress to the Customer data contract shape. This will make the CustomerAddress appear as part of the Customer data contract shape as shown in figure 1.17. If you drag the Aggregation shape in reverse order from the Customer to CustomerAddress data contract shape, then the Customer will be part of the CustomerAddress which is logically wrong.



Figure 1.17 Customer and CustomerAddress Data Contract Relationship

Let add another data contract collection. Click the Data Contract Collection shape on the toolbox and click it on the design surface. We name it CustomerCollection instead of Customers because it is a message type collection instead of property of a message type. Right click the CustomerCollection data contract collection shape to bring up it properties window and set it values of the Data Contract property to Customer from its drop down as shown in figure 1.18. Once the Customer value is selected, an arrow connection will automatically point from the Customer data contract shape to the CustomerCollection data contract collection shape to show their relationship.


Figure 1.18 CustomerCollection Data Contract Collection

Finally, we are going to add a fault contract for our custom SOAP fault type, CustomerNotEstablishedFault. Click the Fault Contract shape on the toolbox and click it again on the design surface. We name it CustomerNotEstablishedFault. We add two primitive data type members namely, Description and ProblemType which are of System.String type to CustomerNotEstablishedFault fault contract shape as shown in figure 1.19.



Figure 1.19 CustomerNotEstablishedFault Fault Contract

We are done for the customer data contract model. At this point, we can save the model and ignore whatever validation errors being presented to us.

Reminder : If you want to reference another data contract which reside on different data contract model file, right click the data contract shape you want to associate/reference another data contract, then click Add new Reference Data Type and give it a name, let say Example. Right click the Example member to bring up the properties window as shown in figure 1.20. Click the button next to the Type property in the properties window to bring up the Create reference to element dialog as shown in figure 1.21 to import the data contracts from different data contract model file you need.



Figure 1.20 Reference Data Contract from Different Data Contract Model File



Figure 1.21 Create Reference to Element Dialog to Import Other Data Contract from Different Data Contract Model File



Wiring up Dependencies between Service Contract and Data Contract Model

After completing our service contract and data contact model. It is time to wire up the dependencies that exist between these two models. If you still remember that in our service contract model, we have some of our message contracts having the customer data contract as part of the message. In the mean time, we have the service operations to possibly throw the custom SOAP fault, CustomerNotEstablishedFault in the event of error occurs in the service operation to communicate back the error processing information to the caller. Both the Customer data contract and the CustomerNotEstablishedFault fault contract need to establish a relationship with the data and fault contract type that we have defined in the data contract model.

To associate the customer data contract message part in the messages in the service contract model to the Customer data contract type in the data contract model, right click the Customer data contract message part to bring up the properties window. From the properties window, click the next to the Type property to bring up the Create Reference to Element Dialog to import or reference the Customer data contract type from the CustomerService data contract model file. This is the same dialog that has been mentioned previously in importing/referencing data contract from other data contract model file. We also do the same for the CustomerNotEstablishedFault data contract fault in the service operations in the service contract data model to the CustomerNotEstablishedFault customer SOAP fault type in the data contract model using similar step explained for the Customer data contract.

Now we can the save customer service contract model and ignore whatever validation errors messages being presented to us. The common errors encountered here are the implementation technology not set for the service and data contract model, the project mapping table property is empty and reference to a data contract model with empty or inconsistent implementation technology or project mapping table associated. Later, once we have associated the implementation technology (WCF or ASMX) and have created the implementation projects, these error messages will be gone.



Choosing Implementation Technology for Implementing the Services

Now, we have already had a complete service interface (service and data contract model) and lack only the technology to implement the service. From here, we can actually see that the service and data contract model are actually technology agnostic because these two DSL models are not bound to any particular technology. In fact, we are able to delay the implementation technology until this point by completing the service and data contract model which should be completely decoupled from the technology dependent elements.

Service factory offers two kind of technology implementations namely, WCF and ASMX. We will be using WCF.

To associate the WCF implementation technology with the service and data contract model, right the design surface of the mode to bring up its properties window, select the WCF extension value associated with the drop down for the Implementation Technology property as shown in figure 1.22



Figure 1.22 Choosing the Service Implementation Technology (WCF)


We repeat the same step as well for the data contract model.

Once the WCF implementation technology is chosen, the WCF properties specific to each kind of shape in the service and data contract model will appear in its properties window. To verify this, we can right click the CustomerService service shape to bring up its properties window as shown in figure 1.23.



Figure 1.23 Two Additional WCF Specific Properties for the CustomerService Service Implementation Shape


The highlighted Concurrency Mode (System.ServiceModel.ServiceBehaviorAttribute.ConcurrencyMode) and Instance Context Mode (System.ServiceModel.ServiceBehaviorAttribute.InstanceContextMode) are WCF properties specific to the service behavior which are applied at the service implementation type.

Other WCF specific properties such as the Protection Level and Session Mode(System.ServiceModel.ServiceContractAttribute.Sessions) are also being added to the CustomerServiceContract service contract shape are highlighted in figure 1.24. These two properties are applied at the service contract type through passing arguments to the System.ServiceModel.ServiceContractAttribute.  There are various interactions among the Sessions, Instancing and Concurrency in WCF.



Figure 1.24 Two Additional WCF Specific Properties for the CustomerServiceContract Service Contract Shape

Let look at the WCF properties specific to the service operation shape. Right click on any of the operation shape to bring up its properties window as in figure 1.25. The highlighted are WCF properties specific to the service operation. These properties are passed as arguments to the System.ServiceModel.OperationContractAttribute.



Figure 1.25 Additional WCF Specific Properties for the Operation Shape

We need to set the Reply Action property (System.ServiceModel.OperationContractAttribute.ReplyAction) to have the same value as the Action Property. The Reply Action property is left blank by default after we have chosen our implementation technology. The rest of the properties; Async Pattern (System.ServiceModel.OperationContractAttribute.AsyncPattern), Is Initiating (System.ServiceModel.OperationContractAttribute.IsInitiating), Is Terminating (System.ServiceModel.OperationContractAttribute.IsTerminating) and Protection Level (System.ServiceModel.OperationContractAttribute.ProtectionLevel) can be left as it is. You need to configure these properties yourself for your own application specific need.

Again, we need to set the Serializer Type property of the service contract model to DataContractSerializer. Since, we are not referencing any type from the XSD schema file that has XML element and attribute or referencing types generated by XSD, then we are very sure that DataContractSerializer is compatible.

Finally, we need to switch to the data contract model to set the Collection Type property of the CustomerCollection data contract collection. There are three collection types to choose from. Generic List, Generic Collection and the Generic Dictionary. In this, just choose Generic List from the drop down as in figure 1.26.


Figure 1.26 Data Contract Collection's Collection Type Property

This property will set the .NET collection type to derive your data contract collection. The final data contract collection type in the final code generation will always be decorated with the System.Runtime.Serialization.CollectionDataContractAttribute. Please click Collection Types in Data Contract for more information on how data contract collection work in WCF.

The very last is to order all data members. Each data member that is required to be serialized and deserialized before one another must have a unique order no for the System.Runtime.Serialization.DataMemberAttribute.Order property. Since each data member will have a default value of 0 for the Order property after we have chosen the WCF implementation technology for the data contract model, we have to make sure that their order nos are unique within each data contract shape. Setting the order no one by one for each of the data member of the data contract shape will be troublesome. Luckily, service factory provides the Order All Data Members function which you can access from the pop up menu by right click on the design surface of the data contract model as shown in figure 1.27.

 

Figure 1.27 Order All Data Members

Forget to order all data members will result in the error as in figure 1.27.



Creating WCF Projects

After we are done with the service contract and data contract model, it is time to generate the solution structures for our service application. Service factory generates service interface layer projects including the codes for the services and data contracts based on what we have modeled in the service contract and data contract model which is either WCF or ASMX based. Service factory will also generate the business and resource access layer projects as well where you can write your respective business and resource access related codes.

The whole service application solution structures follow the following layered diagram which is taken from the Web Service Application Architecture. You can also find the same content in the Web Service Software Factory 2010 chm documentation downloadable from codeplex. You can also read the Service Architecture Guide Pocket Guide by Microsoft Patterns and Practices group which can be download from codeplex as well.



Web Service Application Layered Diagram


To create the WCF projects and generate codes for the service and data contracts, right click the MyCompany.Service.Model.AppName solution in the solution explorer and choose Add and WCF Implemention Projects from the pop up menu as shown in figure 1.28


Figure 1.28 Creating WCF Implementation Projects

After clicking the WCF Implementation Projects, the Add New Project dialog appear where you can type in the prefix for the names of the projects that the service factory is going to create afterwards. I am going to put my prefix as MyCompany.Service as shown in figure 1.29.


Figure 1.29 Add New Project Dialog for WCF Implementation Projects

Service factory will create the rest of my layer projects with names like

MyCompany.Service.DataContracts
MyCompany.Service.FaultContracts
MyCompany.Service.ServiceContracts
MyCompany.Service.MessageContracts
MyCompany.Service.ServiceImplementations

.....
.....
.....

This is the default way the shipped version of the service factory will name the the projects it creates.
Once OK is clicked, all the layered projects will unfold and at the same time, the project mapping file will be updated as well. So later, when we have to regenerate our service and data contract codes after modification, the code generation know where to unfold the codes into the respective projects. The project mapping file was added to the solution initially when we created the MyCompany.Service.Model.AppName project but the content of this mapping file is empty because we haven't created the WCF implementation projects yet. Figure 1.30 shows the solution structures and the layer projects created by the service factory.



Figure 1.30 Solution Structures Unfold by Service Factory


From the figure 1.30, service factory generates the projects for all the layers correspond to the web service application layered diagram by grouping all the projects into their respective solution folders.

It is time to look at the content of the project mapping file (ProjectMapping.xml) . The purpose of this file is to decouple the models from the project that the service factory will generate codes into. Figure 1.31 shows the content of the project mapping file generated by the service factory initially




Figure 1.31 Content of the Project Mapping File

From the figure 1.31, the project mapping table name is the same as the one that was used when creating the WCF implementation projects. Each of the project mapping element has a project id which is a guid that identify the visual studio project. You can get this project id by looking at the visual studio project file using notepad as in figure 1.32



Figure 1.32 Project Guid in C# Visual Studio Project File

The Project Path will tell the service factory where to unfold the code in the visual studio project. Since the \GeneratedCode is specified, the code generation will output the codes into a GeneratedCode folder of visual studio project. If you want the codes to be output into the root level of the visual studio project, then replace it with \ . The role element targets the visual studio project with the model element. For e.g. the ServiceRole will target all the service elements in the service contract model file and ensure the generated codes put into the MyCompany.Service.ServiceImplementation project file. For more information, please refer Code Generation Extensions.

Figure 1.33 shows the original folder structures created by the service factory with all the implementation projects placed under the MyCompany.Service\Source folder.



Figure 1.33 Implementation Project Folders


If you refer to figure 1.30 and 1.33, their naming convention for project namespace and assembly, the solution structure layout and the organization of the projects in the windows folders are not what I desire.
My intention is to have the project name suffixed with the AppName. Something like

MyCompany.Service.DataContracts.AppName
MyCompany.Service.FaultContracts.AppName
MyCompany.Service.ServiceContracts.AppName
MyCompany.Service.MessageContracts.AppName
MyCompany.Service.ServiceImplementations.AppName

....
....
....

My quick workaround solution to this is to rename each of the project name, project folder name, default namespace and assembly name manually to include the suffix AppName. At the same time, I also reorganize the folder structures for all the generated projects to have the same folder level as MyCompany.Service.Model.AppName. Figure 1.34 shows all the implementation projects placed under the ServiceProject\Source folder the same folder as where the MyCompany.Service.Model.AppName project folder is placed.


Figure 1.34 Implementation Projects after Reorganization

Figure 1.35 shows the new solution layout after I have removed the business layer and resource access layer projects generated by the service factory and replaced with the framework and application projects from my previous post on Repository, Specification, Unit of Work, Persistence Ignorance POCO with Microsoft ADO.NET Entity Framework Beta 2. In the mean time, I have also made some necessary changes in the project mapping table. This includes change the mapping table name to MyCompany.Service.AppName, change the project path to \ , project name for all the service projects and the newly introduced business and data layer projects as well as their project ids.



Figure 1.35 New Solution Layout

Modifying the service factory source code to emit the implementation projects to follow the desired naming for the namespace, assembly, project and also the location to create the project is the most ideal solution. This is the long term solution for the organization that has many ongoing service projects as the automation can avoid errors and unproductive works. It is worth the efforts and investment to customize the software factory to tailor to specific development needs.

So far, the service factory has generated all the implementation projects. The service layer projects do not have any codes at all. In order to have the service and data contract codes generated, we need to update the project mapping table property of the service and data contract model to MyCompany.Service.AppName. To access the project mapping table property of the models, right click the design surface of the respective model to bring up its properties window as in figure 1.36. We repeat the steps for both service and data contract model.


Figure 1.36 Project Mapping Table Property

At this moment, we can save both the models with no errors as what we countered previously. We can generate codes for both the service and data contract models. From the design surface area of the service contract model, right click and select Generate All Code from the pop up menu. Service factory will generate codes for the elements in both the models. If you select Generate Code from the pop up menu, service factory will only generate codes for the elements in the service contract models. You can also generate codes for the elements in the data contract model from its design surface area. However, the Generate All Code is not available from the design surface area of the data contract model.



Host Model

This is the last model we will be working with. The general idea is to generate the necessary codes and configuration for the host application to expose the service through the service endpoint so that the service client can consume the service through the client proxy.

This model introduces the notion of service endpoint, client proxy, host application, client application, service reference. We start by creating a new host model through the similar steps we have done for the service and data contract model. We choose the Host Model from the pop up menu and give the name DefaultServiceDeployment to the host model as shown in figure 1.37.



Figure 1.37 Create a New Host Model



Figure 1.38 Host Model Design Surface and its Toolbox Shapes

The toolbox has the following shapes

Host Application - This is the host application that will host the service. It accept request message and send response message. This shapes can be tied to multiple service implementation shapes in the service contract models. The service implementation shape can be tied to the host application through the Service Reference shape.

Client Application - This is the client application that will consume the service exposed by the host application. Client application can contain one or more proxies.

Service Reference - This shape will allow the service implementation shape in the service contract model to be associated with the host application that will host the service.

Endpoint - This is the service endpoint. A location where the service client can connect to using a specified protocol and data format when consuming the service. The endpoint can be described in Address(A), Binding(B), Contract(C). The address tells where the service can be found. It defined the protocol used, the machine where the service is running and the path the service is located. The binding describes how the service client can communicate with the service. Among other things, it controls the following items


  • The Transport such as Http, Tcp, Named pipes and etc

  • The Channel corresponds to the message exchange patterns namely; Request-Reply,One Way and Duplex.

  • The encoding method used to encode the message being exchanged such as binary, MTOM and etc.

  • The supported WS-* specifications such as WS-Security, WS-Reliability, WS-Transactions and so on.
The contract is the external interface which is exposed to the outside and draw a distinct line between the exposed behavior and its internal implementation. It generally refers to the service contract and the message structure described in data contract or message contract.

Proxy - It is the portion of the client code that invokes the service. In more specific term, it is the remote proxy that maintain a reference to the service. It acts as a surrogate to connect to the service on behalf of the service client application. A client application can contain one or more proxies to different services. The web service proxy is generated based on the Web Service Description Language (WSDL) at design time. It is meant to describe the service endpoint (ABC) in a standardized way.


So, let complete our host model.  First thing to do is to drag a host application shape from the toolbox to the design surface and name it IISHost. In its properties window, select the WCF Extension for the Implementation Technology property. As for the Implementation Project property, select the MyCompany.Service.Host.AppName project from the drop down combo. This project will contain the endpoints and configuration for the services on the host. Figure 1.39 shows the host model after adding the host application shape.



 Figure 1.39 Host Model after Adding the Host Application Shape

From figure 1.39, you will notice there is a host explorer which allow you to navigate through the host model elements. At the same time, you can perform activities like adding or removing the host model shapes that you can accomplish with the host model GUI designer.

We add a service reference shape on to the application host shape and name it CustomerService. Please don't simply add the service reference shape to the design surface because the service reference shape won't add. Instead, you have to add it on the application host shape. From the properties window of the service reference shape, we need to set the Service Implementation Type property to the CustomerService service implementation shape in the service contract model. Once the is clicked, a Create Reference to Element dialog box will show up to enable the selection of the model element. The Enable Metadata Publishing property is set the true so that the WSDL of the service can be published and obtained to create the service proxy for the client application. Figure 1.40 shows the host model after adding the service reference shape to the host application shape.


 

Figure 1.40 Host Model after Adding Service Reference Shape


We continue to drag an endpoint shape from the toolbox on the CustomerService service reference shape and name it DefaultEndPoint. From the properties window of the endpoint shape, you will notice the Binding Type property. Service factory only generate binding configuration for basicHttpBinding and wsHttpBinding. The basicHttpBinding is mainly for backward compatibility. Figure 1.41 shows the host model after adding the endpoint shape to the service reference shape.



Figure 1.41 Host Model after Adding Endpoint Shape to the Service Reference Shape


We continue to drag a client application shape to the design surface and name it WinformServiceClient. From its properties window, we set the Implementation Technology property to WCF Extensions and set the Implementation Project property to MyCompany.Service.Client.AppName project from the down drop combo. This is the project where the client proxy will be generated as well as the necessary service client configuration that is necessary to connect to the service. Figure 1.42 shows the host model after adding the client application shape to the design surface.



Figure 1.42 Host Model after Adding Client Application Shape


The last shape to add is the proxy shape. Drag it from the toolbox and add it on the client application shape. Name it as CustomerServiceProxy. From its properties window, set the value of Endpoint property to DefaultEndpoint from the drop down combo. This will establish a connection between the CustomerServiceProxy and DefaultEndpoint shape as show in figure 1.43


Figure 1.43 Host Model after Adding Proxy Shape


This has completed our host model. We can save the model and at the same time the service factory will validate the model with no errors reported.

Finally, we right click on the design surface area of the host model and select Generate All Code from the pop up menu. This will generate all the necessary .svc file and also the service configuration in the web.config into the MyCompany.Service.Host.AppName project as shown in figure 1.44


 

Figure 1.44 .svc File and Service Configuration Generated into the Application Host Project 


We now has the .svc file(s) and service configuration generated for the application host project. We need to have the proxy code and the client configuration generated into the service client project. Right click the proxy shape and choose Add Service Reference from the pop up menu. An Add Service Reference dialog will show up as in figure 1.45



Figure 1.45 Add Service Reference Dialog


Click the discover button to discover the service. If this is the first time you click discover, the MyCompany.Service.Host.AppName web site project will be launched and hosted in the ASP.NET Development Server. Notice that the port no you will be getting may be different from what is shown in figure 1.45 as it is dynamically assigned by the development server. We give the CustomerServiceProxy for the namespace and then click OK. The proxy reference will be generated and its configuration will be placed in the app.config for the MyCompany.Service.Client.AppName project as shown in figure 1.46



Figure 1.46 Proxy and Service Configuration Generated for the Service Client Project


The last thing to thing to cover here is the entity translator which converts internal business entities to and from external message structure (data and message contract). Business entities are internal to the service and they are shared among the data and business layers. They are generally moved into its own project/assembly so that both the business and data layer relies on them as shared contracts. Since the entity translator is responsible for translating message structure into entities for use by the business layer, then it should be placed in the service implementation project.


I will end my post here.

Code DownloadService Application Demo with Service Factory 2010.(Rename the extension from .pdf to .zip once you have downloaded the file. Let me know if you have any problem running the code.)

See you in my next post.
Bye and stay tune ...


References & Recommend Readings




  1. Pro WCF  - Practical Microsoft SOA Implementation (ISBN-13 (pbk): 978-1-59059-702-6, ISBN-10 (pbk): 1-59059-702-8)