Reputation: 1042
I'm trying to create a WCF callback service with netTcpBinding. When I try to call a method of the service I get following exception:
An unhandled exception of type 'System.InvalidOperationException' occurred in System.ServiceModel.dll
Additional information: The InstanceContext provided to the ChannelFactory contains a UserObject that does not implement the CallbackContractType 'Client.WCFService.IHostFunctionsCallback'.
I've added a service reference instead of using SvcUtil.exe I've searched the internet for fixing this problem, but I haven't found a solution yet.
Here's my implementation:
IHostFunctions.cs (Part of HostLibrary)
using System.ServiceModel;
namespace HostLibrary
{
[ServiceContract(CallbackContract = typeof(ICallback))]
public interface IHostFunctions
{
[OperationContract]
void OpenSession();
}
}
ICallback.cs (Part of HostLibrary)
using System.ServiceModel;
namespace HostLibrary
{
public interface ICallback
{
[OperationContract]
void OnCallback();
}
}
HostFunctions.cs (Part of HostLibrary)
using System;
using System.ServiceModel;
using System.Timers;
namespace HostLibrary
{
[ServiceBehavior(ConcurrencyMode = ConcurrencyMode.Multiple)]
public class HostFunctions : IHostFunctions
{
#region Implementation of IHostFunctions
public static ICallback Callback;
public static Timer Timer;
public void OpenSession()
{
Console.WriteLine("> Session opened at {0}", DateTime.Now);
Callback = OperationContext.Current.GetCallbackChannel<ICallback>();
Timer = new Timer(1000);
Timer.Elapsed += OnTimerElapsed;
Timer.Enabled = true;
}
void OnTimerElapsed(object sender, ElapsedEventArgs e)
{
Callback.OnCallback();
}
#endregion
}
}
Callback.cs (Part of Client)
using System;
using HostLibrary;
namespace Client
{
public class Callback : ICallback
{
#region Implementation of ICallback
public void OnCallback()
{
Console.WriteLine("> Received callback at {0}", DateTime.Now);
}
#endregion
}
}
Program.cs of the service
using System;
using System.ServiceModel;
using HostLibrary;
namespace WCF_TCP_Callbacks
{
internal static class Program
{
private static void Main(string[] args)
{
using (var sh = new ServiceHost(typeof (HostFunctions)))
{
sh.Open();
Console.WriteLine("Service started.");
Console.ReadLine();
Console.WriteLine("Stopping service...");
sh.Close();
}
}
}
}
Program.cs of the client
using System;
using System.Globalization;
using System.ServiceModel;
using System.Threading;
using Client.WCFService;
namespace Client
{
internal class Program
{
private static void Main(string[] args)
{
var callback = new Callback();
using (var proxy = new HostFunctionsClient(new InstanceContext(callback)))
{
proxy.OpenSession();
}
Console.ReadLine();
}
}
}
The code is from http://adamprescott.net/2012/08/15/a-simple-wcf-service-callback-example/ but with netTcpBinding.
Upvotes: 0
Views: 2000
Reputation: 495
I know post is old : What is really the name of your callback Class?
the code you posted says this:
Callback : ICallback
The Error Message says this: CallbackContractType 'Client.WCFService.IHostFunctionsCallback'
So is the Callback as per your code above, or is it really defined as:
Client.WCFService.IHostFunctionsCallback
I would say you have decorated an attribute reference to the callback channel incorrectly, or inherited from the wrong callback. Search your project to make sure you named everything correctly.
EDIT As to why the fix worked and what happened: I answered for the case of others.It may be if you were in a team environment that someone changed the name of the Callback class interface from so generic to something more understandable - in WCF that is what your userobject is - it is the contract. You may have used Visual Studio to generate your Client or Service at one point. which can also foul things up, which is what it looks like to me as the naming convention follows IService[Callback].
Upvotes: 0
Reputation: 1042
I fixed that problem by simply renaming the class ICallback
to IHostFunctionsCallback
.
I still don't know why this works now as I didn't use IHostFunctionsCallback
before.
Upvotes: 0
Reputation: 107
by default WCF will attempt to dispatch using an available SynchronizationContext. The problem with this callback is the UI thread is already blocked in an outbound call. SO for the call to dispatch we need to tell WCF not to use the SynchronizationContext – again using the CallbackBehavior attribute:
[CallbackBehavior(ConcurrencyMode=ConcurrencyMode.Reentrant, UseSynchronizationContext=false)]
public class Callback : ICallback
{
....
}
for further detail look this link http://www.dotnetconsult.co.uk/weblog2/PermaLink,guid,b891610a-6b78-4b54-b9a6-4ec81c82b7c0.aspx and one more post describe it further http://stefanoricciardi.com/2009/08/28/file-transfer-with-wcp/
Upvotes: 1