简单的天气通知使用 SignalR






4.42/5 (7投票s)
使用 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);
}
}
}
我们在这里做什么 -
- ChatHub 类继承自 Hub 类,这意味着我们将 ChatHub 类用作通信的中心。
- 我们定义了一个 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 时,没有温度显示,这不好——我的意思是应该有一些初始温度。
所以,我们需要做什么 -
- 我们需要将温度保存在一个静态变量中,这样它对于 ChatHub 的所有对象都是相同的。
- 当 RecieveWeatherNotification.html 连接到 SignalR 服务器时,它会调用 SignalR 服务器来获取当前温度。
- 我们必须在 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 服务器上的方法,服务器也可以调用客户端上的方法。