WCF:ArgumentException:TransactionFlowProperty 已经存在
WCF : ArgumentException : TransactionFlowProperty already exists
我有一个带有点对点绑定的自托管 WCF 服务。我正在使用 DuplexChannel 来获取响应。与 ServiceHost 的连接正常,但是当调用回调时,我得到上面提到的 ArgumentException
,即使我没有使用任何 TransactionFlowProperties。
[ServiceContract(SessionMode = SessionMode.Allowed, CallbackContract = typeof(ICallbackService))]
public interface IService
{
[OperationContract(IsOneWay = true)]
void Login(string email, string password);
[OperationContract(IsOneWay = true)]
void Logout(int userId);
}
[DataContract]
public class User
{
[DataMember]
public string Email {get; set;}
[DataContract]
public string Password {get; set;}
}
我的 IService 实现:
[ServiceBehavior(InstanceContextMode = InstanceContextMode.Single, ConcurrencyMode = ConcurrencyMode.Multiple)]
public class Service : IService
{
private static Dictionary<ICallbackService, ICallbackService> pair = new Dictionary<ICallbackService, ICallbackService>();
private static Dictionary<string, ICallbackService> clients = new Dictionary<string, ICallbackService>();
private ICallbackService callback;
public Service(){}
public void Login(string email, string password)
{
// User user = getAllUsers().Find(u => u.Email.ToLower() == email.ToLower() && u.Password == password);
User user = new User(){Email = email, Password = password}; //for testing purposes
callback = OperationContext.Current.GetCallbackChannel<ICallbackService>();
if (user != null)
{
Console.WriteLine("user : " + email + " has logged in");
clients.Add(email, callback);
callback.Authenticate(true);
}
else callback.Authenticate(false);
}
public void Logout(int userId)
{
//TODO
}
}
我的回拨服务:
public interface ICallbackService
{
[OperationContract(IsOneWay = true)]
void Authenticate(bool authenticated);
}
在我的客户端应用程序中实现回调服务 class:
[CallbackBehavior(ConcurrencyMode = ConcurrencyMode.Single, UseSynchronizationContext = false)]
public class Client : Service.ICallbackService,
{
public bool Authentication { get; internal set; }
public Client()
{
}
public void Authenticate(bool authenticated)
{
Console.WriteLine("authentication : " + authenticated);
Authentication = authenticated;
}
}
代理 class 和用户 class 在单独的客户端应用程序中:
public class Proxy : IService
{
public Proxy(InstanceContext context)
{
init(context);
}
private void init(InstanceContext context)
{
NetTcpBinding binding = new NetTcpBinding();
binding.Security.Mode = SecurityMode.None;
binding.Security.Mode = SecurityMode.Transport;
// binding.CloseTimeout = TimeSpan.FromSeconds(1);
// binding.OpenTimeout = TimeSpan.FromSeconds(2);
// binding.ReceiveTimeout = TimeSpan.FromSeconds(15);
// binding.SendTimeout = TimeSpan.FromSeconds(15);
DuplexChannelFactory<IService> channel = new DuplexChannelFactory<IService>(context, binding, new EndpointAddress("net.tcp://localhost:4242"));
service = channel.CreateChannel();
}
public void Login(string email, string password)
{
service.Login(email, password);
}
public void Logout(int id)
{
service.Logout(id);
}
}
public class User
{
Client client;
IService service;
public User()
{
client = new Client();
InstanceContext context = new InstanceContext(client);
service = new Proxy(context);
}
public void Login(string email, string password)
{
service.Login(email, password);
bool valid = client.Authentication;
if(valid) Console.WriteLine("Login successful");
}
}
这是我在服务器应用程序中启动 ServiceHost 的方式:
public class Server
{
public static void Main(string[] args)
{
Service service = new Service();
ServiceHost host = host = new ServiceHost(service, new Uri("net.tcp://localhost:4242"));
host.Open();
Console.WriteLine("opened server ...");
Console.ReadLine();
}
}
我使用 NetTcpBinding
解决了这个问题。上面的代码现在可以工作了。
我有一个带有点对点绑定的自托管 WCF 服务。我正在使用 DuplexChannel 来获取响应。与 ServiceHost 的连接正常,但是当调用回调时,我得到上面提到的 ArgumentException
,即使我没有使用任何 TransactionFlowProperties。
[ServiceContract(SessionMode = SessionMode.Allowed, CallbackContract = typeof(ICallbackService))]
public interface IService
{
[OperationContract(IsOneWay = true)]
void Login(string email, string password);
[OperationContract(IsOneWay = true)]
void Logout(int userId);
}
[DataContract]
public class User
{
[DataMember]
public string Email {get; set;}
[DataContract]
public string Password {get; set;}
}
我的 IService 实现:
[ServiceBehavior(InstanceContextMode = InstanceContextMode.Single, ConcurrencyMode = ConcurrencyMode.Multiple)]
public class Service : IService
{
private static Dictionary<ICallbackService, ICallbackService> pair = new Dictionary<ICallbackService, ICallbackService>();
private static Dictionary<string, ICallbackService> clients = new Dictionary<string, ICallbackService>();
private ICallbackService callback;
public Service(){}
public void Login(string email, string password)
{
// User user = getAllUsers().Find(u => u.Email.ToLower() == email.ToLower() && u.Password == password);
User user = new User(){Email = email, Password = password}; //for testing purposes
callback = OperationContext.Current.GetCallbackChannel<ICallbackService>();
if (user != null)
{
Console.WriteLine("user : " + email + " has logged in");
clients.Add(email, callback);
callback.Authenticate(true);
}
else callback.Authenticate(false);
}
public void Logout(int userId)
{
//TODO
}
}
我的回拨服务:
public interface ICallbackService
{
[OperationContract(IsOneWay = true)]
void Authenticate(bool authenticated);
}
在我的客户端应用程序中实现回调服务 class:
[CallbackBehavior(ConcurrencyMode = ConcurrencyMode.Single, UseSynchronizationContext = false)]
public class Client : Service.ICallbackService,
{
public bool Authentication { get; internal set; }
public Client()
{
}
public void Authenticate(bool authenticated)
{
Console.WriteLine("authentication : " + authenticated);
Authentication = authenticated;
}
}
代理 class 和用户 class 在单独的客户端应用程序中:
public class Proxy : IService
{
public Proxy(InstanceContext context)
{
init(context);
}
private void init(InstanceContext context)
{
NetTcpBinding binding = new NetTcpBinding();
binding.Security.Mode = SecurityMode.None;
binding.Security.Mode = SecurityMode.Transport;
// binding.CloseTimeout = TimeSpan.FromSeconds(1);
// binding.OpenTimeout = TimeSpan.FromSeconds(2);
// binding.ReceiveTimeout = TimeSpan.FromSeconds(15);
// binding.SendTimeout = TimeSpan.FromSeconds(15);
DuplexChannelFactory<IService> channel = new DuplexChannelFactory<IService>(context, binding, new EndpointAddress("net.tcp://localhost:4242"));
service = channel.CreateChannel();
}
public void Login(string email, string password)
{
service.Login(email, password);
}
public void Logout(int id)
{
service.Logout(id);
}
}
public class User
{
Client client;
IService service;
public User()
{
client = new Client();
InstanceContext context = new InstanceContext(client);
service = new Proxy(context);
}
public void Login(string email, string password)
{
service.Login(email, password);
bool valid = client.Authentication;
if(valid) Console.WriteLine("Login successful");
}
}
这是我在服务器应用程序中启动 ServiceHost 的方式:
public class Server
{
public static void Main(string[] args)
{
Service service = new Service();
ServiceHost host = host = new ServiceHost(service, new Uri("net.tcp://localhost:4242"));
host.Open();
Console.WriteLine("opened server ...");
Console.ReadLine();
}
}
我使用 NetTcpBinding
解决了这个问题。上面的代码现在可以工作了。