При получении канала обратного вызова выдается исключение NullReference - PullRequest
0 голосов
/ 09 апреля 2010

Я пытаюсь договориться с дуплексными контрактами WCF. Код из этой статьи

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

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

выдает исключение NullReferenceException. Так как я могу справиться с этим?

Спасибо за внимание!

Ответы [ 2 ]

0 голосов
/ 09 апреля 2010

Я только что быстро пробежался по примеру.

Код моего сервиса:

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();

    }
}

}

Конфигурация моего приложения выглядит следующим образом:

<?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>

Затем я использовал адрес хоста в файле конфигурации для создания ссылки на службу с именем CalculatorService.

так выглядит мой клиент:

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
    }
}
0 голосов
/ 09 апреля 2010

Украсили ли вы интерфейс для ICalculatorDuplex

с

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

Когда служба получает сообщение, она смотрит на элемент replyTo в сообщении, чтобы определить, куда ответить, и я полагаю, что если вы пропустите атрибут контракта обратного вызова, это приведет к тому, что вы получите исключение NullReferenceException, поскольку Не знаю, где ответить.

...