如何使用SignalR在.NET 4.0系统中实现通知,该系统由ASP.NET MVC 3应用程序(使用表单身份验证),SQL Server 2008数据库和MSMQ WCF服务(托管在WAS中)来处理数据?运行时环境包含在Windows Server 2008 R2 Standard Edition上运行的IIS 7.5.
我只玩了样本,没有广泛的SignalR知识.
这是一些背景知识
Web应用程序接受来自用户的数据并将其添加到表中.然后,它调用WCF服务的单向操作(使用数据库密钥)来处理数据(任务).Web应用程序返回到一个页面,告诉用户数据已提交,并在处理完成时通知他们.用户可以查看"索引"页面,查看哪些任务已完成,失败或正在进行中.他们可以继续提交更多任务(这与以前的数据无关).他们可以关闭浏览器并稍后返回.
基于MSMQ的WCF服务从数据库中读取记录并处理数据.这可能需要几毫秒到几分钟的时间.处理完数据后,记录会以相应的状态(错误或失败)和结果进行更新.
大多数情况下,WCF服务不执行任何处理,但是当它执行时,用户通常希望尽快知道何时完成.即使用户没有要由WCF服务处理的数据,用户仍将使用Web应用程序的其他部分.
这就是我所做的
在主导航栏中,我有一个指示器(类似于Facebook或Google+),供用户在任务状态发生变化时通知他们.当他们点击它时,他们会得到已完成的内容的摘要,然后可以根据需要查看结果.
使用jQuery,我轮询服务器的更改.控制器操作检查是否存在任何已修改(已完成或失败)的进程并返回它们,否则等待几秒钟并再次检查而不返回客户端.为了避免客户端超时,如果没有更改,它将在30秒后返回.jQuery脚本等待一段时间再试一次.
问题
每个查看页面的用户的性能都会下降.他们没有必要特别做任何事情.我们注意到Firefox 7+和Safari的内存使用量会随着时间的推移而增加.
使用SignalR
我希望切换到SignalR可以减少轮询,从而减少资源需求,尤其是在数据库中没有任何改变任务的情况下.我很难通过WCF服务来通知客户端它已完成处理任务,因为它使用基于表单的身份验证.
通过提出这个问题,我希望有人能够更好地了解他们如何使用SignalR重新设计我的通知方案,如果有的话.
我刚刚开始探索signalR,我希望能够从服务器向所有客户端发送消息.
这是我的中心
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using SignalR;
using SignalR.Hubs;
using SignalR.Hosting.Common;
using SignalR.Hosting.AspNet;
using System.Threading.Tasks;
namespace MvcApplication1
{
public class Chat : Hub
{
public void Send(String message)
{
// Call the addMessage methods on all clients
Clients.addMessage(message);
}
}
}
Run Code Online (Sandbox Code Playgroud)
这是我的客户页面
<script type="text/javascript">
$(function () {
//Proxy created on the fly
var chat = $.connection.chat;
// Declare a function on the chat hub so the server can invoke it
chat.addMessage = function (message) { …Run Code Online (Sandbox Code Playgroud) 我在EPiServer 7.5(MVC4框架)中遇到了一些SignalR 2.0的问题.我得到的只是404错误
获取http://web.com/signalr/hubs 404(未找到)
我在Windows 2012 R2服务器上托管所有内容.另外值得注意的是,当从Visual Studio中运行IIS Express中的所有内容时,该解决方案仍然有效,但在IIS 8.5中则无法运行.
到目前为止我所做的是添加SingalR参考.
Startup.cs
启动是在应用程序启动时初始化的,所以似乎工作.
[assembly: OwinStartup(typeof(Web.Startup))]
namespace Web
{
public class Startup
{
#region Local variables
private static readonly ILog Logger = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
#endregion
#region Methods
/// <summary>
/// Configure SignalR
/// </summary>
/// <param name="app"></param>
public void Configuration(IAppBuilder app)
{
try
{
Logger.MethodCallEntry();
// Any connection or hub wire up and configuration should go here …Run Code Online (Sandbox Code Playgroud) 我正在使用SignalR在asp.net中实现聊天,但是当我打开我的Web应用程序的多个选项卡时,我正在 "等待可用的套接字......".
我已经实现了Performance Tuning SignalR上指定的所有设置,但我的问题没有得到解决.
我该如何解决这个问题?
我创建了一个自托管Owin/SignalR应用程序,代码类似于本教程中的代码:
一切正常,但出于安全考虑,我想将其限制为仅允许来自特定远程站点的消息.换句话说,我想替换"app.UseCors(CorsOptions.AllowAll);" 使用代码来限制应用程序仅响应来自我定义的URL的消息,即仅允许来自http://www.remote_site.com等的消息.有没有简单的方法来做到这一点?
作为参考,这是我的SignalR启动类的代码:
using System;
using Microsoft.AspNet.SignalR;
using Microsoft.Owin.Hosting;
using Owin;
using Microsoft.Owin.Cors;
namespace SignalRSelfHost
{
public class Startup
{
public void Configuration(IAppBuilder app)
{
app.UseCors(CorsOptions.AllowAll);
app.MapSignalR();
// How do I only allow a specific URL instead of the "CorsOptions.AllowAll" option?
}
}
}
Run Code Online (Sandbox Code Playgroud) 我有一个非常令人沮丧的问题,我似乎无法深究.
我正在使用SignalR将消息推送到移动设备,并且多次触发客户端方法.当我退出时应该清除/关闭/停止连接时,它发出的次数会增加.
我的中心如下所示
public class MyHub:Hub
{
private static string _groupIdentifier = "Test"
public override Task OnConnected()
{
var identity = //grab identity from auth provider
Groups.Add(Context.ConnectionId, string.Format("{0}-{1}", _groupIdentifier, identity.UserId));
return base.OnConnected();
}
public void OnMessageCreated(Message message)
{
IHubContext context = GlobalHost.ConnectionManager.GetHubContext<MessageCreatedEmitter>();
context.Clients.Group(String.Format("{0}-{1}",_groupIdentifier, message.userId)).onMessageCreated(obj);
}
public override Task OnReconnected()
{
var identity = //grab identity from my auth provider
Groups.Add(Context.ConnectionId, string.Format("{0}-{1}", _groupIdentifier, identity.UserId));
return base.OnReconnected();
}
public override Task OnDisconnected(bool stopCalled)
{
var identity = //grab identity from my auth …Run Code Online (Sandbox Code Playgroud) 所以我被困在这个问题大约一个星期.我试图运行一个项目来接收TCP连接并启动SignalR Hub作为服务.两者都完美地将项目作为.exe文件运行.TCP部分可以完美地工作,但是我遇到了SignalR方面的问题.
原因最终是使用声明.
之前
using (WebApp.Start<SignalrStartup>(url))
{
Console.ForegroundColor = ConsoleColor.Green;
Console.WriteLine("Server running on {0}", url); // was url
Console.WriteLine("ID\tMessage");
Console.ReadLine();
}
Run Code Online (Sandbox Code Playgroud)
后
WebApp.Start<SignalrStartup>(url);
Run Code Online (Sandbox Code Playgroud)
我曾尝试使用Console.WriteLine()注释掉的代码来运行代码,因为我认为它可能会抛出一个异常,因为没有控制台输出到一次作为服务运行.这也不起作用,但也不能作为.exe文件工作,因为它需要Console.ReadLine()保持控制台打开,排序你需要它来保持HelloWorld.cs打开.一旦使用的包装器与控制台一起被移除,它将在.exe和服务中工作.
我已经读过,一旦你离开包装器,using语句会杀死它中的对象.但我不明白After bit代码如何在运行时保持.exe代码打开.有没有使用任何点使用或曾经我一直在使用它错了吗?
编辑
protected override void OnStart(string[] args)
{
Task.Factory
.StartNew(() => StartTCP())
.ContinueWith(t => StartSignalR());
}
Run Code Online (Sandbox Code Playgroud)
该调用是从该StartSignalR()方法进行的.
当使用 SignalR 和 MessagePack 在 JavaScript 和 C# 之间序列化和反序列化值时,我在接收端看到 C# 中的一些精度损失。
例如,我将值 0.005 从 JavaScript 发送到 C#。当反序列化的值出现在 C# 端时,我得到的值0.004999999888241291很接近,但不是 0.005。JavaScript 端的值是Number和我正在使用的 C# 端double。
我读过 JavaScript 无法准确表示浮点数,这会导致像0.1 + 0.2 == 0.30000000000000004. 我怀疑我看到的问题与 JavaScript 的这个特性有关。
有趣的部分是,我没有看到同样的问题反过来。将 0.005 从 C# 发送到 JavaScript 会导致 JavaScript 中的值 0.005。
编辑:来自 C# 的值只是在 JS 调试器窗口中缩短了。正如@Pete 提到的,它确实扩展到不完全是 0.5 的值(0.005000000000000000104083408558)。这意味着差异至少发生在双方。
JSON 序列化没有相同的问题,因为我假设它通过字符串传递,这使得接收环境处于控制状态,并将值解析为其本机数字类型。
我想知道是否有一种方法可以使用二进制序列化在双方都有匹配的值。
如果不是,这是否意味着无法在 JavaScript 和 C# 之间进行 100% 准确的二进制转换?
使用的技术:
我的代码基于 …
使用SignalR,我想知道设置我的集线器的最佳方式是在以下场景下:假设我有一个网络赌场应用程序(只是为了好玩),它有三个游戏,扑克,二十一点和老虎机.扑克和二十一点都是多人游戏,因此他们有聊天功能而插槽没有.好的,为了支持这一点,我正在考虑以下列方式设置我的集线器.
BaseHub(处理扑克,二十一点和老虎机常见的连接内容)
PokerHub:BaseHub(处理扑克游戏)
BlackjackHub:BaseHub(处理二十一点游戏)
SlotsHub:BaseHub(处理老虎机游戏)
ChatHub(处理聊天功能)
我想这个网络应用程序的扑克页面连接到PokerHub以及ChatHub和Blackjack页面会做类似的事情.Slots页面显然只能连接到SlotsHub.
现在,我不确定的事情是:扑克/二十一点页面是否应该连接到PokerHub/BlackjackHub和ChatHub,或者是否有某种方式可以让他们只连接到PokerHub/BlackjackHub并将聊天功能委托给聊天毂?在这种情况下,我可能会创建一个接口IHasChat或类似的东西.在任何一种情况下,ChatHub都应该扩展BaseHub吗?目前,BaseHub仅实现IConnected,IDisconnect以及处理基本的Group功能(JoinGroup,LeaveGroup).另外,BaseHub应该是一个共享实例(单例)吗?
最后,如果你认为我只是完全错了,请告诉我.这是我的第一个SignalR项目,我知道我不是它的专家.另外,我知道这里有几个问题.如果你能回答其中的任何一个或全部,无论哪种方式,我都非常感激.
谢谢,汤姆
是否有推荐的方法在两个应用程序之间共享SignalR集线器?
实际情况是面向公众的WebAPI项目和内部MVC WebApp.我想做的是从WebAPI项目调用SignalR集线器上的方法,并将这些方法的结果推送到通过MVC应用程序连接的客户端.
最好的选择是创建第三个"Hub"项目并让两个项目连接到那个项目吗?如果是这样,如何管理集线器实例?两个应用程序是否可以从不同的应用程序池(以及可能的主机)获取对同一集线器的引用?
我读了一下GlobalHost.ConnectionManager.GetHubContext,这是否足以让两个应用程序都可以使用一个有效的单例集线器?
任何想法都非常感激.
signalr ×10
c# ×6
signalr-hub ×3
angularjs ×1
asp.net ×1
cors ×1
episerver-7 ×1
javascript ×1
msgpack ×1
msmq ×1
owin ×1
using ×1
wcf ×1