How to Host SVC file in win form apps WCF - wcf

i am new in WCF. i know how to host wcf service in windows form. now i develop a small wcf service which has .svc file. i want to host this svc file in win form. so just want to know process will be same or different?
here is my svc file markup
<%# ServiceHost Language="C#" Debug="true"
Service="Services.ChatService" CodeBehind="ChatService.svc.cs" %>
here is small code inside svc file code behind file
namespace Services
{
/// <summary>
/// Implements the chat service interface.
/// </summary>
[ServiceBehavior(InstanceContextMode = InstanceContextMode.Single,
ConcurrencyMode = ConcurrencyMode.Multiple)]
public class ChatService : IChatService
{
private readonly Dictionary<Guid, IChatServiceCallback> clients =
new Dictionary<Guid, IChatServiceCallback>();
#region IChatService
Guid IChatService.Subscribe()
{
IChatServiceCallback callback =
OperationContext.Current.GetCallbackChannel<IChatServiceCallback>();
Guid clientId = Guid.NewGuid();
if (callback != null)
{
lock (clients)
{
clients.Add(clientId, callback);
}
}
return clientId;
}
void IChatService.Unsubscribe(Guid clientId)
{
lock (clients)
{
if (clients.ContainsKey(clientId))
{
clients.Remove(clientId);
}
}
}
void IChatService.KeepConnection()
{
// Do nothing.
}
void IChatService.SendMessage(Guid clientId, string message)
{
BroadcastMessage(clientId, message);
}
#endregion
/// <summary>
/// Notifies the clients of messages.
/// </summary>
/// <param name="clientId">Identifies the client that sent the message.</param>
/// <param name="message">The message to be sent to all connected clients.</param>
private void BroadcastMessage(Guid clientId, string message)
{
// Call each client's callback method
ThreadPool.QueueUserWorkItem
(
delegate
{
lock (clients)
{
List<Guid> disconnectedClientGuids = new List<Guid>();
foreach (KeyValuePair<Guid, IChatServiceCallback> client in clients)
{
try
{
client.Value.HandleMessage(message);
}
catch (Exception)
{
// TODO: Better to catch specific exception types.
// If a timeout exception occurred, it means that the server
// can't connect to the client. It might be because of a network
// error, or the client was closed prematurely due to an exception or
// and was unable to unregister from the server. In any case, we
// must remove the client from the list of clients.
// Another type of exception that might occur is that the communication
// object is aborted, or is closed.
// Mark the key for deletion. We will delete the client after the
// for-loop because using foreach construct makes the clients collection
// non-modifiable while in the loop.
disconnectedClientGuids.Add(client.Key);
}
}
foreach (Guid clientGuid in disconnectedClientGuids)
{
clients.Remove(clientGuid);
}
}
}
);
}
}
}
here is binding info
<service behaviorConfiguration="Services.ChatServiceBehavior" name="Services.ChatService">
<endpoint address="" binding="wsDualHttpBinding" bindingConfiguration="WSDualHttpBinding_IChatService" contract="Services.IChatService">
<identity>
<dns value="localhost"/>
</identity>
</endpoint>
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/>
</service>
here is two endpoint one for wsDualHttpBinding and another one for mex
so now my mex endpoint is
http://localhost:49722/ChatService.svc?wsdl
now i want to add another tcp endpoint and expose this service with two endpoint. so just tell me what i need to write for tcp endpoint and when i add tcp endpoint then what will mex endpoint for tcp because i want that user can create proxy with any of two url
one would be http url and another would be tcp url. so do i need to add mex for tcp here?
please guide me. thanks

you must start host manually
follow to msdn link http://msdn.microsoft.com/en-us/library/system.servicemodel.servicehost.aspx
edited
ServiceHost _serviceHost;
public void Start(Type type)
{
_serviceHost = new ServiceHost(type);
_serviceHost.Open();
}

Related

How to fix AddressInUseException that occurs whenever service host is opened

