signalr信号器入门


备注

本节概述了信号器是什么,以及开发人员可能想要使用它的原因。

它还应该提到信号器中的任何大型主题,并链接到相关主题。由于signalr的文档是新的,您可能需要创建这些相关主题的初始版本。

版本

发布日期
2.2.1 2016年7月13日
2.2.0 情节中字
2.1.2 2014年9月9日
2.1.1 2014年7月22日
2.1.0 2014年5月21日
2.0.3 2014年3月25日
2.0.2 2014年1月22日
2.0.1 2013年10月22日
2.0.0 2013年8月29日
1.2.2 2014年8月18日
1.2.1 2014年2月10日
1.2.0 2013年12月11日
1.1.4 2013年10月22日
1.1.3 2013年7月31日
1.1.2 2013年5月24日
1.1.1 2013年5月16日
1.1.0 2013年5月11日

起床和跑步

IIS / .NET版本要求请参见此处

SignalR 2+

  1. 安装NuGet包Microsoft.AspNet.SignalR (这是整个SignalR解决方案),它会要求您为其他包安装任何依赖项。接受条款并安装它们。

  2. 现在我们已经有了生成自己的SignalR Hub所需的.dlls 和客户端脚本,让我们创建一个。单击您的Web项目,添加名为HubsSignalR 的文件夹,并在其中添加一个NameOfYourChoosing Hub 类。我将我的名字命名为MessagingHub.cs

  3. 我们需要从我们通过NuGet下载的SignalR dll中的基类Hub 派生。代码看起来像:

    [HubName("messagingHub")]
    public class MessagingHub : Hub
    {
        //empty hub class
    }
     

    在我们的Startup.cs类中,我们可以让IAppBuilder 知道我们将使用SignalR。

    public partial class Startup
    {
        public void Configuration(IAppBuilder app)
        {
            app.MapSignalR();
            ConfigureAuth(app);
        }
    }
     
  4. 为了在客户端上引用我们的集线器代码,我们需要导入/引用2个脚本(除了显而易见的jQuery参考)。主要的jQuery.signalR-version.js 文件和hubs.js 专门为我们的集线器生成的生成的hubs.js 文件。这些资源可能如下所示:

    // script tag src="/YourAppPath/scripts/jquery-1.6.4.js"
    // script tag src="/YourAppPath/scripts/jquery.signalR-2.2.0.js"
    // script tag src="/YourAppPath/signalr/hubs"
     
  5. 由于SignalR的JavaScript构建在jQuery之上(需要> = v1.6.4),因此连接和断开连接到集线器的代码应该看起来相当简单。在这里它的所有'荣耀(包裹在IIFE中):

    $(function() {
        //notice the camel casing of our hub name corresponding to the [HubName()] attribute on the server
        var connection = $.connection.messagingHub;
    
        $.connection.hub.start().done(function () {
            alert("Connection Successful!");
        }).fail(function (reason) {
            console.log("SignalR connection failed: " + reason);
        });
    });
     
  6. 截至目前,我们应该能够运行应用程序并建立与SignalR集线器的连接。

将SignalR与Web API和JavaScript Web App一起使用,并支持CORS。

目标:使用SignalR在Web API和基于TypeScript / JavaScript的Web App之间进行通知,其中Web API和Web App托管在不同的域中。

在Web API上启用SignalR和CORS:创建标准Web API项目,并安装以下NuGet包:

  • Microsoft.Owin.Cors
  • Microsoft.AspNet.WebApi.Cors
  • Microsoft.AspNet.WebApi.Owin
  • Microsoft.AspNet.SignalR.Core

之后,您可以摆脱Global.asax 并添加一个OWIN Startup类。

using System.Web.Http;
using System.Web.Http.Cors;
using Microsoft.Owin;
using Owin;

[assembly: OwinStartup(typeof(WebAPI.Startup), "Configuration")]
namespace WebAPI
{
    public class Startup
    {
        public void Configuration(IAppBuilder app)
        {
        
            var httpConfig = new HttpConfiguration();
            
            //change this configuration as you want.
            var cors = new EnableCorsAttribute("http://localhost:9000", "*", "*"); 
            httpConfig.EnableCors(cors);

            SignalRConfig.Register(app, cors);

            WebApiConfig.Register(httpConfig);

            app.UseWebApi(httpConfig);
        }
    }
}
 

创建SignalRConfig 类,如下所示:

using System.Linq;
using System.Threading.Tasks;
using System.Web.Cors;
using System.Web.Http.Cors;
using Microsoft.Owin.Cors;
using Owin;

