【问题标题】:Use SignalR to notify from wcf to JS使用 SignalR 从 wcf 通知 JS
【发布时间】:2013-07-08 07:21:45
【问题描述】:

我想使用SignalR 来识别WCF service 上的Jquery 客户端,即使没有请求也可以向他发送消息。 (即在客户端向服务发送第一个请求后,服务可以知道他并向他发送消息)。

我不知道这是否是最好的方法,但这是我能找到的。 (除了仅在 VS 2012 中支持的 WebSocket)。

我在Service的Global文件中添加了如下函数:

protected void Application_Start(object sender, EventArgs e)
{
   RouteTable.Routes.MapHubs();
}

我创建了 Chat.cs:

public class Chat : Hub
{
    public void Send(string message)
    {
        // Call the addMessage method on all clients
        Clients.All.addMessage(message);
    }
}

JS 项目中我添加了SignalRJS 文件:

<script src="../JavaScript/jquery.signalR-1.1.2.min.js" type="text/javascript"></script>
<script src="/signalr/hubs" type="text/javascript"></script>

使用它的函数:

function Chat() {

    $(function () {
        // Proxy created on the fly          
        var chat = $.connection.chat;

        // Declare a function on the chat hub so the server can invoke it          
        chat.client.addMessage = function (message) {
            alert(message);
        };

        // Start the connection
        $.connection.hub.start().done(function () {
            // Call the chat method on the server
            chat.server.send('aa');
        });
    });

}

如果这个问题很愚蠢,这对我来说很抱歉,但是 JS 的 SignalR 应该如何知道服务,我应该在哪里定义他? (这需要跨域)

(变量$.connection.chat未定义)

我确定我错过了一些事情,尤其是他如何通过 SignalR 链接服务和 JS

【问题讨论】:

  • 您能否详细解释一下 WCF 如何融入图片?您在这里展示的只是基本的 SignalR 客户端/服务器通信。另外,请务必查看示例:github.com/SignalR/Samples

标签: javascript jquery html wcf signalr


【解决方案1】:

我缺少的是 SignalR 与跨域的使用。

在全局文件上我更改了代码:

protected void Application_Start(object sender, EventArgs e)
{
  RouteTable.Routes.MapHubs(new HubConfiguration() { EnableCrossDomain = true });
}

在这里需要注意的是,由于我使用跨域,我在 Application_BeginRequest 函数中有代码,当完成 SignalR 请求时应该取消它,否则 它不起作用。所以我就这样取消了:

 protected void Application_BeginRequest(object sender, EventArgs e)
        {
            //Here is testing whether this request SignalR, if not I do the following code
            if (HttpContext.Current.Request.Path.IndexOf("signalr") == -1)
            {
                HttpContext.Current.Response.Cache.SetCacheability(HttpCacheability.NoCache);

                HttpContext.Current.Response.Cache.SetNoStore();

                HttpContext.Current.Response.AddHeader("Access-Control-Allow-Origin", "*");

                if (HttpContext.Current.Request.HttpMethod == "OPTIONS")
                {

                    HttpContext.Current.Response.AddHeader("Access-Control-Allow-Methods", "GET, POST");

                    HttpContext.Current.Response.AddHeader("Access-Control-Allow-Headers", "Content-Type, Authorization, Accept, x-requested-with");

                    HttpContext.Current.Response.AddHeader("Access-Control-Max-Age", "1728000");

                    HttpContext.Current.Response.End();

                }
            }
        }

在客户端:

我添加了SignalRJquery的脚本,我删除了这个脚本:

&lt;script src="/signalr/hubs" type="text/javascript"&gt;&lt;/script&gt;

因为有跨域调用,所以不需要。

连接在以下函数中:

var connection;
var contosoChatHubProxy;

function RegisterToServiceMessege() {
    connection = $.hubConnection();
    connection.url = 'http://localhost:xxx/signalr';
    contosoChatHubProxy = connection.createHubProxy('ChatHub');
    //This part happens when function broadcastMessage is activated(from the server)
    contosoChatHubProxy.on('broadcastMessage', function (userName, message) {
        alert('You have a messege:\n' + userName + ' ' + message);
    });
    connection.start()
    .done(function () {
        console.log('Now connected, connection ID=' + connection.id);
    })
    .fail(function () { console.log('Could not connect'); });
}

服务器上的 Chat.cs:

 [HubName("ChatHub")]
    public class Chat : Hub
    {
        [HubMethodName("Send")]
        public void Send(string name, string message)
        {
            // Call the broadcastMessage method to update clients.
            Clients.All.broadcastMessage(name, message);
        }
    }

一位客户对函数Send的调用如下:

function SendMessege() {
    contosoChatHubProxy.invoke('Send', 'aaa', 'bbb').done(function () {
        console.log('Invocation of NewContosoChatMessage succeeded');
    }).fail(function (error) {
        console.log('Invocation of NewContosoChatMessage failed. Error: ' + error);
    });

}

所有客户端都会收到发送的消息。

(您可以通过同时运行多个浏览器来检查。)

【讨论】:

    【解决方案2】:

    从 SignalR 2.0 版开始,您无法再使用以下代码启用 Cors:

    protected void Application_Start(object sender, EventArgs e) { RouteTable.Routes.MapHubs(new HubConfiguration() { EnableCrossDomain = true }); }

    相反,您必须在 Startup 类初始化方法中添加这两行:

    public void Configuration(IAppBuilder app)
    {
        app.UseCors(CorsOptions.AllowAll);
        app.MapSignalR();           
    }
    

    而且,对于每个人来说可能并不明显,如果您不想使用其自托管库托管 SignalR,请记住将您的项目更改为 WebApplication。就我而言,我试图将 Signalr 附加到 WCFProject。而且运行时甚至不会去Startup的这个Configuration方法,从而导致不断的错误,禁止访问信号器资源

    【讨论】:

      猜你喜欢
      • 2018-09-07
      • 2012-07-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多