WCF services and shared assemblies

I often see situations on projects where they have design challenges with multiple webservices who share the same datacontracts (DTO). I already wrote a post about the separation of the service contract and the DTO’s, but i would like to extend that post with my vision on how we should work with mutiple services build on top of the same DTO’s.

To illustrate this I have build two WCF services which both have a reference to the DTO project called MyDataContracts. The solution for my services looks like this:

ServiceImplementation

Project 1 & 3 are service contracts and service implementations and project 2 contains the shared DTO’s.

The service contracts are very simple

[ServiceContract]
public interface ICustomerService
{
    [OperationContract]
    Customer GetCustomer(int value);
}
[ServiceContract]
public interface IInvoiceService
{
    [OperationContract]
    Invoice GetInvoice(int invoiceId);
}

The invoice DTO is implemented below

[DataContract]
public class Invoice
{
    int invoiceId = 0;
    Customer client;

    [DataMember]
    public int InvoiceId
    {
        get { return invoiceId; }
        set { invoiceId = value; }
    }

    [DataMember]
    public Customer Customer
    {
        get { return client; }
        set { client = value; }
    }
}

Because the invoice DTO has a datamember of the type customer the clients who want to interact with the invoice service have to know how a customer DTO will look like.

So that’s it for the service side. Now we take a look at the client side. When I consume services I usually create a service agent project which will be responsible for handling the calls to the services. This way I only have to implement exception handling once for the communication with my services. So my service agent project has two service references (two proxies). These two proxies will receive there own version of the customer DTO when I generate the proxy in the standard way. As you can see in the object browser below, both proxies have a Customer DTO generated. This can give you some annoying issues especially when you have to map values to your customer DTO and you have to pick a different one depending on the service you are communicating with.

ObjectBrowser

My client solution looks like this

ClientApplication

The first project is just a console application which interacts with my second project the service agent. I have created a service agent class.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using MyServiceAgents.CustomerProxy;
using MyServiceAgents.InvoiceProxy;
using System.ServiceModel;

namespace MyServiceAgents
{
    public class ServiceAgent
    {
        public Customer GetCustomer()
        {
            CustomerServiceClient proxy = new CustomerServiceClient();

            try
            {
                return proxy.GetCustomer(1);
            }
            catch (FaultException ex)
            {
                // catch any faultexception from the service
            }
            catch (CommunicationException cex)
            {
                // ...
            }
        }

        public Invoice GetInvoice()
        {
            InvoiceServiceClient proxy = new InvoiceServiceClient();

            try
            {
                return proxy.GetInvoice(1);
            }
            catch (FaultException ex)
            {
                // catch any faultexception from the service
                throw new Exception();
            }
            catch (CommunicationException cex)
            {
                // ...
            }
        }
    }
}

The service agent has two methods. Each method is responsible to communicate with one of the two services. To make sure my proxy classes are available i have to add the following using statements

  • using MyServiceAgent.CustomerProxy
  • using MyServiceAgent.InvoiceProxy
    Adding these using statements will give us the problem of ambiguous classes.

Ambiguous

Well take a look at what happened right now. On the right side we see the customer & invoice service. The service project references the contracts project which contain two DTO’s. On the left side I have the service agent project which contains two service references. Adding these service references added a proxy for both services and DTO’s which are needed for the communication. The customer DTO is created twice.

Overview1

To resolve this issue you could use a shared assembly for the DTO’s. You have to make sure that when the service reference is added on the client project it doesn’t generate any DTO’s anymore. To make this possible you have to share your DTO assembly with your consumers, which looks fine to me. This will give you the following situation.

Overview2

I hope that sharing an assembly doesn’t need any explanation. To make sure that adding a service reference doesn’t generate any DTO’s you only have to add a reference from your service agent project to the DTO assembly. This way Visual Studio knows how to handle the generation of your service reference. To be sure click on the advanced button when you add a service reference.

VisualStudioSetting

Make sure the checkbox ‘Reuse types in referenced assemblies’ is enabled and you are good.

This solution can be related the the following SOA pattern: Canonical schema The DTO’s are set as standard across service contracts within an inventory boundary.

Regards,

Dennis

ADO.NET Dataservice

Hi,

