More Flexible Namespace Naming

September 1st, 2009 No comments

When using Visual Studio’s handy Add Service Reference wizard to add a new WCF service to your project, the dialog box allows you to define the namespace of the generated proxy code, which includes the method definitions and the data contracts.  While this is good for most cases, there are some instances where more flexibility in setting the namespace is desired.

image003

I ran into a situation where there were several services using a common library of data classes.  However, the proxy classes generated for each service included separate instances of the same class (in this case, ParticipantDto) in different namespaces.  So instead of having the same class, the client application treated them as GoalService.ParticipantDto, UserService.ParticipantDto, etc.

Service Utility (SVCUTIL) to the Rescue

At the heart of the Add Service Reference Wizard is the SVCUTIL command line program, which has several options not exposed through Visual Studio.  To solve our divergent namespace issue, SVCUTIL includes a /namespace option that allows you to specify how to map a contract namespace to the generated .NET proxy namespace.

Therefore, the first key is setting the Namespace attribute in the DataContract attributes:

namespace Example.Business.DataTransferObjects
{
    [DataContract(Namespace= http://schemas.example.com/Services/2009/09")]
    public class ParticipantDto
    {
       …

Now that the namespace has been established, you can create a batch script as defined at http://stackoverflow.com/questions/889621/adding-service-references-to-multiple-wcf-services-that-shared-classes.  This script will execute SVCUTIL against the set of services that share a common set of classes.

@ECHO OFF
SET cmd=C:"Program Files""Microsoft SDKs"\Windows\v6.0a\bin\SvcUtil.exe
SET cmd=%cmd% /out:ProxyClass.cs /collectionType:System.Collections.Generic.List`1
SET cmd=%cmd% /config:Proxy.config
SET cmd=%cmd% /serializable
SET cmd=%cmd% /serializer:DataContractSerializer 

REM ######### Service namespace mappings (Service Contracts and Message Contracts)
SET cmd=%cmd% /namespace:"http://services.example.com/Services/2009/09"
SET cmd=%cmd%,"Example.Business.Services"

REM ######### Schema namespace mappings (Data Contracts)
SET cmd=%cmd% /namespace:"http://schemas.example.com/Services/2009/09"
SET cmd=%cmd%,"Example.Business.DataTransferObjects"

REM ######### Set all the URLs that have common types
SET cmd=%cmd% http://localhost/GoalsService/GoalService.svc
SET cmd=%cmd% http://localhost/UserService/UserService.svc
SET cmd=%cmd% http://localhost/EmailService/EmailService.svc

%cmd%

PAUSE

The newly generated proxy code will contain two namespaces – one for the data contracts (Example.Business.DataTransferObjects) and one for the services (Example.Business.Services).  Therefore not only does this solve our divergent namespace issue, but it also provides a cleaner separation between the service methods and the data classes.

Categories: .NET, WCF

Business Logic in Data Transfer Objects (DTOs)

September 1st, 2009 No comments

While Data Transfer Objects (DTOs) are meant to be simple data containers with no functionality, there may be cases where you would like to add some simple business logic or data formatting within your classes that doesn’t require a call across the network using a service method.

For instance, let’s say we have a User DTO class that contains a property with the person’s height in inches.  If we would like to add some code to compute the person’s height in feet and inches (e.g., 5 feet, 11 inches), it would be nice to add this within the DTO class itself.

Since the generated proxy code uses partial classes, we have a fairly simple solution.  Within our client application, we can add on to the class using the “partial” keyword and then include any additional logic that we need to perform.  Be sure not to make this too complicated since any complex business logic should be done within the business layer, but this is an easy way to implement data formatting or simple computations.

namespace Example.Business.DataTransferObjects
{
    public partial class UserDto
    {
        public int HeightFeet
        {
            get
            {
                return this.CurrentHeight / 12;
            }
        }

        public int HeightInches
        {
            get
            {
                return this.CurrentHeight % 12;
            }
        }
    }
}
Categories: .NET, WCF