I am working on WCF windows application... while restarting the service, I am getting the below exception.
outerType: System.ServiceModel.AddressAlreadyInUseException
outerMessage: "Cannot listen on pipe name 'net.pipe://0.0.0.1/MyService' because another pipe endpoint is already listening on that name."
type: System.IO.PipeException
App.Config file:
<services>
<service name="ServiceName">
<endpoint address="" binding="netNamedPipeBinding" contract="ServiceClient">
</endpoint>
<host>
<baseAddresses>
<add baseAddress="net.pipe://0.0.0.1/MyService"/>
</baseAddresses>
</host>
</service>
</services>
Start Method:
public void Start(string serviceName)
{
_serviceName = serviceName;
if (_serviceController == null)
{
_serviceController = new ServiceController(_serviceName);
}
TimeSpan timeout;
switch (_serviceController.Status)
{
case ServiceControllerStatus.Stopped:
_serviceController.Start();
timeout = TimeSpan.FromMilliseconds(60000);
_serviceController.WaitForStatus(ServiceControllerStatus.Running, timeout);
break;
case ServiceControllerStatus.Paused:
_serviceController.Continue();
timeout = TimeSpan.FromMilliseconds(60000);
_serviceController.WaitForStatus(ServiceControllerStatus.Running, timeout);
break;
}
}
Stop Method:
public void Stop()
{
if (_serviceController == null)
{
_serviceController = new ServiceController(_serviceName);
}
if (_serviceController.Status == ServiceControllerStatus.Running)
{
_serviceController.Stop();
TimeSpan timeout = TimeSpan.FromMilliseconds(20000);
_serviceController.WaitForStatus(ServiceControllerStatus.Stopped, timeout);
}
}
When ever I restarts my service, I will start my Service controller and also open a service host for hosting my service.
_serverHost = new ServiceHost(this); // this points my service name mentioned in App.Config
_serverHost.Open(); // Exception occurs here.
I tried to increase my time out in WaitForStatus() on both Stop() method but it didn't worked out.
Any suggestion will be a great help.
Thanks.
Since you merely post a management application of the window NT service, I don’t think any changes on this side would help.
What is the Windows NT service code design? In my opinion, we should open and close the service host properly in the windows service OnStart event and windows service OnStop event. Windows NT service is the root of the issue.
Besides, I suggest add the IF statement detection during opening the service host and stop the service host.
Please consider the below code.
public partial class Service1 : ServiceBase
{
public Service1()
{
InitializeComponent();
}
Uri uri = new Uri("net.pipe://localhost/mypipe");
ServiceHost sh = null;
protected override void OnStart(string[] args)
{
NetNamedPipeBinding binding = new NetNamedPipeBinding();
try
{
if (sh == null)
{
sh = new ServiceHost(typeof(MyService), uri);
sh.Open();
} }
catch (Exception e)
{
}
}
protected override void OnStop()
{
if (sh != null && sh.State == CommunicationState.Opened)
{
sh.Close();
}
}
Feel free to let me know if the problem still exists.

Unable to get WCF services to run on shared server using IIS

I am unable to get WCF services to run on a shared server using IIS.
I have tried several tutorials:
http://technologyriver.blogspot.com/2012/02/prerequisites-check-windows-7.html
http://msdn.microsoft.com/en-us/library/ms733766.aspx
I've read blogs about executing command line instructions to enable WCF support on IIS.
However, the hosting company refuses to run the command on their box.
The services work fine on my dev machine.
However, I just cannot get the services to run on the remote server.
When clicking on an svc file I get the following error:
HTTP Error 404.3 - Not Found
The page you are requesting cannot be served because of the extension configuration. If the page is a script, add a handler. If the file should be downloaded, add a MIME map.*
svc file:
<% #ServiceHost Language=C# Debug="true" Service="MyService" Factory="MyServiceHostFactory" CodeBehind="~/App_Code/Service.cs" %>
Web.config:
<service name="MyService" behaviorConfiguration="MyServiceBehavior">
<endpoint contract="IMyService" binding="basicHttpBinding">
<identity>
<dns value="http://www.mydomain.com" />
</identity>
</endpoint>
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
<host>
<baseAddresses>
<add baseAddress="http://www.mydomain.com:8732/Services/Service/" />
</baseAddresses>
</host>
</service>
Service.cs:
using System;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.ServiceModel.Activation;
// A WCF service consists of a contract (defined below as IMyService, DataContract1),
// a class which implements that interface (see MyService),
// and configuration entries that specify behaviors associated with
// that implementation (see <system.serviceModel> in web.config)
[ServiceContract()]
public interface IMyService
{
[OperationContract]
string MyOperation1(string myValue1);
[OperationContract]
string MyOperation2(DataContract1 dataContractValue);
}
public class MyService : IMyService
{
public string MyOperation1(string myValue1)
{
return "Hello: " + myValue1;
}
public string MyOperation2(DataContract1 dataContractValue)
{
return "Hello: " + dataContractValue.FirstName;
}
}
[DataContract]
public class DataContract1
{
string firstName;
string lastName;
[DataMember]
public string FirstName
{
get { return firstName; }
set { firstName = value; }
}
[DataMember]
public string LastName
{
get { return lastName; }
set { lastName = value; }
}
}
public class MyServiceHostFactory : ServiceHostFactoryBase
{
protected virtual ServiceHost CreateServiceHost(Type serviceType, Uri[] baseAddresses)
{
// Specify the exact URL of your web service
Uri webServiceAddress = new Uri("http://www.mydomain.com/MyService.svc");
MyServiceHost webServiceHost = new MyServiceHost(serviceType, webServiceAddress);
return webServiceHost;
}
public override ServiceHostBase CreateServiceHost(string constructorString, Uri[] baseAddresses)
{
throw new NotImplementedException();
}
}
public class MyServiceHost : ServiceHost
{
public MyServiceHost(Type serviceType, params Uri[] baseAddresses)
: base(serviceType, baseAddresses)
{ }
protected override void ApplyConfiguration()
{
base.ApplyConfiguration();
}
}
I had to switch hosts.
I was originally using DiscountASP.Net and they refused my request to ensure WCF settings were enabled and told me that I needed to hire a developer or follow the MS IIS specs.
(P.S. They didn't know that I'm actually an SDET.)
As a result, I had to switch to another provider (i.e. Winhost).
Things just work now without me having to do any crazy webconfig alterations or ServiceHostFactory coding crap that the previous host wanted me to do that had no success.
I spent 5 days reopening tickets with their tech support until I finally switched to a hosting company that actually supports WCF Services.
Thanks Winhost for ending this dreadful nightmare!
It seemed to be access/configurability problem on remote server then.
Try checking following areas for the deployed service.
Binding of the WCF service is configured correctly, DNS and port (default is 80)
Authentication Mode of service (Anonymous access should be allowed to browser through WSDL)
Permissions granted to the website (directory and user permissions)
If none of them work, then can you list down the steps you followed when service is deployed?

Holding first service call and make second call in WCF from ASP.Net

I have a big doubt in WCF service call from a asp.net application. I implemented duplexchannel and call back contracts. I used conurrency mode is reentrant and instance mode = per session. I can make a call to wcf service and it will trigger the call back method. Untill this point, everything is good.
But i am thinking of a way like, when i make a first call to service, i hold that call in that service method using a waithandler object and triggered the call back method. This call back hits the client side code and again from the client side call another method in the same service class to release that wait handler lock. When i used the wait handler to lock the first call and triggered the call back method, it is calling back to the client side and after that, it is again calling the another method in the same service. But i am getting time out exception...Holding the first call and making second call in the same service is possible ?? I am very new to ASP.Net
[ServiceContract(SessionMode = SessionMode.Required, CallbackContract = typeof(IMyServiceCallBacks))]
public interface IMyService
{
[OperationContract]
string GetData1();
[OperationContract]
void GetData2(bool isOK);
}
public interface IMyServiceCallBacks
{
[OperationContract(IsOneWay = true)]
void MyCallBack();
}
This is the service class
[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerSession, ConcurrencyMode = ConcurrencyMode.Reentrant)]
public class MyService : IMyService
{
EventWaitHandle waitHandle;
bool isook = false;
public MyService()
{
}
string IMyService.GetData1()
{
waitHandle = new EventWaitHandle(false, EventResetMode.AutoReset);
CallMethod();
bool isOK = waitHandle.WaitOne();
return "success";
}
private void CallMethod()
{
OperationContext.Current.GetCallbackChannel<IMyServiceCallBacks>().MyCallBack();
}
public void GetData2(bool isOK)
{
isook = true;
waitHandle.Reset();
}
}
Below is the client side code
[CallbackBehavior(ConcurrencyMode = ConcurrencyMode.Reentrant, UseSynchronizationContext = false, IncludeExceptionDetailInFaults = true)]
public class MyProxyClient : MyService, MyServiceCallback
{
bool isOK;
private MyServiceClient caServiceProxy
private InstanceContext myInstanceContext;
public MyService()
{
myInstanceContext = new InstanceContext(this);
EndpointAddress endPointAddress = new EndpointAddress("http://localhost:2222222/MyWCF1/MyService.svc");
caServiceProxy = new MyServiceClient(myInstanceContext, new WSDualHttpBinding(), endPointAddress);
}
public string GetData1()
{
string hhhh = caServiceProxy.GetData1();
return hhhh;
}
public void GetData2(bool isOK)
{
caServiceProxy.GetData2(isOK); // here it is processing but finally time out
}
// This is the call back
public void MyCallBack()
{
isOK = true;
GetData2(isOK);
}
}
And below is the web config serviceModeltag
<system.serviceModel>
<services>
<service name="MyABService.MyService" behaviorConfiguration="WCFDuplex.Service1Behavior">
<!-- Service Endpoints -->
<endpoint address="" binding="wsDualHttpBinding" contract="MyABService.IMyService">
<identity>
<dns value="localhost"/>
</identity>
</endpoint>
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/>
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="WCFDuplex.Service1Behavior">
<serviceMetadata httpGetEnabled="true"/>
<serviceDebug includeExceptionDetailInFaults="false"/>
</behavior>
</serviceBehaviors>
</behaviors>
I used svcutil to generate proxy.
Any Idea ???
Thanks
1) This is bad idea to rely on unstable channel and hold service method call. Calls shouldn't be long running. Therefore Http duplex based on periodical polling. TCP is better but for this kind of scenario I recommend to use operation with OneWay = true for Method1. Server can register clients, remember/manage states, do some work. And client must choose behavior according to callbacks. You can use AutoResetEvent/ManualResetEvent/TPL infrastructure for that background threads interchange/sync.
2) I'm 90% sure that notifying client with callback inside service method with OneWay = false can cause errors. See for ex. here
I wrote that you can avoid problems by deferring callback (Task.Factory.StartNew/QueueUserWorkItem etc.) to allow method to finish.

