天道酬勤,学无止境

Using SignalR Core to send messages from a Controller Method to Angular

I'm trying to use SignalR for Asp Net Core 2.1 in order to send a message from a controller method which call is triggered from a test button in Angular.
The behavior I'd expect is that when I click the button, my service invokes the controller method, which sends the test message. Then, I will simply log the message.

I want to manage this in a service in order to avoid code duplication in all of the components.

I've read some examples like this question about using SignalR in a service (I've used the second solution) and this article and the official docs but even with applying these concepts it don't seems to work.
(So, or I'm absolutely applying them in a wrong way or there's still something missing but I can't find out what...)

The client connects to the Message Hub successfully and if I click the button, the method is getting hit but I don't get any message and instead I get this warning in the Chrome console:

Warning: No client method with the name 'SendAsync' found.

Sending messages works fine, the issue is just with receiving them...

The question is: what am I doing wrong? Is the error on the back-end side or in the Angular side?


I share with you all of my code (the button and the service to call the controller method are not relevant since the call to the service goes fine):

> Startup.cs

public void ConfigureServices(IServiceCollection services)
{
   //...
   services.AddSignalR();
}
//...
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
   //...
   app.UseSignalR(routes =>
   {
      //...
      routes.MapHub<MessageHub>("/messagehub");
      //...
   });
}

> MessageHub.cs

public class MessageHub : Hub<ITypedHubClient>
{
    public async Task SendMessage(string user, string message)
    {
        await Clients.All.SendAsync("ReceiveMessage", user, message);
    }
}

public interface ITypedHubClient
{
    Task SendAsync(string title, string name, string message);
}

> MessageController.cs

IHubContext<MessageHub, ITypedHubClient> _messageHubContext;

public MessageController(IHubContext<MessageHub, ITypedHubClient> messageHubContext)
{
    _messageHubContext = messageHubContext;
}

[HttpPost("Test")]
public async Task<IActionResult> Test()
{
    try
    {
        await _messageHubContext.Clients.All.SendAsync("ReceiveMessage","test", "test");

        return Ok(true);
    }
    catch (Exception e)
    {
        return BadRequest(e);
    }
}

> communication.service.ts

@Injectable()
export class CommunicationService {

  private _hubConnection: HubConnection | undefined;
  public async: any;
  message = '';
  messages: string[] = [];

  private newmessage = new Subject<string>();
  message$ = this.newmessage.asObservable();


  constructor() {
    this._hubConnection = new signalR.HubConnectionBuilder()
      .withUrl('/messagehub')
      //.configureLogging(signalR.LogLevel.Information)
      .configureLogging(signalR.LogLevel.Debug)
      .build();

    this._hubConnection.start().catch(err => console.error(err.toString()));

    this._hubConnection.on('SendMessage', (user: any, message:any) => {
      const received = `Received: ${message}`;
      //this.messages.push(received);
      this.newmessage.next(received);
      console.log("got something new...", received);
    });
  }

  clear() {
    this.newmessage.next("");
  }

  public sendMessage(): void {
    const data = `Sent: ${this.message}`;

    if (this._hubConnection) {
      this._hubConnection.invoke('SendMessage', 'AAA' ,data);
    }
    this.messages.push(data);
  }
}

评论

In signalr core 2.1 you can use strongly typed hubs to declare in an interface what actions can be called on the clients :

public class MessageHub : Hub<ITypedHubClient>
{
    public async Task SendMessage(string title, string user, string message)
    {
        await Clients.All.SendMessageToClient(title, user, message);
    }
}
public interface ITypedHubClient
{
    Task SendMessageToClient(string title, string name, string message);
}

in the controller :

    IHubContext<MessageHub, ITypedHubClient> _messageHubContext;

    public async Task<IActionResult> Test()
    {
        await _messageHubContext.Clients.All.SendMessageToClient("test", "test", "test");
        return Ok("ok");
    }

in the client :

_hubConnection.on('SendMessageToClient', (title, user, message) => {
    const received = `title: ${title}, name: ${user}, message: ${message}`;
    console.log(received);
});

