views:

537

answers:

3

Hi,

I'm trying to separate actual service data from service functionality and am therefore returning data as a data contract which holds several properties (data members). The client code is generated using svcutil /edb which also generates an INotifyPropertyChanged implementation for the proxy code. As far as my testing revealed, that code does not invoke the PropertyChanged event for changes which happened on the server. Additionally, getting a property does only return the property value as when the data contract proxy has been obtained.

Basically, here is what I've got:

(Server Side)

[ServiceContract]
public interface IControllerService
{
    [OperationContract]
    DataModel GetDataModel();
}

[DataContract]
public class DataModel : INotifyPropertyChanged
{
    private string _state;

    [DataMember]
    public string State
    {
        set
        {
            if (_state != value)
            {
                _state = value;
                OnPropertyChanged("State");
            }
        }
        get
        {
            return _state;
        }
    }

    public event PropertyChangedEventHandler  PropertyChanged;

    [OperationContract]
    protected virtual void OnPropertyChanged(string propertyName)
    {
        if (PropertyChanged != null)
            PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
    }
}

(Client Side)

private void Test()
{
    ControllerServiceClient client = new ControllerServiceClient();

    DataModel model = client.GetDataModel();
    model.PropertyChanged += new System.ComponentModel.PropertyChangedEventHandler(DataModelChanged);

    Console.WriteLine(model.State);

    // ... invoke something that forces the server to change the data model

    // Output stays the same
    Console.WriteLine(model.State); 
}

private void DataModelChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
{
    // This method never get called for server-side changes
}

I expect that the data contract proxy acts as a transparent proxy to the server's data contract but it seems to be completely unbound.

Thanks very much beforehand, Cheers,

Romout

A: 

Perhaps I've got the wrong end of the stick but I'm pretty sure the server can't 'push' property notification changes to the client...

mouters
Okay, so that would mean I'd have to implement such a 'feature' on my own using WCF callbacks? That would prevent any generic approach to such a simple need.
+1  A: 

WCF does not magically generate hookups to the server side objects. It simply calls whatever methods are defined in your ServiceContract and returns the data to you. There is no other communication channel beyond that.

So in your scenario you would need a duplex service (see: http://msdn.microsoft.com/en-us/library/cc645027%28VS.95%29.aspx) that calls back to the client with any change from the server manually.

GaussZ
Okay, okay, I've got it. I already have callback implementations but didn't think about using that approach to sync client/server changes on distributed objects - I think that answers my question :-\
@romout: Sorry the post was not meant to be in an offensive tone, i apologize if it appeared like that.I would advise to look into a refresh mechanism on the client side first where you don't push but pull the data; as duplex services typically add quite a bit of additional complexity (and thus opportunities for exceptions).
GaussZ
You weren't offensive, really. I'd rather not want to poll for data but might use a simple callback notification to retrieve the data object. In case that the client changed a value, it might call an update method or similar to update the servers state. That would also keep bandwidth low enough, I guess.
A: 

Don't think of the DataContract as a 'transparent proxy,' it's more of an interface.

Just because two classes implement the same interface, it doesn't mean they do exactly the same thing. The same is true for the client and server sides of the DataContract.

The client-side (here) is generated based on the DC, to also include DataBinding-helpful aspects, like INPC and ObservableCollections, that's it, no magic. eg if there were some calculated properties on your server-side object, that logic will not be present on the client.

As has been mentioned, if you have a need for the server to invoke events on the client, you'll need some kind of two-way binding/service, there's no other way (other than simulating it via polling the server, etc..)

Bobby