WCF/Windows Service not working

I'm trying to create a windows service along with WCF. We don't want to use IIS to handle the proxying of the service. I've gotten the service registered and started. I created a simple console application to call the service, but it times out.
I have a .NET DLL containing functions that call a locally running application to create an alarm record. I created a forms application that uses AlarmLib.dll and it is able to make the call and insert the alarm record.
It appears to be a permissions issue. I get the following exception:
> Unhandled Exception: System.ServiceModel.EndpointNotFoundException:
> Could not co nnect to http://localhost:8000/ServiceModel/service. TCP
> error code 10061: No co nnection could be made because the target
> machine actively refused it 127.0.0.1:
> 8000. ---> System.Net.WebException: Unable to connect to the remote
> server ---> System.Net.Sockets.SocketException: No connection could
> be made because the tar get machine actively refused it
> 127.0.0.1:8000
> at System.Net.Sockets.Socket.DoConnect(EndPoint endPointSnapshot,
> SocketAddre ss socketAddress) at
> System.Net.Sockets.Socket.InternalConnect(EndPoint remoteEP) at
> System.Net.ServicePoint.ConnectSocketInternal(Boolean connectFailure,
> Sock et s4, Socket s6, Socket& socket, IPAddress& address,
> ConnectSocketState state, IAsyncResult asyncResult, Int32 timeout,
> Exception& exception) --- End of inner exception stack trace
> at System.Net.HttpWebRequest.GetRequestStream(TransportContext&
> context) at System.Net.HttpWebRequest.GetRequestStream() at
> System.ServiceModel.Channels.HttpOutput.WebRequestHttpOutput.GetOutputStre
> am() --- End of inner exception stack trace ---
I ran VS2010 as an administrator. Any other settings for the service that I can modify?
Thanks,
John
Windows service code:
using System.ServiceProcess;
using System.Text;
using System.ServiceModel;
using System.Configuration;
using System.Configuration.Install;
using AlarmLib;
namespace Test.ServiceModel
.WindowsServices {
//
Define a service contract.
[ServiceContract(Namespace = "http://ServiceModel.WindowsServices")]
public interface IAlarmLib {
[OperationContract]
bool CreateNoDataAlarm(string well, string run, string record, string description, string selectedVariable);
}
// Implement the IAlarmLib service contract in a service class.
public class AlarmLibService : IAlarmLib {
// Implement the IAlarmLib methods.
public bool CreateNoDataAlarm(string well, string run, string record, string description, string sel
ectedVariable) {
AlarmUserConfiguration newalarm = new AlarmUserConfiguration();
// The Machine name should be the machine which is running the client application
// and which calls the webservice. This should not be the name of machine hosting
// webservice.
newalarm.MachineName = System.Environment.MachineName;
newalarm.AlarmType = AlarmTypes.NoData;
newalarm.TimeInSeconds = 30;
DateTime CreationTime = DateTime.Now;
newalarm.Name = "NoDataAlarm " + CreationTime.ToString();
PrimaryKey key = new PrimaryKey();
key.Well = "Well ID 1";
key.Run = "1600";
key.Record = "DGR";
key.Desc = "Realtime";
key.SelectedVariable = "Gamma Ray A";
newalarm.PrimaryKeys = key;
// Add any of the following activities.
/*"All"
"Trip Out"
"Trip In"
"Circulating"
"Drilling On Bottom"
"Drilling Off Bottom"*/
newalarm.TDActivities.Add("Drilling On Bottom");
bool bStatus = AlarmUtilities.AddNewAlarm(newalarm, "-Local-");
return bStatus;
}
}
public class AlarmLibWindowsService : ServiceBase {
public ServiceHost serviceHost = null;
public AlarmLibWindowsService() {
// Name the Windows Service
ServiceName = "AlarmLibWS";
}
public static void Main() {
ServiceBase.Run(new AlarmLibWindowsService());
}
// Start the Windows service.
protected override void OnStart(string[] args) {
if (serviceHost != null) {
serviceHost.Close();
}
// Create a ServiceHost for the AlarmLibService type and
// provide the base address.
serviceHost = new ServiceHost(typeof(AlarmLibService));
// Open the ServiceHostBase to create listeners and start
// listening for messages.
serviceHost.Open();
}
protected override void OnStop() {
if (serviceHost != null) {
serviceHost.Close();
serviceHost = null;
}
}
}
// Provide the ProjectInstaller class which allows
// the service to be installed by the Installutil.exe tool
[RunInstaller(true)]
public class ProjectInstaller : Installer {
private ServiceProcessInstaller process;
private ServiceInstaller service;
public ProjectInstaller() {
process = new ServiceProcessInstaller();
process.Account = ServiceAccount.LocalSystem;
service = new ServiceInstaller();
service.ServiceName = "AlarmLibWS";
Installers.Add(process);
Installers.Add(service);
}
}
}
App.config:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<system.serviceModel>
<services>
<!-- This section is optional with the new configuration model
introduced in .NET Framework 4. -->
<service name="ServiceModel.WindowsServices.AlarmLibService" behaviorConfiguration="AlarmLibServiceBehavior">
<host>
<baseAddresses>
<add baseAddress="http://localhost:8000/ServiceModel/service"/>
</baseAddresses>
</host>
<!-- this endpoint is exposed at the base address provided by host: http://localhost:8000/ServiceModel/service -->
<endpoint address=""
binding="wsHttpBinding"
contract="ServiceModel.WindowsServices.IAlarmLib" />
<!-- the mex endpoint is exposed at http://localhost:8000/ServiceModel/service/mex -->
<endpoint address="mex"
binding="mexHttpBinding"
contract="IMetadataExchange" />
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="AlarmLibServiceBehavior">
<serviceMetadata httpGetEnabled="true"/>
<serviceDebug includeExceptionDetailInFaults="False"/>
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>
</configuration>
Console app:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace TestAlarmLibConsoleApp {
class Program {
static void Main(string[] args) {
ServiceReference1.AlarmLibClient client = new ServiceReference1.AlarmLibClient();
bool result = client.CreateNoDataAlarm("Well ID 1", "1100", "DGR", "Realtime", "Gamma Ray A");
Console.WriteLine("result = " + bool.TrueString);
}
}
}
Here is the code in forms app that works:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows.Forms;
using AlarmLib;
namespace TestCallingAlarmLib {
static class Program {
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main() {
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
bool result = CreateNoDataAlarm();
Application.Run(new Form1());
}
static bool CreateNoDataAlarm() {
AlarmUserConfiguration newalarm = new AlarmUserConfiguration();
// The Machine name should be the machine which is running the client application
// and which calls the webservice. This should not be the name of machine hosting
// webservice.
newalarm.MachineName = System.Environment.MachineName;
newalarm.AlarmType = AlarmTypes.NoData;
newalarm.TimeInSeconds = 30;
DateTime CreationTime = DateTime.Now;
newalarm.Name = "NoDataAlarm " + CreationTime.ToString();
PrimaryKey key = new PrimaryKey();
key.Well = "Well ID 1";
key.Run = "1100";
key.Record = "DGR";
key.Desc = "Realtime";
key.SelectedVariable = "Gamma Ray A";
newalarm.PrimaryKeys = key;
// Add any of the following activities.
/*"All"
"Trip Out"
"Trip In"
"Circulating"
"Drilling On Bottom"
"Drilling Off Bottom"*/
newalarm.TDActivities.Add("Drilling On Bottom");
bool bStatus = AlarmUtilities.AddNewAlarm(newalarm, "-Local-");
return bStatus;
}
}
}
Check your Client Access Policy, make sure you have the ports opened up on the server and double check your firewall. Every single time I get this error it's related to one of those.