With the release of Visual Studio 2008 SP1 and the .NET Framework 3.5 SP1, ADO.NET Dataservices is also released. With this technology you are able to expose multiple datasource as dataservices. ADO.NET Dataservice uses REST technolgy which means that every datasource is referenced by a URI. I think ADO.NET Dataservice is a technology which will be used very often in the future especially with the upcoming interrest for Silverlight. The project team already made some “How do I” videos available here! Enjoy

Regards

XML serialization part II

Hi all,

I have to recall my thoughts about the commnadline tool xsd.exe in the post: XML serialization. When an XSD element contains a minoccurs =”0″ and it’s not a string, there will be a property generated with the name. <element name>+Specified. This property is a boolean field which is used to determine if a field needs to be serialized to XML. The default value is false, so if you don’t set this field you won’t be able to see your data back in your XML.

Regards,

Dennis

XML serialization

Hi,

Last week i spend a few hours to analyse and fix a very strange problem. On the project where i am working on right now we have to serialize some objects to XML before we could send it to WebMQ. The objects that need to be serialized are created with the XSD command-line tool. We received an XSD from our customer and generated a class with this XSD.

XSD.exe /c /l:c# <XSD file>

These XSD’s are sometimes huge files so this will generate enormous classes. Before we send our XML reqeust to WebMQ we validate the XML against the XSD to be sure that WebMQ will accept and process our request. At this point i receive messages that the serialized XML isn’t valid, there are some elements missing. I started the debugger and checked if all the values of my object were set before it will be serialized. Everything looks fine, but the XML doens’t contain the values that it put in my object.

When i took a closer look to the XSD file i saw that every property that i have set in my object and isn’t in the XML file has the attribute minOccurs=”0″ defined. So i removed the minOccurs attribute from the XSD, generated a new class again with the XSD command-line tool and tried it again. This time every property was serialized to XML. I couldn’t  believe this was the solution for my problem. minOccurs=”0″ means the least amount of elements that should be in the XML file. So ‘0’ is acceptable but ‘1’ also. I think the problem is within the XSD command-line tool. The reason this took me so long to fix it, was because first i was looking in the wrong direction. I was searching for ingore and serialazable attributes never thought that the minOccurs in the XSD would be the problem. A colleague mentioned that when the XSD is changed which is my contract to communicate with WebMQ that this could introduce a new problem because my message could be invalid. fortunately this was not a problem i validated my XML against an XSD with the minOccurs attribute and my XML was valid.

Regards,

Dennis

Naming convention

I see ( in code) and hear many times developers discussing naming convention. Should this paramater start with a capital character of not? In other words when should i use PascalCasing and when camelCasing? Well it could be confusing when you are talking to different developers with different ideas. Who is saying the right thing? (The discussion when is something right is not part of this post 🙂 ). I am reading a book Framework design guidelines by Krzysztof Cwalina and Brad Abrams and they discuss this issue. I want to show you a table from this book which is very clear which naming convention you can use in which situation:

Identifier Casing Example
Namespace Pascal System.Security
Type Pascal StreamReader
Interface Pascal IEnumerable
Method Pascal public virtual string ToString();
Property Pascal public int Length { get; }
Event Pascal public event EventHandler Exited;
Fields Pascal public static readonly TimeSpan InfiniteTimeout;
Enum value Pascal FileMode{

Append,

}

Parameter Camel public static int ToInt32(string value);

This could be a good start when every developer is using the same naming convention. This will make it easier to read code from another developer, but this is just one piece there is more! This subject is just a paragraph in the book. If you want to know more about naming conventions and programming guidelines you should check the book. It is written very clear and easy to read.

Upgrade exam 70-553 passed

A week ago i passed for the upgrade exam 70-553. This is a huge relief because it was a pretty big exam and i want to fix this exam before i can re-focus on the TFS exam i have to do later. I already posted before that i didn’t pass for my TFS beta exam (625) but now i am armed with the wrox book, so i have faith that i will succeed this time. The 70-553 exam contains 3 exams (Foundation, Web and Winform). After i finished my TFS exam i will take a look at 70-554 and hopefully i will finish this one at begin of 2008.

Unable to update the dependencies of the project

When you are using a database project and a setup project in the same solution you can run into this problem “Unable to update the dependencies of the project”. Well i read a suggestion and it was to install SP1 for Visual Studio. This didn’t fix our problem. What did fix our problem is described at the following page. Check it out