If you don't use strongly typed hub, then to call the same method in the client it becomes :

public class MessageHub : Hub
{
    public async Task SendMessage(string title, string user, string message)
    {
        await Clients.All.SendAsync("SendMessageToClient", title, user, message);
    }
}

In that case you can use the SendAsync method on the client proxy, it's first parameter is the name of the method you want to call.

Update : When we define a strongly typed hub with an interface, all interface methods must return a Task. With custom methods, signalr generates methods that call SendCoreAsync. That allow us to call these methods asynchronously.

If the return type of the interface methods is not a Task we get the error : All client proxy methods must return 'System.Threading.Tasks.Task'

受限制的 HTML

  • 允许的HTML标签:<a href hreflang> <em> <strong> <cite> <blockquote cite> <code> <ul type> <ol start type> <li> <dl> <dt> <dd> <h2 id> <h3 id> <h4 id> <h5 id> <h6 id>
  • 自动断行和分段。
  • 网页和电子邮件地址自动转换为链接。

相关推荐
  • 从控制器调用 SignalR Core Hub 方法(Call SignalR Core Hub method from Controller)
    问题 如何从 Controller 调用 SignalR Core Hub 方法? 我将 ASP.NET Core 2.0 与 Microsoft.AspNetCore.SignalR (1.0.0-alpha2-final) 一起使用。 我有与 Excel、SolidEdge 通信的 Windows 服务......操作完成后,它会在 ASP.NET Core 应用程序中向我的控制器发送请求。 现在我需要用 SignalR 通知所有连接到服务器的客户端外部程序完成了一些任务。 我无法改变窗口服务的工作方式。 (无法从窗口服务连接到 SignalR)。 我发现老SignalR(大量的解决方案GlobalHost.ConnectionManager.GetHubContext ),但大部分已经改变,这些解决方案都不能工作了。 我的控制器: [Route("API/vardesigncomm")] public class VarDesignCommController : Controller { [HttpPut("ProcessVarDesignCommResponse/{id}")] public async Task<IActionResult> ProcessVarDesignCommResponse(int id) { //call method
  • 请求线程外的ASP.NET Core RC2 SignalR集线器上下文(ASP.NET Core RC2 SignalR Hub Context outside request thread)
    问题 我目前正在尝试ASP.NET Core的RC2版本,并且遇到SignalR的问题。 我需要能够将消息发送到请求线程之外的客户端。 现在,在完整的.NET框架中,您可以像这样进行操作: var context = GlobalHost.ConnectionManager.GetHubContext<MyHub>(); context.Clients.<SendMessage>() 但是在ASP.NET Core中没有GlobalHost 。 我发现了一个类似的问题:如何在vNext项目中获取SignalR Hub上下文? 第二个答案提供了一种在请求线程之外获取hubcontext的方法,但这在ASP.NET Core也不起作用。 所以我的问题是:如何在ASP.NET Core的请求范围之外获取集线器上下文? 回答1 您将必须从:Signalr Github中获取当前的github版本(在撰写本文时,提交: b95ac7b ) 一旦有了它,并加载了解决方案,或将所有三个项目添加到现有解决方案中,您将需要在所有三个项目中更改project.json。 Microsoft.AspNetCore.SignalR.Server-project.json 您将看到每个组件的版本1.1.0- *(RC3)的引用。 将它们更改为当前的RC2,直到看到以下内容 "Microsoft
  • Angular/SignalR Error: Failed to complete negotiation with the server
    Using SignalR for my server and Angular for my client... When I run my client I receive these errors: zone.js:2969 OPTIONS https://localhost:27967/chat/negotiate 0 () Utils.js:148 Error: Failed to complete negotiation with the server: Error Utils.js:148 Error: Failed to start the connection: Error I am guessing it is something with CORS... I am trying to implement a simple chat application. I am using the latest verison of SignalR: Here is the github that contains the code for the tutorial I am following. SignalR Chat Tutorial Here is my startup using Microsoft.AspNetCore.Builder; using
  • 从WebAPI控制器问题调用SignalR集线器(calling SignalR hub from WebAPI controller issues)
    问题 我无法弄清楚如何从WebAPI ApiController调用SignalR集线器。 我整理了一个样本,您可以在此处下载该样本,以简化问题并演示问题。 我从ASP.NET MVC WebAPI模板创建了一个新项目。 我向该项目添加了一个新的SignalR Hub,名为ChatHub。 添加了一个HTML页面,该页面在加载时连接到ChatHub,加入一个组并向该组发送消息。 这很好用。 HTML页面还具有一个按钮,单击该按钮将触发对ValuesController的post方法的ajax调用。 在ValuesController的post方法中,我想向组中所有连接的客户端广播消息。 我无法使它正常工作。 我有一个仅使用2种方法的简单SignalR集线器。 [HubName("chat")] public class ChatHub : Hub { public void Join(string room) { // NOTE: this is not persisted - .... Groups.Add(Context.ConnectionId, room); } public void Send(string room, string message) { var msg = String.Format( "{0}: {1}", Context.ConnectionId
  • calling SignalR hub from WebAPI controller issues
    I cannot figure out how I can call into a SignalR hub from a WebAPI ApiController. I have put together a sample you can download here that simplifies the problem and demonstrates the issue. I created a new project from the ASP.NET MVC WebAPI template. I added a new SignalR Hub to the project called ChatHub. Added a HTML page that on load, connects to ChatHub, joins to a group and sends a message to that group. This works great. HTML page also has a button that when clicked will fire an ajax call to the ValuesController's post method. In the ValuesController's post method, I want to broadcast a
  • 如何在ASP.NET Core中获取SignalR Hub上下文?(How to get SignalR Hub Context in a ASP.NET Core?)
    问题 我正在尝试使用以下命令获取中心的上下文: var hubContext = GlobalHost.ConnectionManager.GetHubContext<SomeHub>(); 问题是没有定义GlobalHost。 我看到它是SignalR.Core dll的一部分。 目前,我在项目.json文件中的依赖项中包含以下内容: "Microsoft.AspNet.SignalR.Server": "3.0.0-*" 如果我添加Core的最新可用版本: "Microsoft.AspNet.SignalR.Server": "3.0.0-*", "Microsoft.AspNet.SignalR.Core" : "2.1.2" 我收到很多错误,因为服务器和核心冲突。 如果我将它们都更改为都使用版本“ 3.0.0- *”,则所有冲突都将消失,但是找不到GlobalHost。 如果我删除服务器,而仅使用用户核心版本2.1.2,则GlobalHost可以工作,但是所有其他需要服务器的东西显然都不能。 有任何想法吗? 回答1 Microsoft.AspNet.SignalR.Infrastructure.IConnectionManager是一种DI注入服务,通过它可以获取集线器上下文...例如: using Microsoft.AspNet.SignalR; using
  • 在Typescript中使用ASP.NET Core SignalR和React创建实时应用程序
    目录 介绍 ScrumPoker应用程序 源代码 开发工具 基本步骤 后端代码 创建Hub 在Startup中注册集线器 创建持久性 让我们为客户端应用程序公开一些终端 启用Cors 前端代码 结论 SignalR现在包含在ASP.NET Core框架中,并且进行了大量改进,使其轻巧易用。令我惊讶的是,我找不到任何有关如何使用SignalR的好教程,并且无法使用它使相同的旧聊天应用程序变得有趣。我想到了用SignalR创建一些东西,而不是同一个无聊的聊天应用程序。 介绍 在本教程中,我将指导您完成创建实时应用程序所需的主要步骤。我不会在这里写完整的代码。您可以在github 上找到完整的源代码。 ScrumPoker应用程序 在本教程中,我们将创建一个有趣的应用程序,名为ScrumPoker。我们生活在敏捷的世界中,因此在我们的开发过程或每个冲刺周期中进行故事评估并指出要点很普遍。过去,我们曾经计划使用扑克牌,而团队则通过这些牌来进行故事评估,但是现在一切都在线上了,我们经常进行远程工作。 用户可以创建ScrumBoard链接并与队友共享链接。团队成员可以进入那里并开始指出故事。只有当创建的用户ScrumBoard允许他们查看时,团队给出的点才会显示在仪表板上。 用户会实时添加到仪表板上,他们提交的点也会实时反映出来。 源代码 ├───clientapp├───Contracts├
  • 如何在Android中使用Signalr(How to use signalr in Android)
    问题 我正在尝试将signalR集成到android应用中,但是没有运气。 我一直在研究各种链接,但没有一个提供有关实现的适当信息。 我有以下问题。 SignalR集成必须在服务/意图服务内部完成吗? 如果我们想通过相同的调用方法接收响应,那么如何获得? 我添加了三个库,即signalr android , signalr client和gson但无法理解代码的工作原理,没有适当的文档可用来理解代码。 提出了一些问题,但没有太多信息 Android Studio中的SignalR无法使用Android中的SignalR实现p2p聊天 如果有人对本机应用程序的信号处理有经验,那对我会非常有帮助。 更新 public class SignalRService extends Service { private static final String TAG = "Service"; private HubConnection mHubConnection; private HubProxy mHubProxy; private Handler mHandler; // to display Toast message private final IBinder mBinder = new LocalBinder(); private SharedPreferences sp;
  • 您网站上的多个signalR连接/集线器(Multiple signalR connections/hubs on your website)
    问题 如果我有多个页面可以使用多个中心类,那么管理此问题的最佳方法是什么? 例如: 导航到网站上的另一个页面并从本质上“重新打开”与上一页中打开的同一集线器类的连接是否不好? 我是否认为在页面上打开多个集线器连接是正确的,因为即使它们是不同的集线器类,它们也都统一在一个连接中? 回答1 您可以有多个集线器在您的站点上共享一个连接。 SignalR 2.0已更新,可以通过一个信号连接处理多个集线器,而不会降低性能。 官方文档:http://www.asp.net/signalr/overview/signalr-20/hubs-api/hubs-api-guide-server#multiplehubs 所有客户端将使用相同的URL与您的服务建立SignalR连接(“ / signalr”或您的自定义URL(如果您指定了一个)),并且该连接用于该服务定义的所有集线器。 与在单个类中定义所有集线器功能相比,多个集线器没有性能差异。 回答2 要开始使用集线器,请阅读集线器和集线器的客户端的WIKI条目。 根据多个页面的上下文,有几件事情。 启动集线器时,它将为您的客户提供一个ID,该ID在多个页面上都与该集线器相同(可以通过示例进行确认)。 重新打开与同一集线器的连接也不错。 您可能在所有页面上都运行hub.start客户端方法,但是,如果一个客户端打开多个窗口或从一个页面转到另一个页面
  • SignalR无法读取未定义的属性客户端(SignalR cannot read property client of undefined)
    问题 我正在尝试将SignalR添加到我的项目(ASPNET MVC 4)中。 但是我不能使它工作。 在下图中,您可以看到我收到的错误。 我已经阅读了很多stackoverflow帖子,但是都没有解决我的问题。 这是我到目前为止所做的: 1) Ran Install-Package Microsoft.AspNet.SignalR -Pre 2) Added RouteTable.Routes.MapHubs(); in Global.asax.cs Application_Start() 3) If I go to http://localhost:9096/Gdp.IServer.Web/signalr/hubs I can see the file content 4) Added <modules runAllManagedModulesForAllRequests="true"/> to Web.Config 5) Created folder Hubs in the root of the MVC application 6) Moved jquery and signalR scripts to /Scripts/lib folder (I'm not using jquery 1.6.4, I'm using the latest) 这是我的Index.cshtml
  • SignalR使用GlobalHost.ConnectionManager.GetHubContext从外部集线器调用客户端方法不起作用。 但是从集线器内部进行呼叫确实可以(SignalR calling client method from outside hub using GlobalHost.ConnectionManager.GetHubContext doesn't work. But calling from within the hub does)
    问题 我正在尝试从.net Web API控制器操作中调用客户端方法。 我可以这样做吗? 我可以找到的唯一一篇与我要完成的工作非常接近的帖子是: SignalR +通过操作方法将消息发布到集线器 在那里,使用GlobalHost.ConnectionManager.GetHubContext从asp.net MVC控制器操作中发送一条消息。 当我在Web API操作中尝试该操作时,不会引发任何错误,但是永远不会在客户端调用方法“ methodInJavascript”。 Public ActionResult MyControllerMethod() { var context = GlobalHost.ConnectionManager.GetHubContext<MyHub>(); context.Clients.All.methodInJavascript("hello world"); // or context.Clients.Group("groupname").methodInJavascript("hello world"); } 当我在该动作中设置断点时,我看到代码已到达并执行。 不过,javascript客户端没有任何反应。 为什么? Web API到底有什么不同,以至于无法使用? 有没有其他人尝试过并取得成功? 当我从集线器“内部”调用“
  • In ASP.NET Core SignalR, how do I send a message from the server to a client?
    I've successfully setup a SignalR server and client using the newly released ASP.NET Core 2.1. I built a chat room by making my ChatHub extend Hub: whenever a message comes in from a client, the server blasts it back out via Clients.Others. What I do not yet understand is how to send a message to clients not as a response to an incoming message. If the server is doing work and produces a result, how do I gain access to the Hub in order to message particular clients? (Or do I even need access to the Hub? Is there another way to send messages?) Searching this issue is difficult as most results
  • How can I pass a SignalR hub context to a Hangfire job on ASP .NET Core 2.1?
    How can I pass a SignalR hub context to a Hangfire job on ASP .NET Core 2.1? It seems that since passing arguments to Hangfire is done via serialization/deserialization, it seems that Hangfire has hard-time reconstructing the SignalR hub context. I schedule the job (in my controller) using : BackgroundJob.Schedule(() => _hubContext.Clients.All.SendAsync( "MyMessage", "MyMessageContent", System.Threading.CancellationToken.None), TimeSpan.FromMinutes(2)); Then after 2 minutes, when the job tries to execute, I have the error : Newtonsoft.Json.JsonSerializationException: Could not create an
  • Asp.Net Core 3.1 SignalR 启动配置变化
    一、Asp.Net Core 3.1 SignalR 启动配置变化 在.net Core 3.1版本不少的api使用方式发生变化。 在Asp.net Core 3.1中SignalR配置方式如下: using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.HttpsPolicy; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; using SignalRChat.Hubs; namespace SignalRChat { public class Startup { public Startup(IConfiguration configuration) { Configuration = configuration; } public
  • 如何在.NET客户端中通过SignalR发送大数据(How to send big data via SignalR in .NET client)
    问题 我们有一个.NET客户端,它使用SignalR调用Server方法,但是该参数似乎很大,对于这种情况如何解决? 客户代码: public async Task FooAsync() { var hubConnection = new HubConnection(...); await hubConnection.Start(); var hubProxy = hubConnection.CreateHubProcx("ValueHub"); //the content is very long, about 11776065 bytes (11MB) var content = File.ReadAllText(...); hubProxy.Invoke("Send", content); ... } 服务器代码: [HubName("ValueHub")] public class ValueHub : Hub { public void Send(string json) { } } 从异常堆栈和源代码中,我发现SignalR在内部使用HttpClient且FormUrlEncodedContent类型为HttpContent ,并且限制可能来自此处。 System.UriFormatException was unhandled HResult=-2146233033
  • Call SignalR Core Hub method from Controller
    How can I call SignalR Core Hub method from Controller? I am using ASP.NET Core 2.0 with Microsoft.AspNetCore.SignalR (1.0.0-alpha2-final). I have windows service which communicate with Excel, SolidEdge ... When operation is complete it post request to my controller in ASP.NET Core application. Now I need to inform all clients connected to server with SignalR that external program completed some task. I can not change the way window service works. (Can not connect to SignalR from window service). I found plenty solution for old SignalR (GlobalHost.ConnectionManager.GetHubContext), but much has
  • ASP.Net MVC中长时间运行的服务器调用的进度条(Progress bar for long running server calls in ASP.Net MVC [closed])
    问题 关闭。 这个问题需要调试细节。 它当前不接受答案。 想要改善这个问题吗? 更新问题,使它成为Stack Overflow的主题。 2年前关闭。 改善这个问题 我只想在长时间运行服务器调用时创建一个进度条。 控制器执行长时间运行的工作时,无法向控制器创建ajax发布请求。 我想要创建一个其他操作来获取当前长期运行任务的实际语句。 我试图在ajax请求中创建民意调查,然后可以从服务器端返回状态并将其显示在客户端进度栏中。 有任何想法吗 ? 回答1 正确,最简单的方法是使用SignalR。 请在https://www.nuget.org/packages/Microsoft.AspNet.SignalR/2.1.2中下载Microsoft SignalR 在项目路径的单独文件夹中创建中心类,称为“中心”,将两个类文件添加到“中心”文件夹中 Startup.cs using Owin; using Microsoft.Owin; [assembly: OwinStartup(typeof(SignalRChat.Startup))] namespace SignalRChat { public class Startup { public void Configuration(IAppBuilder app) { // Any connection or hub wire up
  • SignalR协商404(SignalR Negotiate 404)
    问题 我正在使用SignalR 2.0。 在VS 2012上本地运行时,一切正常。但是,当我在IIS上发布站点时,它会中断。 该站点已加载,但其中一个脚本返回404 Not Found。 脚本是这样的。 https://example.com/signalr/negotiate?xxx 此路径确实不存在。 正确的路径应为: https://example.com / private / signalr / negotiate?xxx 注意该部分以粗体显示。 在网站(https://example.com/)内,我有另一个应用程序(https://example.com/private/)。 这是使用SignalR。 这似乎是SignalR中的错误,因为从我的私有站点可以访问signalr / hubs路径。 回答1 我有一个类似的问题。 这是用于配置/ signalr URL的文档。 但是,我的解决方案与文档不同。 我没有更改标准的app.MapSignalR() ,而是将客户端代码更改为使用/MyApp/signalr 。 这是代码,其中“ MyApp”是我的Web应用程序的虚拟目录。 var connection = $.hubConnection('/MyApp/signalr', {useDefaultPath: false}); var changesHub =
  • SignalR + Autofac + OWIN: Why doesn't GlobalHost.ConnectionManager.GetHubContext work?
    I'm trying to use OWIN, SignalR and Autofac in a single project. I'm setting things up with regards to signalR as follows: // Create the AutoFac container builder: var builder = new ContainerBuilder(); // ...[Register various other things in here]... // register signalR Hubs builder.RegisterHubs(Assembly.GetExecutingAssembly()); // Build the container: var container = builder.Build(); // Configure SignalR with the dependency resolver. app.MapSignalR(new HubConfiguration { Resolver = new AutofacDependencyResolver(container) }); My issue is that when I use the Autofac SignalR integration, I can
  • SignalR + Autofac + OWIN:为什么GlobalHost.ConnectionManager.GetHubContext不起作用?(SignalR + Autofac + OWIN: Why doesn't GlobalHost.ConnectionManager.GetHubContext work?)
    问题 我正在尝试在单个项目中使用OWIN,SignalR和Autofac。 我正在对signalR进行如下设置: // Create the AutoFac container builder: var builder = new ContainerBuilder(); // ...[Register various other things in here]... // register signalR Hubs builder.RegisterHubs(Assembly.GetExecutingAssembly()); // Build the container: var container = builder.Build(); // Configure SignalR with the dependency resolver. app.MapSignalR(new HubConfiguration { Resolver = new AutofacDependencyResolver(container) }); 我的问题是,当我使用Autofac SignalR集成时,无法再在服务器上(例如在webapi控制器中)获得signalR集线器上下文,因此无法从服务器端向连接的客户端发送消息。 不使用Autofac signalR集成时,如何执行以下操作: var