namespace WebAPI
{
    public static class SignalRConfig
    {
        public static void Register(IAppBuilder app, EnableCorsAttribute cors)
        {

            app.Map("/signalr", map =>
            {
                var corsOption = new CorsOptions
                {
                    PolicyProvider = new CorsPolicyProvider
                    {
                        PolicyResolver = context =>
                        {
                            var policy = new CorsPolicy { AllowAnyHeader = true, AllowAnyMethod = true, SupportsCredentials = true };

                            // Only allow CORS requests from the trusted domains.
                            cors.Origins.ToList().ForEach(o => policy.Origins.Add(o));

                            return Task.FromResult(policy);
                        }
                    }
                };
                map.UseCors(corsOption).RunSignalR();
            });
        }
    }
}
 

到目前为止,我们刚刚在服务器端启用了带有CORS的SignalR。现在让我们看看如何从服务器端发布事件。为此我们需要一个Hub

public class NotificationHub:Hub
{
    //this can be in Web API or in any other class library that is referred from Web API.
}
 

现在终于实际广播变化的一些代码:

public class SuperHeroController : ApiController
{
    [HttpGet]
    public string RevealAlterEgo(string id)
    {
        var alterEgo = $"The alter ego of {id} is not known.";
        var superHero = _superHeroes.SingleOrDefault(sh => sh.Name.Equals(id));
        if (superHero != null)
        {
            alterEgo = superHero.AlterEgo;
            
            /*This is how you broadcast the change. 
             *For simplicity, in this example, the broadcast is done from a Controller, 
             *but, this can be done from any other associated class library having access to NotificationHub.
             */
            var notificationHubContext = GlobalHost.ConnectionManager.GetHubContext<NotificationHub>();
            if (notificationHubContext != null)
            {
                var changeData = new { changeType = "Critical", whatHappened = $"Alter ego of {id} is revealed." };

                //somethingChanged is an arbitrary method name.
                //however, same method name is also needs to be used in client.
                notificationHubContext.Clients.All.somethingChanged(changeData);
            }
        }
        return alterEgo;
    }
}
 

因此,到目前为止,我们已经准备好了服务器端。对于客户端,我们需要jQuerysignalr 包。您可以使用jspm 安装它们。如果需要,安装两者的类型。

我们不会使用默认生成的JavaScript代理。我们宁愿创建一个非常简单的类来处理SignalR通信。

/**
 * This is created based on this gist: https://gist.github.com/donald-slagle/bf0673b3c188f3a2559c.
 * As we are crreating our own SignalR proxy, 
 * we don't need to get the auto generated proxy using `signalr/hubs` link.
 */
export class SignalRClient {

    public connection = undefined;
    private running: boolean = false;

    public getOrCreateHub(hubName: string) {
        hubName = hubName.toLowerCase();
        if (!this.connection) {
            this.connection = jQuery.hubConnection("https://localhost:44378");
        }

        if (!this.connection.proxies[hubName]) {
            this.connection.createHubProxy(hubName);
        }

        return this.connection.proxies[hubName];
    }

    public registerCallback(hubName: string, methodName: string, callback: (...msg: any[]) => void,
        startIfNotStarted: boolean = true) {

        var hubProxy = this.getOrCreateHub(hubName);
        hubProxy.on(methodName, callback);

        //Note: Unlike C# clients, for JavaScript clients, 
        //      at least one callback needs to be registered, 
        //      prior to start the connection.
        if (!this.running && startIfNotStarted)
            this.start();
    }

    start() {
        const self = this;
        if (!self.running) {
            self.connection.start()
                .done(function () {
                    console.log('Now connected, connection Id=' + self.connection.id);
                    self.running = true;
                })
                .fail(function () {
                    console.log('Could not connect');
                });
        }
    }
}
 

最后使用此类来收听更改广播,如下所示:

/**
 * Though the example contains Aurelia codes, 
 * the main part of SignalR communication is without any Aurelia dependency.
 */
import {autoinject, bindable} from "aurelia-framework";
import {SignalRClient} from "./SignalRClient";

@autoinject
export class SomeClass{
    
    //Instantiate SignalRClient.
    constructor(private signalRClient: SignalRClient) {
    }

    attached() {
        //To register callback you can use lambda expression...
        this.signalRClient.registerCallback("notificationHub", "somethingChanged", (data) => {
            console.log("Notified in VM via signalr.", data);
        });
        
        //... or function name.
        this.signalRClient.registerCallback("notificationHub", "somethingChanged", this.somethingChanged);
    }

    somethingChanged(data) {
        console.log("Notified in VM, somethingChanged, via signalr.", data);
    }
}