2
votes

I have a web service that is currently using asmx. The operations are decorated with WebMethod and each takes in a request and returns a response. I started creating a WCF app and I am referencing the business layer so I can reuse the Web methods. My question is, do I have to decorate each class with DataContract and each property of the request with DataMember?

Currently, one of the classes is decorated with SerializableAttribute, XmlTypeAttribute, and XmlRootAttribute. Do I need to remove these and add DataContract or do I can I add DataContract to it? It is a .NET 2 app by the way. The class also contains a bunch of private fields and public properties, do I need to decorate these with a DataMember attribute. Is this even possible if it is using the .NET 2 framework?

The WCF Service is currently targeting .NET Framework 4.0. A few of the methods need to still use the XmlSerializer, so does this mean I can just decorate the operation with [XmlSerializerFormat]?

Can you elaborate on not using any business objects on the service boundary? and what is DTO?

If possible, can you give an example?

2
Regarding XMLSerializer: yes. I'll edit my answer about DTOsRichard Blewett

2 Answers

2
votes

Since .NET 3.5 SP1 the DataContractSerializer does not require the use of attributes (called POCO support). Although this gives you little control over the XML that is produced

However, if you already have an ASMX service you want to port then to maintain the same serialization you really want to use the XmlSerializer. You can wire this in in WCF using the [XmlSerializerFormat] attribute which can be applied at the service contract or individual operation level

Edit: adding section on DTOs

However, putting business objects on service boundaries causes potential issues:

  1. You may be exposing unnecessary data that is purely part of your business rules
  2. You tightly couple your service consumers to your business layers introducing fragility in their code and preventing you from refactoring freely

The idea of Data Transfer Objects (DTOs) is to create classes whose sole role in life is to manage the transition between the XML and object worlds. This also conforms to the Single Responsibility Principle. The DTOs oinly expose the necessary data and act as a buffer between business changes and the wire format. Here is an example

[ServiceContract]
interface ICustomer
{
    [OperationContract]
    CustomerDTO GetCustomer(int id);
}

class CustomerService : ICustomer
{
    ICustomerRepository repo;
    public CustomerService (ICustomerRepository repo)
    {
        this.repo = repo;
    }

    public CustomerService()
        :this(new DBCustomerRepository())
    {

    }

    public CustomerDTO GetCustomer(int id)
    {
        Customer c = repo.GetCustomer(id);
        return new CustomerDTO
        {
            Id = c.Id,
            Name = c.Name,
            AvailableBalance = c.Balance + c.CreditLimit,
        };
    }
}

class Customer
{
    public int Id { get; private set; }
    public string Name { get; set; }
    public int Age { get; set; }
    public decimal Balance { get; set; }
    public decimal CreditLimit { get; set; }      
}

[DataContract(Name="Customer")]
class CustomerDTO
{
    [DataMember]
    public int Id { get; private set; }
    [DataMember]
    public string Name { get; set; }
    [DataMember]
    public decimal AvailableBalance { get; set; }
}

Using DTOs allows you to expose existing business functionality via services without having to make changes to that business functionality for purely technical reasons

The one issue people tend to baulk at with DTOs is the necessity of mapping between them and business objects. However, when you consider the advantages they bring I think it is a small price to pay and it is a price that can be heavily reduced by tools such as AutoMapper

0
votes

WCF uses the DataContractSerializer which is primarily based upon attributes like: DataContract, DataMember, ServiceContract and so forth. But it also supports SerializableAttribute amongst others. This http://msdn.microsoft.com/en-us/library/ms731923.aspx document gives you all the insight you need.

So it might be that you don't need to refactor all your existing code but it aks some further investigation and testing ;)