views:

140

answers:

2

Hi!

I am trying to get along with WCF's duplex contracts. A code from this article

(http://msdn.microsoft.com/en-us/library/ms731184.aspx)

ICalculatorDuplexCallback callback = null; callback = OperationContext.Current.GetCallbackChannel();

throws a NullReferenceException. So how can i manage this?

Thanks for your attention!

A: 

Have you decorated the interface for ICalculatorDuplex

with

[ServiceContract(Namespace = "http://Microsoft.ServiceModel.Samples", SessionMode=SessionMode.Required,
                 CallbackContract=typeof(ICalculatorDuplexCallback))]

When a service receives a message it looks at a replyTo element in the message to determine where to reply to, I would guess that if your missing the callback contract attribute it, it would result in you getting a NullReferenceException, as it doesn't know where to replyTo.

Miker169
Yes, i have, that's not it.
Yaroslav
A: 

I've just ran quickly through the example.

The code for my service is :

using System;
using System.Collections.Generic;
using System.Linq;
using System.ServiceModel;
using System.Text;

namespace DuplexExample
{
    // Define a duplex service contract.
// A duplex contract consists of two interfaces.
// The primary interface is used to send messages from client to service.
// The callback interface is used to send messages from service back to client.
// ICalculatorDuplex allows one to perform multiple operations on a running result.
// The result is sent back after each operation on the ICalculatorCallback interface.
[ServiceContract(Namespace = "http://Microsoft.ServiceModel.Samples", SessionMode=SessionMode.Required,
                 CallbackContract=typeof(ICalculatorDuplexCallback))]
public interface ICalculatorDuplex
{
    [OperationContract(IsOneWay=true)]
    void Clear();
    [OperationContract(IsOneWay = true)]
    void AddTo(double n);
    [OperationContract(IsOneWay = true)]
    void SubtractFrom(double n);
    [OperationContract(IsOneWay = true)]
    void MultiplyBy(double n);
    [OperationContract(IsOneWay = true)]
    void DivideBy(double n);
}

// The callback interface is used to send messages from service back to client.
// The Equals operation will return the current result after each operation.
// The Equation opertion will return the complete equation after Clear() is called.
public interface ICalculatorDuplexCallback
{
    [OperationContract(IsOneWay = true)]
    void Equals(double result);
    [OperationContract(IsOneWay = true)]
    void Equation(string eqn);
}
// Service class which implements a duplex service contract.
// Use an InstanceContextMode of PerSession to store the result
// An instance of the service will be bound to each duplex session
[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerSession)]
public class CalculatorService : ICalculatorDuplex
{
    double result;
    string equation;
    ICalculatorDuplexCallback callback = null;

    public CalculatorService()
    {
        result = 0.0D;
        equation = result.ToString();
        callback = OperationContext.Current.GetCallbackChannel<ICalculatorDuplexCallback>();
    }

    public void Clear()
    {
        callback.Equation(equation + " = " + result);
        result = 0.0D;
        equation = result.ToString();
    }

    public void AddTo(double n)
    {
        result += n;
        equation += " + " + n;
        callback.Equals(result);
    }

    public void SubtractFrom(double n)
    {
        result -= n;
        equation += " - " + n;
        callback.Equals(result);
    }

    public void MultiplyBy(double n)
    {
        result *= n;
        equation += " * " + n;
        callback.Equals(result);
    }

    public void DivideBy(double n)
    {
        result /= n;
        equation += " / " + n;
        callback.Equals(result);
    }

}
class Program
{
    static void Main()
    {
        var host = new ServiceHost(typeof(CalculatorService));

        host.Open();
        Console.WriteLine("Service is open");
        Console.ReadLine();

    }
}

}

My application config looks like :

<?xml version="1.0" encoding="utf-8" ?>

    <services>
        <service behaviorConfiguration="NewBehavior" name="DuplexExample.CalculatorService">
            <endpoint address="dual" binding="wsDualHttpBinding" bindingConfiguration=""
                contract="DuplexExample.ICalculatorDuplex" />
            <endpoint address="mex" binding="mexHttpBinding" bindingConfiguration=""
                contract="IMetadataExchange" />
            <host>
                <baseAddresses>
                    <add baseAddress="http://localhost:8081/duplex" />
                </baseAddresses>
            </host>
        </service>
    </services>
</system.serviceModel>

I then used the host address in the config file to create a service reference named CalculatorService.

so my client looks like :

using System;
using System.Collections.Generic;
using System.Linq;
using System.ServiceModel;
using System.Text;
using Client.CalculatorService;


namespace Client
{
    class Program
    {
        static void Main(string[] args)
        {
          var context = new InstanceContext(new CallbackHandler());

            var client = new CalculatorDuplexClient(context);

            Console.WriteLine("Press <ENTER> to terminate client once the output is displayed.");
            Console.WriteLine();


            // Call the AddTo service operation.
            var value = 100.00D;
            client.AddTo(value);

            // Call the SubtractFrom service operation.
            value = 50.00D;
            client.SubtractFrom(value);

            // Call the MultiplyBy service operation.
            value = 17.65D;
            client.MultiplyBy(value);

            // Call the DivideBy service operation.
            value = 2.00D;
            client.DivideBy(value);

            // Complete equation
            client.Clear();

            Console.ReadLine();

            //Closing the client gracefully closes the connection and cleans up resources
            client.Close();
        }
    }


    // Define class which implements callback interface of duplex contract
    public class CallbackHandler : ICalculatorDuplexCallback
    {
        public void Result(double result)
        {
            Console.WriteLine("Result({0})", result);
        }

        public void Equation(string eqn)
        {
            Console.WriteLine("Equation({0})", eqn);
        }


        #region ICalculatorDuplexCallback Members

        public void Equals(double result)
        {
            Console.WriteLine("Equals{0} ",result );
        }

        #endregion
    }
}
Miker169
Yeah, all that looks nice, but you don't call any client methods from the server, and that's exactly where the problem is. I need to get a callback channel and i define a null instance of a callback interface, using which in further code causes some problems.
Yaroslav
You wr0te CalculatorDuplexCallback callback = null; callback = OperationContext.Current.GetCallbackChannel();Shouldn't you be passing the callbackcontract in this method ?
Miker169