使用WCF回调和asp.net实现发布/订阅模式的问题 [英] problem with using WCF Callback and asp.net to implement publish/subscribe pattern

查看:197
本文介绍了使用WCF回调和asp.net实现发布/订阅模式的问题的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这是我的第一个web应用程序与wcf。所以请指导我作为一个新的家伙。



我试图使用WCF回调来实现发布/订阅模式。我想将消息从UserA发送到UserB或UserA到每个客户端。我有一个来自这里的示例



在我的应用程序中,我使用asp.net作为客户端连接wcf服务,而我发现一个问题,当我订阅wcf服务。



wcf服务不包含任何其他客户端对象。所以当我调用GetAllClients(_guid),它将只返回一个客户端本身。



这里是asp.net页面的代码(我把每个控件内部updatePanel )

  public partial class _Default:System.Web.UI.Page,AlertServiceCallback 
{
private AlertServiceClient _客户;
private Guid _guid = Guid.NewGuid();

protected void Page_Load(object sender,EventArgs e)
{
InstanceContext context = new InstanceContext(this);
_client = new AlertServiceClient(context);
_client.RegisterClient(_guid);
}

protected void btnGetClients_Click(object sender,EventArgs e)
{
//尝试退出所有活动客户端
Client [] cs = _client .GetAllClients(_guid);
List< Client> list = new List< Client>(cs);
//绑定到dropDownList以显示所有活动的客户端
ddlClients.DataSource = list;
ddlClients.DataBind();
}

#regionCallBack

public void OnRegister(string message)
{
throw new NotImplementedException();
}

public void OnMessageSending(string message)
{
throw new NotImplementedException();
}

#endregion

}

这里是WCF上的IService和服务。

  [ServiceContract(Name =AlertService,Namespace =http ://www.testWcf.com/,
CallbackContract = typeof(IAlertCallBack),SessionMode = SessionMode.Required)]
public interface IAlertService
{
[OperationContract(IsOneWay = true)]
void RegisterClient(Guid id,string name);

[OperationContract(IsOneWay = false)]
List< Client> GetAllClients(Guid id);

[OperationContract(IsOneWay = true)]
void SendMessage(Guid fromId,Guid toId,string message);
}

public interface IAlertCallBack
{
[OperationContract(IsOneWay = true)]
void OnRegister(string message);

[OperationContract(IsOneWay = true)]
void OnMessageSending(string message);
}


public class AlertService:IAlertService
{

private object locker = new object();

私人字典< Client,IAlertCallBack> clients = new Dictionary< Client,IAlertCallBack>();

public AlertService(){}

public void RegisterClient(Guid guid)
{
IAlertCallBack callback = OperationContext.Current.GetCallbackChannel< IAlertCallBack> );

// ---防止多个客户端同时添加---
lock(locker)
{
clients.Add(new Client {Id = guid,Name = name},callback);
}

}

public List< Client> GetAllClients(Guid guid)
{
// ---获取字典中的所有客户端 -
return(from c in clients
其中c.Key.Id!= guid
选择c.Key).ToList();
}

...
}

问题是:


  1. 是否可以使用asp.net和wcf回调实现这个发布/ (我已经尝试了窗口应用程序,它工作正常)


  2. 如果可能,如何保持所有客户端连接到WCF服务,使用这些GuId调用回调方法。


谢谢。

解决方案

我不知道你为什么没有得到客户名单 - 你应该,但你的代码有更糟糕的问题。



您不能在ASP.NET应用程序中使用WCF回调。它不能工作,因为页面只为服务单个HTTP请求 - 这意味着它很可能生活只有几分之一秒,所以也注册。即使您将能够获得客户列表,您将无法调用 OnRegister OnMessageSending ,因为会有



即使强制代理在请求处理后生效,它仍然只会通知后面的代码,而不是您的网页在客户端浏览器中呈现。

另一个问题是它只能与net.pipe或net.tcp绑定一起工作。它不能与wsDualHttp一起使用。在使用wsDualHttp时,从同一台机器打开多个双工客户端非常有问题。



