65.9K
CodeProject 正在变化。 阅读更多。
Home

简单的天气通知使用 SignalR

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.42/5 (7投票s)

2016年8月6日

CPOL

6分钟阅读

viewsIcon

19589

downloadIcon

547

使用 SignalR 创建简单的天气应用程序,该应用程序将通知所有用户天气变化。

引言

SignalR 是一个面向 .NET 开发者的库,用于在 .NET 技术(ASP.NET 应用程序、C# 控制台应用程序、WPF 应用程序、Windows Phone 应用程序等)构建的应用程序中添加实时功能。它是开源的,您可以从 GitHub 下载。

SignalR 的 GitHub 地址是 -  https://github.com/signalr. 

在这里,我将创建一个简单的天气通知应用程序,该应用程序将即时(实时)通知所有已连接的用户天气变化。

背景

您应该具备以下基础知识:

  • C# 
  • Asp.net
  • JavaScript
  • Jquery
  • 套接字通信(非必需)

使用代码

创建新项目

创建一个名为 WeatherAppDemo 的新 Web 项目,使用 .NET Framework 版本 4.5。我使用 .NET 4.5 是因为这样可以使用最新的 SignalR 2.x 版本。

请不要更改名称,因为我将在整个文章中使用此命名空间。

我正在创建一个 Asp.net mvc 项目,但您也可以创建 WebForm 或任何 asp.net 技术项目。

添加 SignalR 库

1. 打开 NuGet 包管理器

 

2. 在 NuGet 搜索中搜索 SignalR,然后单击第一个搜索结果

 

这将安装创建 SignalR 应用程序所需的所有库。它将同时添加服务器库和 JavaScript 客户端库。

您会注意到 SignalR 搜索结果很多,那么问题来了——如果我点击其他的会怎样?实际上,它们是 SignalR 为不同目的提供的独立库,但我们需要完整的包,因为我们要创建 SignalR 服务器以及客户端。

3. 在项目中添加一个名为 SignalR 的新文件夹

我这样做是因为我想将与 SignalR 相关的代码保存在一个单独的文件夹中。

配置 SignalR

1. 创建 Hub 类

在 SignalR 文件夹中添加一个名为 ChatHub 的新类,并粘贴以下代码:

using Microsoft.AspNet.SignalR;
using Microsoft.AspNet.SignalR.Hubs;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;

namespace WeatherAppDemo.SignalR
{
    public class ChatHub:Hub
    {
        [HubMethodName("change_weather")]
        public void ChangeWeather(int temperature)
        {
             //Clients is ConnectionContext, it holds the information about all the connection.
            //Others in 'Clients.Others' is holding the list of all connected user except the 
            // caller user (the user which has called this method) 
            //NotifyUser is a function on the clientside, you will understand it later.

            Clients.Others.NotifyUser(temperature);

        }

    }
}

我们在这里做什么 -

  1. ChatHub 类继承自 Hub 类,这意味着我们将 ChatHub 类用作通信的中心。
  2. 我们定义了一个 ChangeWeather 函数,它接受一个 temperature 参数,并使用 temperature 参数调用客户端的 NotifyUser

2. 将 Hub 映射到 SignalR 管道

在 SignalR 文件夹中添加一个名为 StartUp 的新类,并将以下代码粘贴到 StartUp.cs 中:

using Microsoft.Owin;
using Owin;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
[assembly: OwinStartup(typeof(WeatherAppDemo.SignalR.StartUp))]

namespace WeatherAppDemo.SignalR
{
    public class StartUp
    {
        public void Configuration(IAppBuilder app)
        {
            app.MapSignalR();
        }
    }
}

我们在这里做什么 -

1. 我们调用 owinstartup 并传入参数 WeatherAppDemo.SignalR.StartUp,这将初始化我们的 StartUp 类。

2. 在 StartUp 类中,我们使用 app.MapSignalR() - 它会将 SignalR Hubs 映射到应用程序构建器管道。简单来说,它会将 Hubs 添加到 SignalR 管道中,这样您就可以通过 URL 访问它们。SignalR 的 URL 格式为 - <带端口的网站 URL>/signalr。

例如:codeproject.com/signalr

所以基本上我们做了两件事:首先启动 StartUp 类,然后将 Hubs 添加到 SignalR 管道。

现在,编译代码并将 "/signalr/hubs" 添加到 URL 末尾。您会看到一些 JavaScript 代码。如果您能看到 JavaScript 代码,则表示您已成功配置了 SignalR 服务器。

创建客户端

所以,我们需要创建两个客户端:

  • 第一个是改变天气的客户端
  • 第二个是接收通知的客户端

创建基本 JavaScript 客户端的步骤:

  • 创建一个 HTML 页面。
  • 将 jquery.js 库包含到 HTML 页面中。(您可以在脚本文件夹中找到 jQuery)
  • 将 signalr.js 库包含到 HTML 页面中。(您可以在脚本文件夹中找到 SignalR)
  • 添加一个脚本,其 src 为 "/signalr/hubs"。(这是 SignalR 服务器生成的 JavaScript 代理)。
  • 编写一些 JS 代码与 SignalR 服务器通信(我将在下一段中编写这段代码)。

创建 ChangeWeather 客户端

按照步骤创建基本 JavaScript 客户端,并在最后一步将以下代码粘贴到脚本标签中:

var SignalrConnection;

function Connect() {
    //This will hold the connection to the signalr hub
    SignalrConnection = $.connection.chatHub;

    //connecting the client to the signalr hub
    $.connection.hub.start().done(function () {
        alert("Connected to Signalr Server");
    })
    .fail(function () {
        alert("failed in connecting to the signalr server");
    })

}

function ChangeWeather() {
    //get the temperature from a textfield with id txtTemprature
    var Temperature = document.getElementById('txtTemperature').value;

    //calling the ChangeWeather function on the signalr server
    SignalrConnection.server.change_weather(Temperature)
}

在上面的代码中,我用注释描述了大部分部分。

现在,您可能对一些不是 jQuery 本身的 jQuery 代码感到好奇,例如 - "$.connection",那么我们是如何使用它的呢?实际上,我们通过 src="/signalr/hubs" 包含的脚本正在扩展 jQuery 并使其成为可能。

是时候设计我们的 HTML 页面了,只需复制以下代码:

<body onload="Connect();">
<div style="text-align:center;">
    <input type="text" id="txtTemperature" />
    <button id="btnChange" onclick="ChangeWeather();">Change Weather</button>
</div>
</body>

我假设您理解上面的 HTML 代码,所以我不做详细说明。

所以,我们终于创建了改变天气的客户端。

创建 RecieveWeatherNotification 客户端

按照步骤创建基本 JavaScript 客户端,并在最后一步将以下代码粘贴到脚本标签中:

var SignalrConnection
function Connect() {
    //This will hold the connection to the signalr hub
    SignalrConnection = $.connection.chatHub;

    //This will be called by signalr
    SignalrConnection.client.NotifyUser = function (temperature) {
        $('span').text(temperature);
    }

    //connecting the client to the signalr hub
    $.connection.hub.start().done(function () {
        alert("Connected to Signalr Server");
    })
    .fail(function () {
        alert("failed in connecting to the signalr server");
    })

}

请注意代码中的 "NotifyUser" - "SignalrConnection.client.NotifyUser" 是一个将由 SignalR 服务器调用的函数,所以尽量不要用错词。

HTML 页面设计非常简单,请查看以下代码:

<div style="text-align:center;">
    Temperature : <span></span> ℃
</div>

现在,我们已经拥有了所需的一切。是时候检查一下我们做了什么了。

执行以下步骤:

  • 编译代码。
  • 打开 ChangeWeather.html。
  • 在其他选项卡中打开 RecieveWeatherNotification(在多个选项卡或多个浏览器中打开)。
  • 在 ChangeWeather.html 中更改天气,并观察 RecieveWeatherNotification.html 中的温度。

请注意,当您第一次打开 RecieveWeatherNotification.html 时,没有温度显示,这不好——我的意思是应该有一些初始温度。

所以,我们需要做什么 -

  1. 我们需要将温度保存在一个静态变量中,这样它对于 ChatHub 的所有对象都是相同的。
  2. 当 RecieveWeatherNotification.html 连接到 SignalR 服务器时,它会调用 SignalR 服务器来获取当前温度。
  3. 我们必须在 ChatHub 中创建一个函数(HubMethod),RecieveWeatherNotification.html 将调用该函数来获取当前温度。该函数将调用客户端的 NotifyUser 来设置温度。

添加更多功能

更新 ChatHub

我上面已经描述了我将要做什么,所以只需复制以下代码并更新 ChatHub 类:

using Microsoft.AspNet.SignalR;
using Microsoft.AspNet.SignalR.Hubs;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;

namespace WeatherAppDemo.SignalR
{
    public class ChatHub:Hub
    {
        //keeping temperature variable static will make the value temperature to be stored in         
        //memory permanently and will be equal to all the object of chathub.
        static int Temperature;
        
        [HubMethodName("change_weather")]
        public void ChangeWeather(int temperature)
        {
            //change the temperature
            Temperature = temperature;

            //Clients is ConnectionContext, it holds the information about all the connection.
            //Others in 'Clients.Others' is holding the list of all connected user except the             
            //caller user (the user which has called this method) 
            //NotifyUser is a function on the clientside, you will understand it later.
            Clients.Others.NotifyUser(temperature);
            
        }

        [HubMethodName("get_weather")]
        public void GetWeather()
        {
            //pushing the data only to the user which has called this method.
            Clients.Caller.NotifyUser(Temperature);
        }

    }
}

这样,我们就更新了 ChatHub 类,现在让我们在客户端调用 GetWeather 方法。

更新 RecieveWeatherNotification.html

复制以下代码并替换之前的代码:

var SignalrConnection
function Connect() {
    //This will hold the connection to the signalr hub
    SignalrConnection = $.connection.chatHub;

    //This will be called by signalr
    SignalrConnection.client.NotifyUser = function (temperature) {
        $('span').text(temperature);
    }

    //connecting the client to the signalr hub
    $.connection.hub.start().done(function () {
        GetWeather();
        alert("Connected to Signalr Server");
    })
    .fail(function () {
        alert("failed in connecting to the signalr server");
    })

}

function GetWeather() {
    //calling the GetWeather function on the signalr server
    SignalrConnection.server.get_weather()
}

我们在这里做了什么 -

  • 我创建了一个 GetWeather 方法,它将调用 chathubmethod "get_weather"。
  • 当客户端连接到 SignalR 时,我调用 GetWeather。

所以,编译代码并检查所有内容。

这是一个非常简单的应用程序,但您也可以创建实时复杂应用程序,例如:

  • 聊天应用程序
  • 实时通知,如 Facebook
  • 在线游戏的每秒高频更新。
  • 等等。

关注点

您是否注意到我们既没有使用任何表单,也没有使用任何 ajax 请求,那么我们是如何获取数据的?实际上,我们正在与服务器建立一个套接字通道,这是一个双向通信,因此我们可以调用 SignalR 服务器上的方法,服务器也可以调用客户端上的方法。

© . All rights reserved.