Search code examples
c#wcfsoasolid-principlesonion-architecture

How to use DomainModel Into WCF


Background: I need to release a simple project, which will be used for transporting data from my storage to other place (other developers who will use my WCF. WCF wiil be used for transporting data (To protect DB and so on). I used onion architecture in my project(base parts).

--------------------------------------
|                WCF                 |
| ---------------------------------- |
| | Interfaces for working with DB | |     
| |        -------------           | |
| |        |DomainModel|           | |
| |        -------------           | |
| -----------------------------------|
--------------------------------------

I show my problen on a simple example:

I have DomainModel like this:

[DataContract]
public class User
{
    private string _name;
    private List<Text> _texts;

    public User(string name, List<Text> texts)
    {
        _name = name;
        _texts = texts;
    }
    [DataMember]
    public string Name { get { return _name; }  }
    [DataMember]
    public List<Text> Texts { get { return _texts; } }
}    


[DataContract]
public class Text
{
    private string _name;

    public Text(string name)
    {
        _name = name;
    }

    [DataMember] 
    public string Name { get { return _name; } }
}

WCF service have this method:

    public DomainModel.User ReturnUser()
    {
        User user = new User("Texts",
            new List<Text>()
            {
                new Text("TextOne"),
                new Text("TextTwo")
            });

        return user;
    }

But when I call the method

static void Main(string[] args)
{
    try
    {
        ServiceRomanClient client = new ServiceRomanClient();
        User user = client.ReturnUser();
        Console.WriteLine(user.Name);
    }
    catch (Exception ex)
    {
        Console.WriteLine(ex.Message);
    }
}

I get this exception: This could be due to the service endpoint binding not using the HTTP protocol. This could also be due to an HTTP request context being aborted by the server (possibly due to the service shutting down). See server logs for more details.

If I change propertis in DomainModel on this ( I added set)

[DataContract]
public class User
{
    private string _name;
    private List<Text> _texts;

    public User(string name, List<Text> texts)
    {
        _name = name;
        _texts = texts;
    }
    [DataMember]
    public string Name { get { return _name; } set{ _name = value;  } }
    [DataMember]
    public List<Text> Texts { get { return _texts; } set { _texts = value; } }
}

[DataContract]
public class Text
{
    private string _name;

    public Text(string name)
    {
        _name = name;
    }

    [DataMember] 
    public string Name { get { return _name; } set{ _name = value;} }
}

I don not have the execption, but I break S.O.L.I.D principels.

I want not to add set into DomainModel, I suggest that better way to solve this problem is to create a transport layer between DomainModel and WCF.

I will appreciate if you can give me your thoughts from your experience.


Solution

  • You could give the property a private setter. That way the data contract serializer should still be able to serialize the object, but you aren't exposing the property's setter to any code outside of the domain model.

    Alternatively you could implement a data transfer object that is effectively just a class with a bunch of public getters and setters and use that as your WCF data contract. I suppose the downside of this option is that you would then have to write some mapping code or use an auto-mapping tool to map between your domain model and your data transfer object.