Asp.net mvc 未调用信号器客户端函数 概述

Asp.net mvc 未调用信号器客户端函数 概述,asp.net-mvc,signalr,Asp.net Mvc,Signalr,让我的信号服务器/集线器在我的信号客户端上调用javascript函数时遇到了实际问题 我试过的 我已经阅读了更多的教程,并查看了如此多的例子(包括官方文档),说明这应该如何工作,这几乎是荒谬的 除了核心功能外,我已经尝试过对所有功能进行注释 我必须确保服务器和客户端功能不相同,并且拼写正确 我也打开了日志,但Firebug控制台中没有出现错误 环境 所讨论的信号器代码已在ASP.net MVC4项目中使用VB.net和MySQL以及Entity framework v5实现。我正在Visu

让我的信号服务器/集线器在我的信号客户端上调用javascript函数时遇到了实际问题

我试过的
  • 我已经阅读了更多的教程,并查看了如此多的例子(包括官方文档),说明这应该如何工作,这几乎是荒谬的
  • 除了核心功能外,我已经尝试过对所有功能进行注释
  • 我必须确保服务器和客户端功能不相同,并且拼写正确
  • 我也打开了日志,但Firebug控制台中没有出现错误
环境 所讨论的信号器代码已在ASP.net MVC4项目中使用VB.net和MySQL以及Entity framework v5实现。我正在Visual Studio 2012的本地开发机器上使用IISExpress调试该系统

代码片段 global.asax.vb:

Sub Application_Start()

    MiniProfilerEF.Initialize()

    AreaRegistration.RegisterAllAreas()

    ' Register the default hubs route: ~/signalr
    RouteTable.Routes.MapHubs()

    WebApiConfig.Register(GlobalConfiguration.Configuration)
    FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters)
    RouteConfig.RegisterRoutes(RouteTable.Routes)
    BundleConfig.RegisterBundles(BundleTable.Bundles)
    AuthConfig.RegisterAuth()

    ' Register custom view
    ViewEngines.Engines.Add(New CustomViewEngine())

End Sub
$(function () {

    // Proxy created on the fly
    var notification = $.connection.notificationHub;
    //$.connection.notificationHub.logging = true;

    // Declare functions that can be run on the client by the server
    notification.client.sendNotification = onAddNotification;

    // Testing code only
    $("#testButton").click(function () {
        // Run test function on server
        notification.server.runTest();
    });

    // Map the onConnect and onDisconnect functions
    notification.client.connected = function () { };
    notification.client.disconnected = function () { };

    //$.connection.hub.start();
    $.connection.hub.start(function () {
        alert("Notification system connected");
    });
});

// Process a newly received notification from the server
function onAddNotification(message) {

    // Convert the passed json message back into an object
    var obj = JSON.parse(message);

    var parsedDate = new Date(parseInt(obj.Timestamp.substr(6)));

    // Update the notification list
    $('#notifications').prepend('<li>' + obj.Message + ' at ' + dateFormat(parsedDate, "default") + '</li>');

    // Update the new notification count
    var count = document.getElementById("notification_count")
    if (count.textContent) {
        //W3C DOM
        count.textContent = obj.Count;
    } else if (anchor.innerText) {
        //Microsoft DOM
        count.innerText = obj.Count;
    }
    //document.getElementById("notification_count").innerHTML = obj.Count + '<i class="splashy-comment"></i>';

    // Show a brief notification message
    $.sticky(obj.Message, { autoclose: 2000, position: "top-right", type: "st-info" });

};
Public Class NotificationHub
Inherits Hub

ReadOnly Group As String = "Notification"

Public Function RunTest()
    Dim testMessage As New SignalR_Notification_Message

    testMessage.Count = 3
    testMessage.Message = "Some test message"
    testMessage.Timestamp = Now

    Call Notify(testMessage, "joebloggs")
End Function

Public Overrides Function OnConnected() As Task

    Dim db As New MyEntities
    Dim userName As String = Context.User.Identity.Name
    Dim connectionID = Context.ConnectionId

    Dim conn As SignalR_Connection

    ' Attempt to find a retrieve a connection entry with the same Connection ID
    conn = db.SignalR_Connection.Where(Function(s) s.Connection_ID = connectionID).FirstOrDefault

    ' If the connection does not already exist, add it
    If IsNothing(conn) Then
        conn = New SignalR_Connection

        ' Create the new connection entry
        conn.Connection_ID = connectionID
        conn.Username = userName
        conn.Group = Group

        ' Attempt to save the new connection entry
        Try
            db.SignalR_Connection.Add(conn)
            db.SaveChanges()
        Catch ex As Exception
            Dim a As String = ""
            a = ""
        End Try
    End If

    Return MyBase.OnConnected()
End Function

