How to Register SignalR Middleware
To enable clients to connect to Hub, you need to call the MapSignalR method when the program starts.
The following code shows how to define SignalR Hubs routing in the OWIN startup class.
using Microsoft.Owin; using Owin; [assembly: OwinStartup(typeof(MyApplication.Startup))] namespace MyApplication { public class Startup { public void Configuration(IAppBuilder app) { // Any connection or hub wire up and configuration should go here app.MapSignalR(); } } }
The /signalr URL
By default, clients connect to your Hub through the'/ signalr'routing address. You can also modify the'/ signalr' without using the default'.
Server-side code specifies Url
app.MapSignalR("/signalrTest", new HubConfiguration());
JavaScript client code specifies Url
<script src="signalrTest/hubs"></script> var chat = $.connection.chatHub; chat.url = "/signalrTest";
NET client code specifies Url
var Connection = new HubConnection("http://localhost:8080/signalrTest");
How to create and use Hub classes
To create Hub classes, you need to create a class that inherits from Microsoft.Aspnet.Signalr.Hub.
public class ContosoChatHub : Hub { public void NewContosoChatMessage(string name, string message) { Clients.All.addNewMessageToPage(name, message); } }
Hub name on JavaScript side
Server (hump nomenclature, the first letter can be capitalized or lowercase)
public class ContosoChatHub : Hub
JavaScript (whether the first letter on the Server side is small or small, the JavaScript client must be small, or the corresponding Hub will not be found)
var contosoChatHubProxy = $.connection.contosoChatHub;
When the Hub name is named using the feature HubName, the case of the Hub name on the Server and Client sides must be consistent.
Server (If the first letter specified by HubName is capitalized, the JavaScript side must also be capitalized. If it's lowercase, then the JavaScript side must also be lowercase.
[HubName("PascalCaseContosoChatHub")] public class ContosoChatHub : Hub
JavaScript
var contosoChatHubProxy = $.connection.PascalCaseContosoChatHub;
Strong type Hub
Define an interface T so that your Hub class inherits from Hub < T> so that you can specify the methods that your client can call or open code prompts in your Hub method.
public class StrongHub : Hub<IClient> { public void Send(string message) { Clients.All.NewMessage(message); } } public interface IClient { void NewMessage(string message); }
How to define methods that client can call in Hub class
If you need to expose a method that can be invoked on the client side, you need to define a public method in Hub, as shown below.
public class ContosoChatHub : Hub { public void NewContosoChatMessage(string name, string message) { Clients.All.addNewMessageToPage(name, message); } }
public class StockTickerHub : Hub { public IEnumerable<Stock> GetAllStocks() { return _stockTicker.GetAllStocks(); } }
You can specify method parameters and return types, including complex types and arrays. These data are transmitted using Json on both client and server sides, and SignalR automatically binds complex type objects and array objects.
Method name in Hub (non-client method name)
Server (hump nomenclature, the first letter can be capitalized or lowercase)
public void NewContosoChatMessage(string userName, string message)
JavaScript (regardless of whether the first letter on the Server side is small or small, the JavaScript client must be small or no corresponding method can be found)
contosoChatHubProxy.server.newContosoChatMessage(userName, message);
Using the HubMethodName feature to specify method names, the case of the method names on the Server and Client sides must be consistent.
Server terminal
[HubMethodName("PascalCaseNewContosoChatMessage")] public void NewContosoChatMessage(string userName, string message)
JavaScript side
contosoChatHubProxy.server.PascalCaseNewContosoChatMessage(userName, message);
How to Call Client Method in Hub Class
You can use the Clients property in Hub class methods to invoke client-side methods
Server terminal
public class ContosoChatHub : Hub { public void NewContosoChatMessage(string name, string message) { Clients.All.addNewMessageToPage(name, message); } }
JavaScript side
contosoChatHubProxy.client.addNewMessageToPage = function (name, message) { // Add the message to the page. $('#discussion').append('<li><strong>' + htmlEncode(name) + '</strong>: ' + htmlEncode(message) + '<li>'); };
You can't get a return value from the client, such as int x = Clients.All.add(1,1) is useless.
You can specify complex types and array types for parameters, as shown below.
Sever terminal
public void SendMessage(string name, string message) { Clients.All.addContosoChatMessageToPage(new ContosoChatMessage() { UserName = name, Message = message }); } public class ContosoChatMessage { public string UserName { get; set; } public string Message { get; set; } }
JavaScript code
var contosoChatHubProxy = $.connection.contosoChatHub; contosoChatHubProxy.client.addMessageToPage = function (message) { console.log(message.UserName + ' ' + message.Message); });
Specify which clients receive information
All connected clients
Clients.All.addContosoChatMessageToPage(name, message);
Just Calling's client
Clients.Caller.addContosoChatMessageToPage(name, message);
All connected clients except Calling clients
Clients.Others.addContosoChatMessageToPage(name, message);
Specify a specific client by connection ID
Clients.Client(Context.ConnectionId).addContosoChatMessageToPage(name, message);
Exclude specific clients through connection ID
Clients.AllExcept(connectionId1, connectionId2).addContosoChatMessageToPage(name, message);
Specify a special group
Clients.Group(groupName).addContosoChatMessageToPage(name, message);
Specify a special group and exclude clients with a specific connection ID
Clients.Group(groupName, connectionId1, connectionId2).addContosoChatMessageToPage(name, message);
Specify a special group, but exclude call
Clients.OthersInGroup(groupName).addContosoChatMessageToPage(name, message);
Specify a particular user through userId, typically IPrincipal.Identity.Name
Clients.User(userid).addContosoChatMessageToPage(name, message);
All clients and groups in a list of connection IDs
Clients.Clients(ConnectionIds).broadcastMessage(name, message);
Specify multiple groups
Clients.Groups(GroupIds).broadcastMessage(name, message);
By username
Clients.Client(username).broadcastMessage(name, message);
A set of usernames
Clients.Users(new string[] { "myUser", "myUser2" }).broadcastMessage(name, message);
Case insensitive
Client method name calls are case insensitive, such as Clients.All.addContosoChatMessageToPage calls client's AddContosoChatMessageToPage, addcontosochatmessagetopage, or addContosoChatMessageToPage.
Asynchronous execution
public async Task NewContosoChatMessage(string name, string message) { await Clients.Others.addContosoChatMessageToPage(data); Clients.Caller.notifyMessageSent(); }
How to use a string variable as a method name
If you need to use a string as the method name, then you need to assign the Clients.All (or Clients.Others, Clients.Caller, etc.) object to IClientProxy and call its Invoke(methodName, args...) method.
public void NewContosoChatMessage(string name, string message) { string methodToCall = "addContosoChatMessageToPage"; IClientProxy proxy = Clients.All; proxy.Invoke(methodToCall, name, message); }
Management team membership
Server terminal
public class ContosoChatHub : Hub { public Task JoinGroup(string groupName) { return Groups.Add(Context.ConnectionId, groupName); } public Task LeaveGroup(string groupName) { return Groups.Remove(Context.ConnectionId, groupName); } }
Client
contosoChatHubProxy.server.joinGroup(groupName);
contosoChatHubProxy.server.leaveGroup(groupName);
Asynchronous execution
public async Task JoinGroup(string groupName) { await Groups.Add(Context.ConnectionId, groupName); Clients.Group(groupname).addContosoChatMessageToPage(Context.ConnectionId + " added to group"); }
How to capture and process connection lifecycle events in Hub classes
public class ContosoChatHub : Hub { public override Task OnConnected() { // Add your own code here. // For example: in a chat application, record the association between // the current connection ID and user name, and mark the user as online. // After the code in this method completes, the client is informed that // the connection is established; for example, in a JavaScript client, // the start().done callback is executed. return base.OnConnected(); } public override Task OnDisconnected() { // Add your own code here. // For example: in a chat application, mark the user as offline, // delete the association between the current connection id and user name. return base.OnDisconnected(); } public override Task OnReconnected() { // Add your own code here. // For example: in a chat application, you might have marked the // user as offline after a period of inactivity; in that case // mark the user as online again. return base.OnReconnected(); } }
How to get Clients information from Content
connection ID of Calling Client
string connectionID = Context.ConnectionId;
Connection ID is a GUID assigned by SignalR (you can't specify it in your own code). Each connection has a connection ID. If your application contains multiple Hubs, multiple Hubs will share the same connection ID.
Http Header data
System.Collections.Specialized.NameValueCollection headers = Context.Request.Headers;
System.Collections.Specialized.NameValueCollection headers = Context.Headers;
Query string data
System.Collections.Specialized.NameValueCollection queryString = Context.Request.QueryString; System.Collections.Specialized.NameValueCollection queryString = Context.QueryString; string parameterValue = queryString["parametername"];
JavaScript client QueryString
$.connection.hub.qs = { "version" : "1.0" };
This $. connection.hub.qs does not refer to your current Hub ($. connection.chatHub.qs).
Cookies
System.Collections.Generic.IDictionary<string, Cookie> cookies = Context.Request.Cookies;
System.Collections.Generic.IDictionary<string, Cookie> cookies = Context.RequestCookies;
User information
System.Security.Principal.IPrincipal user = Context.User;
Request's HttpContext object
System.Web.HttpContextBase httpContext = Context.Request.GetHttpContext();
How to Pass State Between Client and Server
JavaScript Client
contosoChatHubProxy.state.userName = "Fadi Fakhouri"; contosoChatHubProxy.state.computerName = "fadivm1";
Server side access, you can use Caller or CallerState two ways
string userName = Clients.Caller.userName; string computerName = Clients.Caller.computerName;
string userName = Clients.CallerState.userName; string computerName = Clients.CallerState.computerName;
How to catch exceptions in Hub class
- Use try - catch and log
- Create a Houbs pipeline model that can handle OnIncoming Error
-
public class ErrorHandlingPipelineModule : HubPipelineModule { protected override void OnIncomingError(ExceptionContext exceptionContext, IHubIncomingInvokerContext invokerContext) { Debug.WriteLine("=> Exception " + exceptionContext.Error.Message); if (exceptionContext.Error.InnerException != null) { Debug.WriteLine("=> Inner Exception " + exceptionContext.Error.InnerException.Message); } base.OnIncomingError(exceptionContext, invokerContext); } } public void Configuration(IAppBuilder app) { // Any connection or hub wire up and configuration should go here GlobalHost.HubPipeline.AddModule(new ErrorHandlingPipelineModule()); app.MapSignalR(); }
-
- Use the HubException class to throw exceptions
-
public class MyHub : Hub { public void Send(string message) { if(message.Contains("<script>")) { throw new HubException("This message will flow to the client", new { user = Context.User.Identity.Name, message = message }); } Clients.All.send(message); } }
-
Enabling Log Diagnosis
If you need to start the Server end log, you need to add a system.diagnostics node to the web.config
<system.diagnostics> <sources> <source name="SignalR.SqlMessageBus"> <listeners> <add name="SignalR-Bus" /> </listeners> </source> <source name="SignalR.ServiceBusMessageBus"> <listeners> <add name="SignalR-Bus" /> </listeners> </source> <source name="SignalR.ScaleoutMessageBus"> <listeners> <add name="SignalR-Bus" /> </listeners> </source> <source name="SignalR.Transports.WebSocketTransport"> <listeners> <add name="SignalR-Transports" /> </listeners> </source> <source name="SignalR.Transports.ServerSentEventsTransport"> <listeners> <add name="SignalR-Transports" /> </listeners> </source> <source name="SignalR.Transports.ForeverFrameTransport"> <listeners> <add name="SignalR-Transports" /> </listeners> </source> <source name="SignalR.Transports.LongPollingTransport"> <listeners> <add name="SignalR-Transports" /> </listeners> </source> <source name="SignalR.Transports.TransportHeartBeat"> <listeners> <add name="SignalR-Transports" /> </listeners> </source> </sources> <switches> <add name="SignalRSwitch" value="Verbose" /> </switches> <sharedListeners> <add name="SignalR-Transports" type="System.Diagnostics.TextWriterTraceListener" initializeData="transports.log.txt" /> <add name="SignalR-Bus" type="System.Diagnostics.TextWriterTraceListener" initializeData="bus.log.txt" /> </sharedListeners> <trace autoflush="true" /> </system.diagnostics>
How to call client method and management group outside Hub class
If you need to call client methods and management groups outside the Hub class, you need to get a SignalR context object, and then you can manipulate client methods and groups through context.Clients objects.
IHubContext _context = GlobalHost.ConnectionManager.GetHubContext<StockTickerHub>();
_context.Clients.All.updateStockPrice(stock);
How to Customize Pipeline Model
SignalR allows you to inject your code into the Hub pipeline model, which you can implement by inheriting the Hub Pipeline Module
public class LoggingPipelineModule : HubPipelineModule { protected override bool OnBeforeIncoming(IHubIncomingInvokerContext context) { Debug.WriteLine("=> Invoking " + context.MethodDescriptor.Name + " on hub " + context.MethodDescriptor.Hub.Name); return base.OnBeforeIncoming(context); } protected override bool OnBeforeOutgoing(IHubOutgoingInvokerContext context) { Debug.WriteLine("<= Invoking " + context.Invocation.Method + " on client hub " + context.Invocation.Hub); return base.OnBeforeOutgoing(context); } }
Then inject a custom Houb pipeline model into Startup.cs
public void Configuration(IAppBuilder app) { GlobalHost.HubPipeline.AddModule(new LoggingPipelineModule()); app.MapSignalR(); }
Reference link:
https://docs.microsoft.com/zh-cn/aspnet/signalr/overview/guide-to-the-api/hubs-api-guide-server