使用 WinForms 和 Framework 4.8 MVC 的 Signalr

bru*_*iow 2 .net asp.net-mvc winforms signalr

我正在尝试使用信号器作为通知者创建一个作业通知流程。我的情况是,我有一个 winforms 项目,它将控制流程的各个阶段。MVC 项目中流程影响的系统。

目前我有这些项目: 流程(Winforms)系统(框架4.8 MVC)服务(框架4.8)SignalRSelfHost(控制台)

服务层由流程和系统项目引用,并包含流程每个步骤的逻辑。当一个阶段开始或结束时,它需要调用连接的客户端并让他们知道。

我最初在系统项目中创建了信号器内容,并且能够从页面上的按钮调用服务方法,并按预期传递开始/结束消息。然后我创建了 winforms 应用程序并调用了相同的服务方法。当我这样做时,没有消息发送到网络客户端。

值得一提的是,winforms 项目对 signalr 一无所知,它被留给服务使用以下方式与 signalr 进行协商:

            var context = GlobalHost.ConnectionManager.GetHubContext<ProcessHub>();
            context.Clients.All.StageStarted(stage.started);
Run Code Online (Sandbox Code Playgroud)

然后我突然意识到,即使进入该服务的两条路由运行相同的代码,但它们创建的集线器可能是独立的,永远不会作为一个整体进行通信。

所以我想也许我需要一个与系统和进程端分开的通用信号服务器,两者都可以使用。我创建了一个注释控制台应用程序,它将充当自主机,然后运行为:

http://localhost:8080
Run Code Online (Sandbox Code Playgroud)

然后我可以重新指向我的脚本标签以查找该 URL,而不是 Web 端的 ../signalr。

我现在的问题是如何让 WinForms 和 Web 应用程序将正确的上下文注入到服务中?

我尝试为我的服务创建一个构造函数,如下所示:

    private IHubContext<ProcessHub> Clients {get;set;}

    public ProcessService(IHubContext<ProcessHub> clients)
    {
        Clients = clients;
    }
Run Code Online (Sandbox Code Playgroud)

但我没有使用 core,所以我无法弄清楚如何从我的控制器创建该服务的实例(我通常会在 .net core 中使用 DI 并注册我的服务)我尝试了这个,但它显然是错误的......

    public ProcessController(IHubContext<ProcessHub> clients)
    {
        _processService = new ProcessService(clients);
    }
Run Code Online (Sandbox Code Playgroud)

这告诉我控制器需要一个无参数构造函数。如果我创建其中之一,我想我将无法按预期使用该服务。我没有尝试将 win 表单连接到该服务,因为我认为我会遇到类似的问题。

任何人都可以帮助我a)我是不是完全找错了树...b)我如何创建我的服务实例并让它了解我的中心上下文。

非常感谢!

小智 6

让我向您展示我的解决方案,它正在与我一起工作,我正在使用 asp.NET MVC .net4.6 和 winforms .net4.8

  1. 通知中心:
    [HubName("notifyHub")]
    public class NotifyHub : Hub
    {
        public void Send(string name, string message)
        {
            Clients.All.broadcastMessage(name, message);
        }

        public Task JoinGroup(string groupName)
        {
            return Groups.Add(Context.ConnectionId, groupName);

        }

        public Task LeaveGroup(string groupName)
        {
            return Groups.Remove(Context.ConnectionId, groupName);
        }
    }
Run Code Online (Sandbox Code Playgroud)
  1. MVC-Controller-Action 向客户端发送消息:
public ActionResult CreateCustomer(Customer customer)
{
    if (ModelState.IsValid)
    {
        db.Customers.Add(customer);
        db.SaveChanges();
        var notificationHub = Microsoft.AspNet.SignalR.GlobalHost.ConnectionManager.GetHubContext<NotifyHub>();
        notificationHub.Clients.Group(YourCustomGroupOfClients.ToString()).UpdateCustomer(customer);
        return RedirectToAction("Index");
    }

    return View(customer);
}
Run Code Online (Sandbox Code Playgroud)
  1. 客户端(winforms):
//  Create this hub globally just one time
public static HubConnection hubConnection = new HubConnection(baseUrl);
Run Code Online (Sandbox Code Playgroud)
readonly IHubProxy stockTickerHubProxy = Globals.hubConnection.CreateHubProxy("notifyHub");
Run Code Online (Sandbox Code Playgroud)
stockTickerHubProxy.On<Customer>("UpdateCustomer", async customer =>
{
    try
    {
        var oldCust = await db.Customers.FirstOrDefaultAsync(a => a.id == customer.id);
        if (oldCust == null)
        {
            db.Customer.Add(customer);
        }
        else
        {
            oldCust.Cust_Name = customer.Cust_Name;
            oldCust.Phone1 = customer.Phone1;
        }
        await db.SaveChangesAsync();
        if (InvokeRequired) Invoke(new MethodInvoker(delegate
        {
            Refresh_DG_Customers();
        }));
    }
    catch (Exception)
    {
    }
});
Run Code Online (Sandbox Code Playgroud)