Duplex WCF service - Direct call and callback do not use same channel

My goal is to reach a WCF service behind a firewall with no incoming ports opened.
The solution I chose is to host a duplex WCF service on the public side, that has as callback the same contract that was used if no firewall was involved.
It worked if I used netTcpBinding but since I need streamed communication I had to use the custom binding.
Everything works fine until I raise up the firewall. At that point, the direct call (from behind the firewall out) works fine, but the callback does not (firewall stops it).
The question is WHY? Shoudn't they use the same channel as for the predefined netTcpBinding?
Here is my channels stack in app.config:
<customBinding>
<binding name="ReversedServiceBinding">
<compositeDuplex />
<oneWay />
<binaryMessageEncoding />
<tcpTransport transferMode="Streamed" />
</binding>
</customBinding>
Actual behavior is correct. You have used compositeDuplex binding element - the meaning of composite word is exactly what you get - two separate channels each working for one direction. Composite duplex is needed only for transport channel which doesn't support duplex communication by default. That is not the case for TCP transport channel - check remarks. If you don't use compositeDuplex it should work like you have expected. Also there is no need to define whole new custom binding to allow streamed transport. NetTcpBinding also has TransportMode property which can be specified in configuration.
EDIT:
I have prepared working example with Net.TCP duplex communication. It doesn't use streaming. You are right that streaming is not possible when duplex TCP communication is used. You can try to combine duplex communication with chunking channel or check WCF Xtensions (commercial product).
Shared contracts
namespace NetTcpDuplexContracts
{
[ServiceContract(SessionMode = SessionMode.Required,
CallbackContract = typeof(IDuplexServiceCallback))]
public interface IDuplexService
{
[OperationContract(IsOneWay = true)]
void DoAction(string message);
}
public interface IDuplexServiceCallback
{
[OperationContract(IsOneWay = true)]
void ConfirmAction(string message);
}
}
Service and host
namespace NetTcpDuplexService
{
public class DuplexService : IDuplexService
{
public void DoAction(string message)
{
Console.WriteLine("DoAction: " + message);
var callbackChannel =
OperationContext.Current.GetCallbackChannel<IDuplexServiceCallback>();
callbackChannel.ConfirmAction("Ping back " + message);
}
}
class Program
{
public static void Main(string[] args)
{
try
{
using (var host = new ServiceHost(typeof(DuplexService)))
{
host.Open();
Console.ReadLine();
}
}
catch (Exception e)
{
Console.WriteLine(e.Message);
Console.ReadLine();
}
}
}
}
Service configuration
<configuration>
<system.serviceModel>
<services>
<service name="NetTcpDuplexService.DuplexService">
<host>
<baseAddresses>
<add baseAddress="net.tcp://localhost:8800/NetTcpDuplexService"/>
</baseAddresses>
</host>
<endpoint address="" binding="netTcpBinding" contract="NetTcpDuplexContracts.IDuplexService" />
</service>
</services>
</system.serviceModel>
</configuration>
Callback and client
namespace NetTcpDuplexClient
{
public class DuplexServiceCallback : IDuplexServiceCallback
{
public void ConfirmAction(string message)
{
Console.WriteLine(message);
}
}
class Program
{
public static void Main(string[] args)
{
DuplexChannelFactory<IDuplexService> factory = null;
try
{
var callbackService = new DuplexServiceCallback();
var context = new InstanceContext(callbackService);
factory = new DuplexChannelFactory<IDuplexService>(context, "IDuplexService_NetTcp");
var channel = factory.CreateChannel();
channel.DoAction("Hello world");
factory.Close();
Console.ReadLine();
}
catch (Exception e)
{
if (factory != null && factory.State != CommunicationState.Closed)
{
factory.Abort();
}
Console.WriteLine(e.Message);
Console.ReadLine();
}
}
}
}
Client configration
<configuration>
<system.serviceModel>
<client>
<endpoint name="IDuplexService_NetTcp" address="net.tcp://localhost:8800/NetTcpDuplexService" binding="netTcpBinding"
contract="NetTcpDuplexContracts.IDuplexService" />
</client>
</system.serviceModel>
</configuration>