简体   繁体   English

SignalR如何在Web API中工作

[英]how SignalR works in Web API

I'm working in SignalR chat project like this example 我正在像这个例子一样在SignalR聊天项目中工作

It works well however, I want to make chat hub.cs in a Web API project and call it from other client projects. 但是它运行良好,我想在Web API项目中创建chat hub.cs并从其他客户端项目中调用它。

I have searched for solutions but haven't found any. 我已经搜索了解决方案,但没有找到任何解决方案。 How do I achieve this. 我该如何实现。

My chatHub 我的chatHub

public class ChatHub : Hub
{
        dbcontext db = new dbcontext();
        ChatManager chatManager = new ChatManager();
    public static string ConnectionId = null;

    public void Send(string name, string message)
    {
        ConnectedUsers cu = chatManager.getCurrentUserRow(Context.ConnectionId);

        if (cu != null)
        {
            string L_ConnectionId = cu.Other_ConnectionId;

            Clients.Client(L_ConnectionId)
                .addNewMessageToPage(name, message);
        }
    }
    public override Task OnConnected()
    {
        Console.WriteLine("Connected user: " + Context.User.Identity.Name);
        ConnectionId = Context.ConnectionId;
        chatManager.AddAndRemoveUser(true, Context.ConnectionId); // to add user in connectedUser Table
        chatManager.OpenRandomChat(Context.ConnectionId);

        return base.OnConnected();
    }
    public override Task OnDisconnected(bool stopCalled)
    {
        chatManager.RemoveLeftUser(Context.ConnectionId);
        chatManager.AddAndRemoveUser(false, Context.ConnectionId);
        return base.OnDisconnected(stopCalled);
    }
    public override Task OnReconnected()
    {
        Console.WriteLine("ReConnected user: " + Context.User.Identity.Name);
        return base.OnReconnected();
    }
    public void NewConnection()
    {
        int retVal = -1;
        chatManager.RemoveLeftUser(Context.ConnectionId); // to remove left user from 2 users
        chatManager.OpenRandomChat(Context.ConnectionId); // to chosse random user for me 

        // to get me and my if i have partner ..
        ConnectedUsers cu = chatManager.getCurrentUserRow(Context.ConnectionId);

        if (cu != null)
        {
            retVal = 0;
            //string groupId = cu.ConnectionId + cu.Other_ConnectionId;
            //string R_ConnectionId = cu.ConnectionId;
            string L_ConnectionId = cu.Other_ConnectionId;
        }
        Clients.Client(Context.ConnectionId)
              .sendGroupData(retVal);
    }

    public void SendQuestion(string question)
    {
        ConnectedUsers cu = chatManager.getCurrentUserRow(Context.ConnectionId);
        if (cu != null)
        {
            string L_ConnectionId = cu.Other_ConnectionId;
            Clients.Client(L_ConnectionId)
                .sendQuestion(question);
        }
    }
    public void AnswerQuestion(string answer)
    {
        ConnectedUsers cu = chatManager.getCurrentUserRow(Context.ConnectionId);
        if (cu != null)
        {
            string L_ConnectionId = cu.Other_ConnectionId;

            Clients.Client(L_ConnectionId)
                .answerQuestion(answer);
        }
    }
}

I created a separate class library that I include and use in any of my other projects, works great and gives access to a single reusable Hub. 我创建了一个单独的类库,该类库在我的任何其他项目中都包含和使用,效果很好,并且可以访问单个可重用的Hub。 I use mine for order notifications. 我使用我的订单通知。

 namespace MyProjects.SignalR.Hubs
{
    public class OrdersHub : Hub
    {


        public void OrderDeleted(int manufacturerId, int orderId)
        {
            Clients.Group(OrdersGroup(manufacturerId)).BroadcastOrder(orderId);
        }


        public Task JoinOrders(int manufacturerId)
        {
            return Groups.Add(Context.ConnectionId, OrdersGroup(manufacturerId));
        }

        private string OrdersGroup(int manufacturerId)
        {
            return "orders" + manufacturerId;
        }

    }
}

Then in any of my other projects that use this I simply call: 然后,在其他任何使用此功能的项目中,我只需调用:

var ordersHubContext = GlobalHost.ConnectionManager.GetHubContext<OrdersHub>();
ordersHubContext.Clients.All.OrderDeleted(order.ManufacturerID, order.OrderID);

ChatManager chatManager = new ChatManager();

You can´t do that within a Hub. 您无法在集线器中执行此操作。 Hubs instances are not persistent, they are re-created on every single request, and so does your ChatManager . 集线器实例不是持久性的,它们是在每个单个请求上都重新创建的,您的ChatManager也是如此。

To make that work, convert your ChatManager to a Lazy Singleton. 为此,请将您的ChatManager转换为Lazy单例。 The aim of using Lazy in this case is to make it thread safe (pretty neat for SignalR): 在这种情况下使用Lazy的目的是使其线程安全(对于SignalR而言,它非常简洁):

public sealed class ChatManager
{
    private static readonly Lazy< ChatManager > lazy =
        new Lazy< ChatManager >(() => new ChatManager());

    public static ChatManager Instance { get { return lazy.Value; } }

    private ChatManager()
    {
    }

    // TODO add your methods here
}

Then, from your hub: 然后,从您的中心:

ChatManager.Instance.AddAndRemoveUser(true, Context.ConnectionId);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM