1

我在发布这个问题时犹豫不决,因为网上有很多相同的答案但是我的运气不好,没有什么能帮助我。对于我的 Web 应用程序,我需要通知部分,为此我认为使用 SignalR 2。

但它不起作用。以下是完整的代码部分:

==>Hub Class

[HubName("MyHub")]
public class MyHub : Hub
{
    public static void Show()
    {
        IHubContext context = GlobalHost.ConnectionManager.GetHubContext<MyHub>();
        context.Clients.All.displayStatus();
    }
}

==>全局文件

public class MvcApplication : System.Web.HttpApplication
{
    protected void Application_Start()
    {
        SqlDependency.Start(ConfigurationManager.ConnectionStrings["DefaultConnection"].ConnectionString);
        AreaRegistration.RegisterAllAreas();
        FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
        RouteConfig.RegisterRoutes(RouteTable.Routes);
        BundleConfig.RegisterBundles(BundleTable.Bundles);
    }

    protected void Application_End()
    {
        SqlDependency.Stop(ConfigurationManager.ConnectionStrings["DefaultConnection"].ConnectionString);
    }
}

==>存储库

public class DAL
{
    public List<DTO.Employee> GetEmployee()
    {
        List<DTO.Employee> l = new List<DTO.Employee>();
        try
        {
            using (var con = new SqlConnection(ConfigurationManager.ConnectionStrings["DefaultConnection"].ConnectionString))
            {
                con.Open();
                using (var cmd = new SqlCommand("select * from employee", con))
                {
                    cmd.Notification = null;
                    SqlDependency dep = new SqlDependency(cmd);
                    dep.OnChange += new OnChangeEventHandler(Dep_OnChange);

                    using (var drd = cmd.ExecuteReader())
                    {
                        while (drd.Read())
                        {
                            l.Add(new DTO.Employee()
                            {
                                Id = Convert.ToInt64(drd["id"]),
                                Name = Convert.ToString(drd["name"])
                            });
                        }
                    }
                }
            }
        }
        catch { }
        return l;
    }

    private void Dep_OnChange(object sender, SqlNotificationEventArgs e)
    {
        if (e.Type == SqlNotificationType.Change)
        {
            MyHub.Show();
        }
    }
}

==> Owin 创业班

[assembly: OwinStartupAttribute(typeof(SignalR2_App1.Startup))]

namespace SignalR2_App1 { public partial class Startup { public void Configuration(IAppBuilder app) { app.MapSignalR(); } } }

==> 查看

<script src="~/Scripts/jquery-1.10.2.min.js"></script>    
<script src="~/Scripts/jquery.signalR-2.2.0.min.js"></script>
<script src="~/signalr/hubs"></script>
<script type="text/javascript">
    $(function () {
        var job = $.connection.MyHub;
        job.client.displayStatus = function () {
            getData();
        }
        $.connection.hub.start();
        getData();
    })
    function getData() {
        $.ajax({
            url: "/data/getdata",
            contentType: "application/json charset=utf-8",
            dataType: "json",
            type: "Post",
            success: function (result) {
                $.each(result, function (e, obj) {
                    $("#tbldata_tbody").append("<tr><td>" + obj.Id + "</td><td>" + obj.Name + "</td></tr>")
                })
            },
            error: function () {
                alert("Error");
            }
        })
    }
</script>
<body>
<table id="tbldata">
    <thead>
        <tr>
            <td>Id</td>
            <td>Name</td>
        </tr>
    </thead>
    <tbody id="tbldata_tbody"></tbody>
</table>

==>行动

[HttpPost]
    public JsonResult GetData()
    {
        DAL.DAL O = new DAL.DAL();
        return Json(O.GetEmployee());
    }

您可以从以下链接下载整个代码:
代码链接

4

1 回答 1

1

根据您的代码,我认为您不了解信号器的所有细节。这里有一些提示:

1. 在您的集线器内,您不需要 GlobalHost.ConnectionsManager

在集线器内,您已经拥有一个 Clients 属性

2. 不要自己创建集线器的实例!

在你的 DAL 里面你不应该打电话

  MyHub.Show();

而是抓住 HubContext:

GlobalHost.ConnectionManager.GetHubContext<MyHub>().Clients.All.displayStatus();

更好的方法 - 使用强类型集线器:

根据您的代码,我认为您不了解信号器的所有细节。我建议您阅读https://docs.microsoft.com/en-us/aspnet/signalr/overview/guide-to-the-api/hubs-api-guide-server

例如,在集线器上,您应该只定义客户端可以在服务器上调用的方法。为了正确定义服务器可以在客户端上调用的方法,您可以使用“Strongly-Types-Hubs”。请参阅: https ://docs.microsoft.com/en-us/aspnet/signalr/overview/guide-to-the-api/hubs-api-guide-server#stronglytypedhubs

关于 Hub 对象生命周期的背景信息:

https://docs.microsoft.com/en-us/aspnet/signalr/overview/guide-to-the-api/hubs-api-guide-server

您无需实例化 Hub 类或从服务器上您自己的代码调用其方法;SignalR Hubs 管道为您完成的所有工作。SignalR 每次需要处理 Hub 操作(例如客户端连接、断开连接或对服务器进行方法调用时)都会创建 Hub 类的新实例。

因为 Hub 类的实例是瞬态的,所以您不能使用它们来维护从一个方法调用到下一个方法调用的状态。每次服务器接收到来自客户端的方法调用时,Hub 类的新实例都会处理该消息。要通过多个连接和方法调用来维护状态,请使用其他方法,例如数据库,或 Hub 类上的静态变量,或不是从 Hub 派生的不同类。如果你在内存中持久化数据,使用 Hub 类上的静态变量等方法,当应用域回收时,数据会丢失。

如果您想通过在 Hub 类外部运行的您自己的代码向客户端发送消息,则无法通过实例化 Hub 类实例来实现,但您可以通过获取 Hub 类的 SignalR 上下文对象的引用来实现. 有关详细信息,请参阅本主题后面的如何从 Hub 类外部调用客户端方法和管理组。

于 2018-03-01T09:27:34.363 回答