我需要让我的 Azure MVC-5 Web 应用程序从我的 Azure 服务总线消息队列中读取,然后通过 SignalR 将数据发送到所有客户端网页,已解决。
在代码方面,它非常简单和优雅。这是我的解决方案:
首先,我的 Visual Studio 解决方案只有一个项目——主要的 Web 应用项目。在项目的根目录中,我有我的 SignalR 集线器类,名为 djwHub;
Imports Microsoft.AspNet.SignalR
Imports Microsoft.AspNet.SignalR.Hubs
Imports Microsoft.AspNet.SignalR.Messaging
Imports System.Threading.Tasks
Imports Microsoft.ServiceBus
Imports Microsoft.ServiceBus.Messaging
<HubName("djwHub")>
Public Class djwHub
Inherits Hub
Private connectString As String = "Endpoint=sb://mynamespace.servicebus.windows.net/;SharedAccessKeyName=myKeyName;SharedAccessKey=myKey"
Private queueName As String = "myQueueName"
Private m_count As Integer
Public Sub beginReadingMessageQue()
Dim rf = MessagingFactory.CreateFromConnectionString(connectString)
Dim taskTimer = Task.Factory.StartNew(Async Function()
Dim receiver = Await rf.CreateMessageReceiverAsync(queueName, ReceiveMode.PeekLock)
While True
Dim timeNow As String = DateTime.Now.ToString()
Clients.All.sendServerTime(timeNow)
Try
Dim message = Await receiver.ReceiveAsync(TimeSpan.FromSeconds(5))
If message IsNot Nothing Then
Dim messageBody = message.GetBody(Of [String])()
Clients.All.sendNewMessage(messageBody)
Await message.CompleteAsync
Else
'no more messages in the queue
Exit Try
End If
Catch e As MessagingException
If Not e.IsTransient Then
'Console.WriteLine(e.Message)
'Throw
End If
End Try
'Delaying by 1/2 second.
Await Task.Delay(500)
End While
End Function, TaskCreationOptions.LongRunning)
End Sub
End Class
现在,我的 MVC-5 Web 应用的根目录中没有 Startup 类。相反,我的启动发生在位于我的 App_Start 文件夹中的 IdentityConfig.vb 类中。所以这就是我放 app.MapSignalR() 的地方,如图所示;
Imports Microsoft.AspNet.Identity
Imports Microsoft.Owin
Imports Microsoft.Owin.Security.Cookies
Imports Owin
Imports myApp.Users.Infrastructure
Imports Microsoft.Owin.Security.Google
Imports Microsoft.AspNet.SignalR
Imports Microsoft.Owin.Cors
Imports Microsoft.AspNet.SignalR.ServiceBus
Namespace Users
Public Class IdentityConfig
Public Sub Configuration(app As IAppBuilder)
app.CreatePerOwinContext(Of AppIdentityDbContext)(AddressOf AppIdentityDbContext.Create)
app.CreatePerOwinContext(Of AppUserManager)(AddressOf AppUserManager.Create)
app.CreatePerOwinContext(Of AppRoleManager)(AddressOf AppRoleManager.Create)
app.UseCookieAuthentication(New CookieAuthenticationOptions() With { _
.AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie, _
.LoginPath = New PathString("/Account/Login") _
})
app.UseExternalSignInCookie(DefaultAuthenticationTypes.ExternalCookie)
app.MapSignalR()
End Sub
End Class
End Namespace
剩下的唯一部分是网页视图页面。请注意,我现在在网页上有 6 个 FusionChart 仪表。但是您应该能够挑选出与 djwHub 对话的 SignalR 函数调用;
@Code
Layout = Nothing
End Code
<head>
<title>Drillers Readout - Job #@ViewBag.JobNumber</title>
@Scripts.Render("~/bundles/modernizr")
@Scripts.Render("~/bundles/jquery")
@Scripts.Render("~/bundles/bootstrap")
@Scripts.Render("~/bundles/jqueryui")
<script src="~/Scripts/jquery.signalR-2.2.1.js"></script>
<script src="~/Scripts/jquery.signalR-2.2.1.min.js"></script>
<script src="~/signalr/hubs"></script>
<script type="text/javascript">
(function () {
var currentIndex = -1;
var lastTime;
var GxDisplay;
var GyDisplay;
var GzDisplay;
var HxDisplay;
var HyDisplay;
var HzDisplay;
var myHub = $.connection.djwHub;
$.connection.hub.logging = true;
myHub.client.sendNewMessage = function (message) {
var myArray = JSON.parse(message);
currentIndex += 1;
//var dataId = myArray.dataCount;
if (currentIndex == 0) {
lastTime = new Date(myArray.time1);
} else {
var newTime = new Date(myArray.time1);
if (newTime >= lastTime) {
var dataId = myArray.dataCount;
var Gx = myArray.Gx;
var Gy = myArray.Gy;
var Gz = myArray.Gz;
var Hx = myArray.Hx;
var Hy = myArray.Hy;
var Hz = myArray.Hz;
lastTime = newTime;
GxDisplay.feedData("value=" + Gx);
GyDisplay.feedData("value=" + Gy);
GzDisplay.feedData("value=" + Gz);
HxDisplay.feedData("value=" + Hx);
HyDisplay.feedData("value=" + Hy);
HzDisplay.feedData("value=" + Hz);
$("#newMessage").text('#' + dataId + ": " + lastTime + " Gx=" + Gx.toFixed(2) + " Gy=" + Gy.toFixed(2) + " Gz=" + Gz.toFixed(2)
+ " Hx=" + Hx.toFixed(2) + " Hy=" + Hy.toFixed(2) + " Hz=" + Hz.toFixed(2));
}
}
};
$.connection.hub.start().done(function () {
myHub.server.beginReadingMessageQue();
});
myHub.client.sendServerTime = function (serverTime) {
$("#newTime").text(serverTime);
};
FusionCharts.ready(function () {
GxDisplay = new FusionCharts({
type: 'angulargauge',
renderAt: 'GxChart',
width: '250',
height: '175',
dataFormat: 'json',
dataSource: {
"chart": {
"caption": "Gx",
"subcaption": "",
"lowerLimit": "-2000",
"upperLimit": "2000",
"lowerLimitDisplay": "",
"upperLimitDisplay": "",
"showValue": "1",
"valueBelowPivot": "1",
"theme": "fint"
},
"colorRange": {
"color": [{
"minValue": "-2000",
"maxValue": "2000",
"code": "#ADD8E6"
}]
},
"dials": {
"dial": [{
"id": "fcGx",
"value": "0"
}]
}
}
});
GyDisplay = new FusionCharts({
type: 'angulargauge',
renderAt: 'GyChart',
width: '250',
height: '175',
dataFormat: 'json',
dataSource: {
"chart": {
"caption": "Gy",
"subcaption": "",
"lowerLimit": "-2000",
"upperLimit": "2000",
"lowerLimitDisplay": "",
"upperLimitDisplay": "",
"showValue": "1",
"valueBelowPivot": "1",
"theme": "fint"
},
"colorRange": {
"color": [{
"minValue": "-2000",
"maxValue": "2000",
"code": "#ADD8E6"
}]
},
"dials": {
"dial": [{
"id": "fcGy",
"value": "0"
}]
}
}
});
GzDisplay = new FusionCharts({
type: 'angulargauge',
renderAt: 'GzChart',
width: '250',
height: '175',
dataFormat: 'json',
dataSource: {
"chart": {
"caption": "Gz",
"subcaption": "",
"lowerLimit": "-2000",
"upperLimit": "2000",
"lowerLimitDisplay": "",
"upperLimitDisplay": "",
"showValue": "1",
"valueBelowPivot": "1",
"theme": "fint"
},
"colorRange": {
"color": [{
"minValue": "-2000",
"maxValue": "2000",
"code": "#ADD8E6"
}]
},
"dials": {
"dial": [{
"id": "fcGz",
"value": "0"
}]
}
}
});
HxDisplay = new FusionCharts({
type: 'angulargauge',
renderAt: 'HxChart',
width: '250',
height: '175',
dataFormat: 'json',
dataSource: {
"chart": {
"caption": "Hx",
"subcaption": "",
"lowerLimit": "-100000",
"upperLimit": "100000",
"lowerLimitDisplay": "",
"upperLimitDisplay": "",
"showValue": "1",
"valueBelowPivot": "1",
"theme": "fint"
},
"colorRange": {
"color": [{
"minValue": "-100000",
"maxValue": "100000",
"code": "#ff1493"
}]
},
"dials": {
"dial": [{
"id": "fcHx",
"value": "0"
}]
}
}
});
HyDisplay = new FusionCharts({
type: 'angulargauge',
renderAt: 'HyChart',
width: '250',
height: '175',
dataFormat: 'json',
dataSource: {
"chart": {
"caption": "Hy",
"subcaption": "",
"lowerLimit": "-100000",
"upperLimit": "100000",
"lowerLimitDisplay": "",
"upperLimitDisplay": "",
"showValue": "1",
"valueBelowPivot": "1",
"theme": "fint"
},
"colorRange": {
"color": [{
"minValue": "-100000",
"maxValue": "100000",
"code": "#ff1493"
}]
},
"dials": {
"dial": [{
"id": "fcHy",
"value": "0"
}]
}
}
});
HzDisplay = new FusionCharts({
type: 'angulargauge',
renderAt: 'HzChart',
width: '250',
height: '175',
dataFormat: 'json',
dataSource: {
"chart": {
"caption": "Hz",
"subcaption": "",
"lowerLimit": "-100000",
"upperLimit": "100000",
"lowerLimitDisplay": "",
"upperLimitDisplay": "",
"showValue": "1",
"valueBelowPivot": "1",
"theme": "fint"
},
"colorRange": {
"color": [{
"minValue": "-100000",
"maxValue": "100000",
"code": "#ff1493"
}]
},
"dials": {
"dial": [{
"id": "fcHz",
"value": "0"
}]
}
}
});
GxDisplay.render();
GyDisplay.render();
GzDisplay.render();
HxDisplay.render();
HyDisplay.render();
HzDisplay.render();
});
}());
</script>
</head>
<body>
<div id="newTime"></div><br />
<ul id="newMessage"></ul>
<div id="gCharts">
<div id="GxChart"></div>
<div id="GyChart"></div>
<div id="GzChart"></div>
</div>
<div id="hCharts">
<div id="HxChart"></div>
<div id="HyChart"></div>
<div id="HzChart"></div>
</div>
</body>
在此特别感谢 astaykov 和 Ashley Medway 以及 Microsoft 让这一切成为可能!