我正在使用ASP.NET Core 2.1 RC1。 我也在使用Signal-R(在这里找到):
https://docs.microsoft.com/en-us/aspnet/core/signalr/javascript-client?view=aspnetcore-2.1
我正在创建一个托管Kestrel并使用Signal-R的.NET Core控制台应用程序。我已经设置了完全作为设置启动的入门文档说明。
这一切都很棒。我能够连接到它,使用signal-R脚本获取我的HTML,接收我使用Clients.All.SendAsync制作的消息。效果很好。
BUT 我希望能够从Hub外部向客户发送消息。在我的应用程序中发生某些事件,并向客户端发送消息。在完整的.NET中,我将使用GlobalHost并获取上下文。在 ALL 我对Stack Overflow的搜索中,它们引用了一些不再有效的东西,或者在IHubContext中传递的REST API控制器中使用。
我在program.cs中有一个事件监听器,当事件被触发时,我希望能够向我的UserInterfaceHub发送一条消息。
那么 - 如何在Program.CS中获取集线器上下文 - 所以我可以从Program.CS中的事件委托中向它发送消息(调用SwitchUI方法)?
StartUp.cs
public void ConfigureServices(IServiceCollection services) {
services.Configure<CookiePolicyOptions>(options => {
options.CheckConsentNeeded = context => true;
options.MinimumSameSitePolicy = SameSiteMode.None;
});
services.AddMvc();
services.AddCors(options => options.AddPolicy("CorsPolicy",
builder => {builder.AllowAnyMethod().AllowAnyHeader().AllowAnyOrigin().AllowCredentials();}));
services.AddSignalR();
var provider = services.BuildServiceProvider();
}
public void Configure(IApplicationBuilder app, IHostingEnvironment env) {
if (env.IsDevelopment()) app.UseDeveloperExceptionPage();
app.UseStaticFiles();
app.UseCookiePolicy();
app.UseCors("CorsPolicy");
app.UseSignalR(routes => {routes.MapHub<UserInterfaceHub>("/uihub");});
app.UseMvc();
//app.Run(async (context) =>{await context.Response.WriteAsync("Active");});
}
Program.cs的
CreateWebHostBuilder(args)
.UseKestrel()
.UseUrls("http://0.0.0.0:" + appProperties.HostPort.ToString().Trim())
.UseContentRoot(Directory.GetCurrentDirectory())
.UseIISIntegration()
.Build()
.Start();
UserInterfaceHub.cs
namespace InterfaceModule.Hubs {
public class UserInterfaceHub : Hub {
public async Task SwitchUI(string message) {
await Clients.All.SendAsync("ReceiveEvent", message);
}
public override async Task OnConnectedAsync() {
//await SwitchUI("HOWDY NEW PERSON!");
await base.OnConnectedAsync();
}
}
}
修改添加清晰度。
在Program.CS中,我有这个事件委托: //现在我们准备好了,开始听。 等待
deviceClient.SetInputMessageHandlerAsync(ModuleProperties.InputName, OnReceiveEvent, deviceClient);
Console.WriteLine("INIT: Event Message Input handler created: [{0}]", ModuleProperties.InputName);
这是:
static async Task<MessageResponse> OnReceiveEvent(Message message, object userContext) {
//HOW DO I REACH THE HUB FROM HERE SO I CAN SEND A MESSAGE TO THE LISTENERS?
}
答案 0 :(得分:1)
这行代码:
content
将使用DI容器注册您的集线器。然后,要访问它,您可以使用构造函数注入来注入Book.objects.filter(published=True)#.ignore_fields('content',).order_by('read')
(例如在Web控制器中工作),或者通过执行以下操作直接从DI容器访问它:
app.UseSignalR(routes => {routes.MapHub<UserInterfaceHub>("/uihub");});
(例如,如果在startup.cs IHubContext<UserInterfaceHub>
方法中执行)
如果您无法访问在您需要访问集线器的位置基本上是 var hub = app.ApplicationServices.GetRequiredService<IHubContext<UserInterfaceHub>>();
的{{1}},那么您需要1)让该课程与之合作依赖注入注入Configure
或app.ApplicationServices
2)通过IServiceProvider
设置静态服务全局变量,以便您可以全局访问其中一个,或者找到其他方式来访问DI容器(又名IServiceProvider)通过上面的代码行获取您的集线器。
拥有集线器后,将消息发送到已注册的客户端就像调用集线器上的方法一样简单。
IHubContext<UserInterfaceHub>
答案 1 :(得分:0)
您的问题有点不清楚,但我假设您的意思是要将以下内容替换为可通过您的中心发送消息的内容:
app.Run(async (context) =>{await context.Response.WriteAsync("Active");});
由于这是Configure
方法,您只需将IServiceCollection services
添加到Configure
方法参数中即可。然后,你可以这样做:
var hub = services.GetRequiredService<IHubContext<MyHub>>();
但是,我不确定这最终会有什么用处。在启动时,您在逻辑上没有订阅客户端。因此,此时通过集线器发送消息基本上无处可去。当用户实际访问您的网站并连接到您的中心时,您的应用程序的这一部分已经运行,并且不会再被点击。
答案 2 :(得分:0)
我遇到了类似的情况,下面是解决方法:
在您的服务层中,创建一个称为ISendHubMessage之类的接口。有一个名为Send()的方法,该方法获取您要通过SignalR发送的参数。在名为SendHubMessage的同一文件中创建一个实现该接口的类。让它退货吧。
在顶级项目(位于Startup.cs文件所在的位置)中,创建另一个名为SendHubMessage的类,该类从服务层实现相同的ISendHubMessage接口。在该SendHubMessage中,您可以使用DI到达集线器,如上所述。此方法将执行通过SignalR发送的实际逻辑。
在您的Startup ConfigureServices()方法中,添加以下行:
services.AddTransient <“ Service” .ISendHubMessage,“ TopLevel” .SendHubMessage>();
(其中“服务”是服务级别项目的名称空间,而“顶级”是顶级项目的名称空间)。
此行的意思是“每当对象从Service层请求ISendHubMessage依赖项时,向其提供在我的顶级项目中定义的SendHubMessage类”。
最后,在您想通过集线器发送消息的顶级项目之外的代码中的所有位置,都将ISendHubMessage依赖项注入到构造函数中。然后,您可以在类方法中引用它,当您调用Send()时,它将调用顶级项目中SendHubMessage类中定义的Send()方法。