使用WCF Callback和asp.net实现发布/订阅模式

时间:2011-03-01 16:10:52

标签: asp.net wcf callback publish-subscribe

这是我第一个使用WCF的Web应用程序。所以请指导我作为一个新人。

我正在尝试使用WCF Callback来实现发布/订阅模式。我想将UserA的消息从UserB发送给UserB或UserA。我从here得到了一个例子。

在我的应用程序中,我使用ASP.NET作为客户端来连接WCF服务,我在订阅WCF服务时发现了一个问题。

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

以下是ASP.NET页面中的代码(我将每个控件放在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

}

以下是WCF上的IServiceService

[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();
    }

    ...
}

问题是:

  1. 是否可以使用ASP.NET和WCF回调实现此发布/订阅? (我已经尝试过使用窗口应用程序并且工作正常)

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

  3. 谢谢。

1 个答案:

答案 0 :(得分:5)

我不知道为什么你没有获得客户列表 - 你应该但是你的代码存在更糟糕的问题。

您无法在ASP.NET应用程序中使用WCF回调。它无法工作,因为页面仅用于提供单个HTTP请求 - 这意味着它最有可能仅在几分之一秒内生存,因此您的注册也是如此。即使您能够获得客户列表,也无法拨打OnRegisterOnMessageSending,因为没有代理会听取这些来电。

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

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

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