NullReference Exception is thrown while getting a callback channel
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 NullReferenceEx开发者_StackOverflow中文版ception. So how can i manage this?
Thanks for your attention!
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.
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
}
}
精彩评论