Public Overrides Function OnDisconnected() As Task

    Dim db As New MyEntities
    Dim userName As String = Context.User.Identity.Name
    Dim connectionId As String = Context.ConnectionId

    Dim conn As SignalR_Connection

    ' Attempt to find a retrieve the connection entry
    conn = db.SignalR_Connection.Where(Function(s) s.Connection_ID = connectionId And s.Username = userName).FirstOrDefault

    ' Attempt to remove the connection entry
    Try
        db.SignalR_Connection.Remove(conn)
        db.SaveChanges()
    Catch ex As Exception
        Dim a As String = ""
        a = ""
    End Try

    Return MyBase.OnDisconnected()
End Function

''' <summary>
''' Send the notification to the client
''' </summary>
Public Sub Notify(Message As SignalR_Notification_Message, Username As String)

    Dim ConnectionIDs As List(Of String)
    Dim Serializer As New JavaScriptSerializer()
    Dim json As String

    ' Attempt to convert the object into json before sending
    Try
        json = Serializer.Serialize(Message)
    Catch ex As Exception
        Exit Sub
    End Try

    ' Get the connection id's this message must go to
    ConnectionIDs = GetUsersConnectionID(Username)

    If Not IsNothing(ConnectionIDs) Then
        ' Send the message to all connection ID's
        For Each ConnectionID In ConnectionIDs
            Clients.Client(ConnectionID).sendNotification(json)
        Next
    End If

End Sub

''' <summary>
''' Retrieve a list of connection ID's for the current user
''' </summary>
Public Function GetUsersConnectionID(Username As String) As List(Of String)

    Dim db As New MyEntities

    ' Attempt to find a retrieve the connection entries
    Return db.SignalR_Connection.AsNoTracking.Where(Function(s) s.Username = Username).Select(Function(s) s.Connection_ID).ToList

End Function

End Class
@ModelType Geo_sight.NotificationWindowModel

<div class="modal hide fade" id="myNotifications">
<div class="modal-header">
    <button class="close" data-dismiss="modal">×</button>
    <h3>Notifications</h3>
</div>
<div class="modal-body">
    <ul class="unstyled" id="notifications">
        @For Each Notification In Model.Notifications
            @<li>@Html.Raw(Notification.Text)</li>
        Next
    </ul>
</div>
<div class="modal-footer">
    <a href="javascript:void(0)" class="btn" id="testButton">Send test</a>
</div>
信号器初始化javascript:

Sub Application_Start()

    MiniProfilerEF.Initialize()

    AreaRegistration.RegisterAllAreas()

    ' Register the default hubs route: ~/signalr
    RouteTable.Routes.MapHubs()

    WebApiConfig.Register(GlobalConfiguration.Configuration)
    FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters)
    RouteConfig.RegisterRoutes(RouteTable.Routes)
    BundleConfig.RegisterBundles(BundleTable.Bundles)
    AuthConfig.RegisterAuth()

    ' Register custom view
    ViewEngines.Engines.Add(New CustomViewEngine())

End Sub
$(function () {

    // Proxy created on the fly
    var notification = $.connection.notificationHub;
    //$.connection.notificationHub.logging = true;

    // Declare functions that can be run on the client by the server
    notification.client.sendNotification = onAddNotification;

    // Testing code only
    $("#testButton").click(function () {
        // Run test function on server
        notification.server.runTest();
    });

    // Map the onConnect and onDisconnect functions
    notification.client.connected = function () { };
    notification.client.disconnected = function () { };

    //$.connection.hub.start();
    $.connection.hub.start(function () {
        alert("Notification system connected");
    });
});

// Process a newly received notification from the server
function onAddNotification(message) {

    // Convert the passed json message back into an object
    var obj = JSON.parse(message);

    var parsedDate = new Date(parseInt(obj.Timestamp.substr(6)));

    // Update the notification list
    $('#notifications').prepend('<li>' + obj.Message + ' at ' + dateFormat(parsedDate, "default") + '</li>');

    // Update the new notification count
    var count = document.getElementById("notification_count")
    if (count.textContent) {
        //W3C DOM
        count.textContent = obj.Count;
    } else if (anchor.innerText) {
        //Microsoft DOM
        count.innerText = obj.Count;
    }
    //document.getElementById("notification_count").innerHTML = obj.Count + '<i class="splashy-comment"></i>';

    // Show a brief notification message
    $.sticky(obj.Message, { autoclose: 2000, position: "top-right", type: "st-info" });

};
Public Class NotificationHub
Inherits Hub

ReadOnly Group As String = "Notification"

Public Function RunTest()
    Dim testMessage As New SignalR_Notification_Message

    testMessage.Count = 3
    testMessage.Message = "Some test message"
    testMessage.Timestamp = Now

    Call Notify(testMessage, "joebloggs")
