Don't mean to be too negative but I just don't get this example. The switch from C# to JavaScript just confuses things. How on earth do I initialize a hub in a .NET Core web app host? Do I dependency inject it? Where does the hub get initialized? (On startup as it needs to be a static instance....... I'm guessing??)
I presume the hub must be initialized, but where? If I do a var x = new ChatHub() then everything (Client property etc.) is null.
I looks like something is missing.
Also stick to one technology stack.
⚠Do not edit this section. It is required for docs.microsoft.com ➟ GitHub issue linking.
Hi @grahambunce,
The switch from C# to JavaScript is necessary because you want a working server and client for a getting started doc. The server is C# the client is JavaScript. The switch from C# to JavaScript starts with the header "Create the SignalR client code", is there some way to make this less confusing?
In the example it tells you to add routes.MapHub<ChatHub>("/chathub");
This is where your hub gets "injected", SignalR handles creating hubs, you should never new one up by yourself.
@BrennanConroy injected into where? into a controller class? I'm trying to invoke the message from the server to send it to the clients. The clients in your example are, I think. JavaScript... that's ok.... but the server side is .NET. I don't see where I can invoke the hub to send a message to the JavaScript client
If you want to send messages to the client from somewhere other than the hub you can use IHubContext<THub>
, there is a doc with more details about that https://docs.microsoft.com/en-us/aspnet/core/signalr/hubcontext?view=aspnetcore-2.1.
@rachelappel I think maybe we should change the TOC from HubContext
to something more discoverable.
@BrennanConroy
if you want to send messages to the client from somewhere other than the hub.
I don't even know what that means. Is that my fault for being stupid, or the fault of the guidance for not explaining it correctly in the first place? Is there a difference between using the hub or instead trying to wrap a hub in a class to encapsulate it's logic... which is programmer 101 frankly.
If there are different (and better, more realistic) ways of using SignalR then IMO the examples should either do it that way in the first place, or point in big letters to another more detailed post that explains how to use it in a real-world situation.
@BrennanConroy What text do you recommend to replace HubContext
in the ToC? I agree that this should be changed. It doesn't mean anything to a beginner.
@breannan/@scottaddie Yep, change it but I'm not sure to what either. Scott, I'm not sure it is geared toward a beginner per se.
@grahambunce The getting started article shows the most realistic way to use SignalR (that is, from the hub directly), but the one Brennan linked to shows a different popular alternate way of using it (in an MVC Controller) instead. Neither is better than the other. The getting started article isn't supposed to discuss HubContext, it's outside the scope of that doc.
I don't see where I can invoke the hub to send a message to the JavaScript client
In the Getting Started doc, it is here, under "Create the SignalR Hub":
using Microsoft.AspNetCore.SignalR;
using System.Threading.Tasks;
namespace SignalRChat.Hubs
{
public class ChatHub : Hub
{
public async Task SendMessage(string user, string message)
{
await Clients.All.SendAsync("ReceiveMessage", user,message);
}
}
}
@rachelapplel Maybe this is the source of all the confusion. The example shows how to create a hub.... but where does SendMessage get invoked to send messages to all the connected clients... surely this needs to be called somewhere? it's in JavaScript (I think) but I don't really know... The JavaScript content starts under a header of "Create the SignalR Client Code"... so I presume that's clients listening to content pushed out by the hub?
I'd expect that most real-world situations would have a full .NET stack server with separate JavaScript based clients... but this example mangles the two sides of the architecture into a single structure.
It's this, and then the additional "cross-technologies" that really isn't helping to make the example understandable to a beginner. Since this is a Tutorial article, it really should be as simple to understand as possible.... not in what the task is (as that is easy understand) but in it's implementation.
Yes, under "Create the SignalR client code" is the call:
connection.invoke("SendMessage", user, message).catch(err => console.error(err.toString()));
I don't know what you mean by "full .NET stack server", there is no such thing. This is perfectly fine to use JS files the way they are for project for something small like a beginner sample.
@rachelappel Hi, In the nicest possible way, I'm not going to go back and forth on this. If the team thinks the example is fine, then that's your call.
But just to close off my point of view, I came to this article with a requirement in mind and read through everything and left without a clue how to achieve what I needed to do. That may be my fault, it may be that the examples don't reflect real world problems, I don't know.
This article is meant to be a beginner sample; in that case I guess it's fine. I don't speak JavaScript so it just confused things. However, I don't think the sample really reflects the types of problems someone coming to SignalR is really trying to solve.
For a full .NET stack, what I mean is that the requirement is to develop a .NET Core application that invokes a method on a hub to publish to listening clients. I've actually used the old SignalR, Ably, PubNub etc and none of these solutions used JavaScript on the server to push content to clients. They all respond to some business event (submitting a form, service bus message etc.) and then send the appropriate state to listening clients. This is all .NET code running on the server. Client side JavaScript has no place in that process.
Therefore, IMO, this and the other topics in this guide do not reflect a real-world problem. For example, How server side code can get the hub to publish a message (which usually necessitates dependency injection or getting a reference to an existing hub), how a client can tell the hub what group it belongs to when it connects so that messages are not pushed to all clients etc.
These real-world problems are not referenced in enough detail, or clearly defined in the Table of contents, to really help a beginner to SignalR who knows what they want but have no idea how to achieve it.
@grahambunce This article was created based on overwhelming customer feedback and known usage scenarios, and that is using the hub with the JS client. That is how SignalR works. "For a full .NET stack, what I mean is that the requirement is to develop a .NET Core application that invokes a method on a hub to publish to listening clients." is literally what this doc does. It works exactly the same way as the old SignalR.
There is the already mentioned Hubcontext doc for calling hubs from a Controller. https://docs.microsoft.com/en-us/aspnet/core/signalr/hubcontext?view=aspnetcore-2.1
The "Real world" scenario that you are looking for is outside the scope that the team wanted for this beginner doc.
Closing as addressed. Feel free to re-open if you need more info.
@grahambunce I'm late to this conversation, but on reading through it I wonder if some of what you're looking for would be provided by a SignalR for ASP.NET Core version of this tutorial:
This tutorial demonstrates server-initiated messaging with SignalR for ASP.NET.
@tdykstra thanks for the update; I eventually worked out what to from different posts, blogs and guides scattered across the web.
My original view stands though and I’m not quite sure why I have the downvotes. For a guide into SignalR this beginners guide did not help. Rachel commented that the article was not targeted at the kind of things I wanted to do, which is fair enough, but I’d then contend that this page is probably where a search engine will drop you (which is where I got directed to) so clearly defined jump off points into something more substantial would have been helpful. I still think that an example that appears to contain the server and the client logic in the same webpage is confusing where someone (a beginner) trying to understand the difference between the two sides to signalR and how to separate them.
@grahambunce The ChatHub is not a singleton, it's transitive (created per request). I was a bit confused by this because intuition says it would need to be stateful with references to all connected clients. Apparently this state lives somewhere in the internals. My guess is that the reason for it being transitive is becuase the calling context and connection id is injected per request so that the ConnectId
, Caller
and Others
properties are correctly bound. To get a reference to the hub from within a controller so that you can send messages to clients, inject an IHubContext<ChatHub>
into your controller.
I had an additional requirement which is that I have a database connection that emits events from a background thread, I need to subscribe to the events, filter and send via SignalR. I solved this with a singleton service that takes a HubContext and my database connection object in the constructor.