你做的完全错了。你需要的是从客户端浏览器到asp.net的AJAX轮询,将在您的聊天系统中调用简单的服务。


This is my first web application with wcf. so please guide me as a new guy.

I'm trying to use WCF Callback to implement publish/subscribe pattern. I would like to send the message from UserA to UserB or UserA to every clients at the moment. I got an example from here

In my app, I use asp.net as a client to connect wcf service instead and I found a problem when I subscrib to wcf service.

The wcf service does not hold any other clients object. So when I call GetAllClients(_guid), It will return only 1 client which is itself.

Here is the code in asp.net page (i put every control inside updatePanel)

public partial class _Default : System.Web.UI.Page, AlertServiceCallback
{
    private AlertServiceClient _client;
    private Guid _guid = Guid.NewGuid();

    protected void Page_Load(object sender, EventArgs e)
    {
        InstanceContext context = new InstanceContext(this);
        _client = new AlertServiceClient(context);
        _client.RegisterClient(_guid);
    }

    protected void btnGetClients_Click(object sender, EventArgs e)
    {
        //Try to retrive all active clients
        Client[] cs = _client.GetAllClients(_guid);
        List<Client> list = new List<Client>(cs);
        //Bind to dropDownList to display all active clients
        ddlClients.DataSource = list;
        ddlClients.DataBind();
    }

    #region "CallBack"

    public void OnRegister(string message)
    {
        throw new NotImplementedException();
    }

    public void OnMessageSending(string message)
    {
        throw new NotImplementedException();
    }

    #endregion

}

Here is the IService and Service on WCF respectively.

[ServiceContract(Name = "AlertService",Namespace = "http://www.testWcf.com/",
CallbackContract = typeof(IAlertCallBack),SessionMode = SessionMode.Required)]
public interface IAlertService
{       
    [OperationContract(IsOneWay = true)]
    void RegisterClient(Guid id, string name);

    [OperationContract(IsOneWay = false)]
    List<Client> GetAllClients(Guid id);

    [OperationContract(IsOneWay = true)]
    void SendMessage(Guid fromId, Guid toId, string message);
}

public interface IAlertCallBack
{
    [OperationContract(IsOneWay = true)]
    void OnRegister(string message);

    [OperationContract(IsOneWay = true)]
    void OnMessageSending(string message);
}


public class AlertService : IAlertService
{

    private object locker = new object();

    private Dictionary<Client, IAlertCallBack> clients = new Dictionary<Client, IAlertCallBack>();

    public AlertService() { }

    public void RegisterClient(Guid guid)
    {
        IAlertCallBack callback = OperationContext.Current.GetCallbackChannel<IAlertCallBack>();

        //---prevent multiple clients adding at the same time---
        lock (locker)
        {
            clients.Add(new Client { Id = guid, Name = name }, callback);
        }

    }

    public List<Client> GetAllClients(Guid guid)
    {
        //---get all the clients in dictionary---
        return (from c in clients
                where c.Key.Id != guid
                select c.Key).ToList();
    }

    ...
}

Questions are:

  1. Is it possible to implement this publish/subscribe with asp.net and wcf callback? (I already tried on window app and it worked fine)

  2. If it is possible, how can I keep all clients that is connecting to WCF Service so I can use those GuId to call callback method.

Thank you.

解决方案

I don't know why you don't get list of clients - you should but there are much worse problems with your code.

You can't use WCF callback in ASP.NET application. It cannot work because page lives only to serve single HTTP request - it means it most probably lives only for fraction of second and so also your registration. Even If you will be able to get list of clients you will not be able to call OnRegister or OnMessageSending because there will be no proxy listening for these calls.

Even if you force proxy to live after request processing it will still notify only code behind, not your pages rendered in client browser.

Another problem is that it can work only with net.pipe or net.tcp binding. It will not work with wsDualHttp. It is very problematic to open multiple duplex clients from the same machine when using wsDualHttp.

You are doing it completely wrong. What you need is AJAX polling from client browser to asp.net which will call simple service in your chat system.

这篇关于使用WCF回调和asp.net实现发布/订阅模式的问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