Search code examples
c#wcfdatacontract

WCF - different implementation of shared types


I am trying to design client/server application, that would be able to exchange "commands". The thing is, that server application is processing some stuff and I would like the client to be able to for example send command "pause" to the server.

The thing is, that my manager suggested, that best approach would be to create interface (ICommand for example) and then class for each command (Pause, Resume) that would inherit from the ICommand. After that, we could simply create an object Pause with [DataContract] attribute, that would be sent over to server. For that purpouse, I tried to use shared-types, so I created seprated assembly in which I designed all the [DataContracts], so that both server and client can use them (they have reference leading to them).

On the server, we would then have [OperationContract], that would take the [DataContract] as parameter and return [DataContract] as well, like this:

[ServiceKnownType(typeof(PauseServer))]
[ServiceKnownType(typeof(Resume))]
[ServiceContract]
public interface ITestService
{
     [OperationContract]
    ICommand DoCommand(ICommand command);
}

The problem is, that apart from some properties, we would like to have for example method "Execute(param1,param2)", that would do certain operation - this method would do different operation on server (pause the process) and different operation on client side (change the status and enable "Resume" button for example). Like this:

[DataContract(Namespace="PauseContract")]
public class Pause
{
    string _param1;
    int _param2;

    public void Execute()
    {
       // DO SOMETHING HERE
    }

    [DataMember]
    public string Param1
    {
        get
        {
            return _param1;
        }
        set
        {
            this._param1 = value;
        }
    }

    [DataMember]
    public int Param2
    {
        get
        {
            return _param2;
        }
        set
        {
            this._param2 = value;
        }
    }
}

In the end, the whole process would like this: 1) Client wants to pause the process, so it creates object "Pause", that would contain for example ID of the process. 2) This object is passed to the DoCommand() method, which creates object "Pause" on server side and run its "Execute()" method with the given parameters. 3) If the Pausing process ended well, the Pause object is returned back to client (with process ID and other attributes) 4) If client gets this response, it will know that the process has eben paused and run its own "Execute()" method on its own Pause object, that would change the GUI and so on.

So my question is - is it somehow possible, to have different implementation of contracts stored in common library on both server/client side? Or is this approach wrong in general? From what I have heards, it is not advised to include behaviour (methods) to [DataContracts], but I thought it would be ok, if I dont mark them with [DataMember] attribute.

Thank You, Jakub.


Solution

  • To be honest, I don't think the ICommand with ServiceKnownType attribute idea works well for commands.

    ServiceKnownType is designed to support polymorphism across service boundaries in the context of type properties and not behavior.

    Your Pause/Resume scenario would be very easily implement with the exchange of two distinct request/response DataContract definitions.