использование WCF Callback и asp.net для реализации шаблона публикации / подписки - PullRequest
1 голос
/ 01 марта 2011

Это мое первое веб-приложение с WCF. Поэтому, пожалуйста, ведите меня как новый парень.

Я пытаюсь использовать функцию обратного вызова WCF для реализации шаблона публикации / подписки. Я хотел бы отправить сообщение от UserA к UserB или UserA каждому клиенту в данный момент. Я получил пример от здесь .

В своем приложении я использую ASP.NET в качестве клиента для подключения службы WCF, и обнаружил проблему при подписке на службу WCF.

Служба WCF не содержит никаких других объектов клиентов. Поэтому, когда я звоню GetAllClients(_guid), он вернет только 1 клиента, который сам по себе.

Вот код на странице 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

}

Здесь указаны IService и Service на WCF соответственно.

[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 для вызова метода обратного вызова.

Спасибо.

1 Ответ

5 голосов
/ 01 марта 2011

Я не знаю, почему у вас нет списка клиентов - вы должны это сделать, но с вашим кодом проблемы гораздо хуже.

Вы не можете использовать обратный вызов WCF в приложении ASP.NET. Это не может работать, потому что страница живет только для обслуживания одного HTTP-запроса - это означает, что она, скорее всего, живет только долю секунды, а также вашу регистрацию. Даже если вы сможете получить список клиентов, вы не сможете звонить OnRegister или OnMessageSending, потому что прокси-сервер не будет прослушивать эти вызовы.

Даже если вы заставите прокси работать после обработки запроса, он все равно будет уведомлять только код, а не ваши страницы, отображаемые в клиентском браузере.

Другая проблема заключается в том, что он может работать только с привязкой net.pipe или net.tcp. Это не будет работать с wsDualHttp. При использовании wsDualHttp очень проблематично открыть несколько дуплексных клиентов с одного компьютера.

Вы делаете это совершенно неправильно. Что вам нужно, так это опрос AJAX из клиентского браузера на asp.net, который вызовет простой сервис в вашей системе чата.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...