views:

249

answers:

1

Hey, I can't seem to access the returned value from a method I called on my Host.

    //Service---------------------------------------------------------
    [DataMember]
    private List<CalculationRecord> History = new List<CalculationRecord>();

    public IEnumerable<CalculationRecord> CalculationHistory()
    {
        return (IEnumerable<CalculationRecord>)History;
    }

    public CalculationResult Calculate(CalculationNode problem)
    {
        CalculationResult calcResult = new CalculationResult();


        //Calculates results of expression
        CalculationEvaluation Evaluator = new CalculationEvaluation();
        Evaluator.Calculate(problem, calcResult);

        return calcResult;
    }
    //interface---------------------------------------------------------
    [ServiceContract]
    public interface ICalculate
    {
        [OperationContract]
        CalculationResult Calculate(CalculationNode problem);

        [OperationContract]
        IEnumerable<CalculationRecord> CalculationHistory();
    }

    //Client------------------------------------------------------------
    CalculatorClient client = new CalculatorClient();
    ICalculate calcProxy = client.ChannelFactory.CreateChannel();

    CalculationNode calcRootNode = parser.Parse(expression);
    CalculationResult result = calcProxy.Calculate(calcRootNode);//result is null
+2  A: 

You're under a wrong impression - the DataContract that the server exposes can (and should) only contain data - never any behavior. As such, you can never share an object between client and host - all you can share are service methods to call, and concrete types to use on those methods. That's it.

The process is this: when the client connects up to the server, it will download the metadata for the service - it can find out what service methods are available, what data those take - but it cannot infer any additional methods on the data contract. It just can't. The client then builds up an exact copy of the data contract type - but it's a totally separate class, and it only matches the server-side data contract class as far as its serialized representation in XML is concerned. It is not the same class - it just look the same.

Because in the end, all that happens between the server and the client is an exchange of a serialized message - basically a XML text document. You are not sending across a .NET object! All you're exchanging is a data representation of your data contract, nothing more.

So in your case, the client side proxy will have a new class that looks like the one the server uses - at least on the serialized level on the wire - but it will not contain the Calculate method. The Calculate method you're calling is on the service contract - it's not the one on the data member you have.

In your concrete example, too - you seem to be intermixing [DataMember] and service interface definition. Avoid this at all costs. Also, all the types involved in the calculation - most definitely CalculationNode and CalculationResult - must be exposed as [DataContract] elements containing a number of [DataMember] fields or properties. This is not clear from the snippet of code you posted.

marc_s
Not exactly a solution but an explanation none the less. I know that Data Contracts and Data Members are for storage purposes only. My mistake was in the first couple lines of the service where I used a Data Member for the List<CalculationRecord>. I'm still trying to get the right syntax for using a collection and retaining its data structure across the wire so that was my mistake. But I did realize that I didn't actually add the Data Member Attribute to all the necessary properties in my class , and that is what fixed my issue, so that was helpful.
Terrance
Forgive my verbiage and syntax. I will try be clearer the next time. Thanks for the help.
Terrance
@Terrance: ok, glad I could help after all :-)
marc_s