Reputation: 143
I am currently making a WCF-WPF app where multiple clients can connect to a chatroom. I am nearly there except for the most important part. Whenever I start the host, I can get one client to connect and every message is received and sent shown on the client's GUI. However, whenever I try to connect with a second client, that client's program crashes with a System.ServiceModel.CommunicationObjectFaultedException.
I have no idea what I'm doing wrong and was hoping an experienced programmer here could help me. out.
This is my WCF Service:
[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerSession)]
public class Service1 : IService1
{
private static Dictionary<string, IService1Callback> clients = new Dictionary<string, IService1Callback>();
public Service1()
{
}
public void SendMessage(Message m)
{
Console.WriteLine("Sent by: " + m.User);
Console.WriteLine(m.Content);
Console.WriteLine("");
foreach (var client in clients)
{
client.Value.SendMessageToClients(m);
}
}
public void RegisterClient()
{
IService1Callback callback = OperationContext.Current.GetCallbackChannel<IService1Callback>();
clients.Add("Client", callback);
}
}
My client app is a WPF project with some already generated components. the xaml.cs file looks like this:
public partial class MainWindow : Window
{
Service1Client s;
public MainWindow()
{
InitializeComponent();
InstanceContext site = new InstanceContext(new CallbackHandler(txtAllMessages));
s = new Service1Client(site);
s.RegisterClient();
}
private void Button_Click(object sender, RoutedEventArgs e)
{
Message m = new Message();
m.Content = txtMessage.Text;
m.User = txtName.Text;
s.SendMessage(m);
}
public class CallbackHandler : IService1Callback
{
public TextBox txtValue { get; set; }
public CallbackHandler(TextBox tb)
{
this.txtValue = tb;
}
public void SendMessageToClients(Message m)
{
txtValue.Text += "Sent by: " + m.User + "\n";
txtValue.Text += m.Content + "\n\n";
}
}
}
If anybody is able to help me out with this that would be awesome. Thanks a lot!
Upvotes: 0
Views: 1578
Reputation: 2535
I suggest to get the sessionId of the current context and insure no same session with same callback will be registered in your storage.
public void RegisterClient()
{
IService1Callback callback = OperationContext.Current.GetCallbackChannel<IService1Callback>();
var sessionId = OperationContext.Current.SessionId;
if (!clients.ContainsKey(sessionId))
{
clients.Add(sessionId, callback);
}
}
The above approach will give you an advantage to keep track who's session is tied up to existing callback and at the same time it avoid registering duplicate callbacks in same user, which is already registered. SessionId is unique per connected user. "assuming that you are using duplex message exchange pattern"
Upvotes: 1
Reputation: 10764
The problem is caused by the RegisterClient
method trying to add multiple Dictionary
entries with the same key ("Client"). Each entry in the dictionary must have a unique key.
Try this:
clients.Add(Guid.NewGuid().ToString(), callback);
Upvotes: 0