End Function

Public Overrides Function OnConnected() As Task

    Dim db As New MyEntities
    Dim userName As String = Context.User.Identity.Name
    Dim connectionID = Context.ConnectionId

    Dim conn As SignalR_Connection

    ' Attempt to find a retrieve a connection entry with the same Connection ID
    conn = db.SignalR_Connection.Where(Function(s) s.Connection_ID = connectionID).FirstOrDefault

    ' If the connection does not already exist, add it
    If IsNothing(conn) Then
        conn = New SignalR_Connection

        ' Create the new connection entry
        conn.Connection_ID = connectionID
        conn.Username = userName
        conn.Group = Group

        ' Attempt to save the new connection entry
        Try
            db.SignalR_Connection.Add(conn)
            db.SaveChanges()
        Catch ex As Exception
            Dim a As String = ""
            a = ""
        End Try
    End If

    Return MyBase.OnConnected()
End Function

Public Overrides Function OnDisconnected() As Task

    Dim db As New MyEntities
    Dim userName As String = Context.User.Identity.Name
    Dim connectionId As String = Context.ConnectionId

    Dim conn As SignalR_Connection

    ' Attempt to find a retrieve the connection entry
    conn = db.SignalR_Connection.Where(Function(s) s.Connection_ID = connectionId And s.Username = userName).FirstOrDefault

    ' Attempt to remove the connection entry
    Try
        db.SignalR_Connection.Remove(conn)
        db.SaveChanges()
    Catch ex As Exception
        Dim a As String = ""
        a = ""
    End Try

    Return MyBase.OnDisconnected()
End Function

''' <summary>
''' Send the notification to the client
''' </summary>
Public Sub Notify(Message As SignalR_Notification_Message, Username As String)

    Dim ConnectionIDs As List(Of String)
    Dim Serializer As New JavaScriptSerializer()
    Dim json As String

    ' Attempt to convert the object into json before sending
    Try
        json = Serializer.Serialize(Message)
    Catch ex As Exception
        Exit Sub
    End Try

    ' Get the connection id's this message must go to
    ConnectionIDs = GetUsersConnectionID(Username)

    If Not IsNothing(ConnectionIDs) Then
        ' Send the message to all connection ID's
        For Each ConnectionID In ConnectionIDs
            Clients.Client(ConnectionID).sendNotification(json)
        Next
    End If

End Sub

''' <summary>
''' Retrieve a list of connection ID's for the current user
''' </summary>
Public Function GetUsersConnectionID(Username As String) As List(Of String)

    Dim db As New MyEntities

    ' Attempt to find a retrieve the connection entries
    Return db.SignalR_Connection.AsNoTracking.Where(Function(s) s.Username = Username).Select(Function(s) s.Connection_ID).ToList

End Function

End Class
@ModelType Geo_sight.NotificationWindowModel

<div class="modal hide fade" id="myNotifications">
<div class="modal-header">
    <button class="close" data-dismiss="modal">×</button>
    <h3>Notifications</h3>
</div>
<div class="modal-body">
    <ul class="unstyled" id="notifications">
        @For Each Notification In Model.Notifications
            @<li>@Html.Raw(Notification.Text)</li>
        Next
    </ul>
</div>
<div class="modal-footer">
    <a href="javascript:void(0)" class="btn" id="testButton">Send test</a>
</div>

更新2013-04-04 通过更多的调试,我可以让客户端运行,但完全是随机的,非常偶然的,只需在前一个signarsend调用完成几秒钟后反复按下test按钮即可

下面是Firebug控制台中的一个示例。。。


更新日期2013-04-05 随着越来越多的测试和调试,我在客户端函数调用和不调用时遇到了一个特点

正如我在上一次更新中所看到的,SignalR选择使用长轮询,超时时间约为35秒

对客户机函数进行了多次重复调用后,似乎只有在长轮询生命周期的大约前10秒内进行的调用才能到达客户机并成功运行该函数。在此期间之后发送的电话似乎无法接通

我猜这意味着我的代码是健全的,但为什么会发生这种情况

信号员常见问题解答问题…

我在这里也发现了与我的问题类似的东西:


我使用的是Windows 7 Professional,但我没有使用IIS(我使用的是IIS Express),所以这可能是同一个问题吗?

嗨,John。您的信号器实现似乎正常。我已经用一个简单的web应用程序测试了你的代码,对我来说效果很好。你可以在下载。您是否检查了连接ID是否匹配并且没有被截断?感谢您花时间研究此问题,非常感谢!我已经检查了连接ID,它们肯定是相同的,所以没有问题。奇怪的是,你做的项目运行得很好,发送给客户的所有消息都通过了,所以某个地方出了问题。