"
ASP.NET (snapshot 2017) Microsoft documentation and samples

ASP.NET SignalR Hubs API Guide - Server (C#)

by Patrick Fletcher, Tom Dykstra

This document provides an introduction to programming the server side of the ASP.NET SignalR Hubs API for SignalR version 2, with code samples demonstrating common options.

The SignalR Hubs API enables you to make remote procedure calls (RPCs) from a server to connected clients and from clients to the server. In server code, you define methods that can be called by clients, and you call methods that run on the client. In client code, you define methods that can be called from the server, and you call methods that run on the server. SignalR takes care of all of the client-to-server plumbing for you.

SignalR also offers a lower-level API called Persistent Connections. For an introduction to SignalR, Hubs, and Persistent Connections, see Introduction to SignalR 2.

Software versions used in this topic

Topic versions

For information about earlier versions of SignalR, see SignalR Older Versions.

Questions and comments

Please leave feedback on how you liked this tutorial and what we could improve in the comments at the bottom of the page. If you have questions that are not directly related to the tutorial, you can post them to the ASP.NET SignalR forum or StackOverflow.com.

Overview

This document contains the following sections:

For documentation on how to program clients, see the following resources:

The server components for SignalR 2 are only available in .NET 4.5. Servers running .NET 4.0 must use SignalR v1.x.

How to register SignalR middleware

To define the route that clients will use to connect to your Hub, call the MapSignalR method when the application starts. MapSignalR is an extension method for the OwinExtensions class. The following example shows how to define the SignalR Hubs route using an OWIN startup class.

[!code-csharpMain]

   1:  using Microsoft.Owin;
   2:  using Owin;
   3:   
   4:  [assembly: OwinStartup(typeof(MyApplication.Startup))]
   5:  namespace MyApplication
   6:  {
   7:      public class Startup
   8:      {
   9:          public void Configuration(IAppBuilder app)
  10:          {
  11:              // Any connection or hub wire up and configuration should go here
  12:              app.MapSignalR();
  13:          }
  14:   
  15:      }
  16:  }

If you are adding SignalR functionality to an ASP.NET MVC application, make sure that the SignalR route is added before the other routes. For more information, see Tutorial: Getting Started with SignalR 2 and MVC 5.

The /signalr URL

By default, the route URL which clients will use to connect to your Hub is ???/signalr???. (Don???t confuse this URL with the ???/signalr/hubs??? URL, which is for the automatically generated JavaScript file. For more information about the generated proxy, see SignalR Hubs API Guide - JavaScript Client - The generated proxy and what it does for you.)

There might be extraordinary circumstances that make this base URL not usable for SignalR; for example, you have a folder in your project named signalr and you don???t want to change the name. In that case, you can change the base URL, as shown in the following examples (replace ???/signalr??? in the sample code with your desired URL).

Server code that specifies the URL

[!code-csharpMain]

   1:  app.MapSignalR("/signalr", new HubConfiguration());

JavaScript client code that specifies the URL (with the generated proxy)

[!code-javascriptMain]

   1:  $.connection.hub.url = "/signalr"
   2:  $.connection.hub.start().done(init);

JavaScript client code that specifies the URL (without the generated proxy)

[!code-javascriptMain]

   1:  var connection = $.hubConnection("/signalr", { useDefaultPath: false });

.NET client code that specifies the URL

[!code-csharpMain]

   1:  var hubConnection = new HubConnection("http://contoso.com/signalr", useDefaultUrl: false);

Configuring SignalR Options

Overloads of the MapSignalR method enable you to specify a custom URL, a custom dependency resolver, and the following options:

The following example shows how to specify the SignalR connection URL and these options in a call to the MapSignalR method. To specify a custom URL, replace ???/signalr??? in the example with the URL that you want to use.

[!code-csharpMain]

   1:  var hubConfiguration = new HubConfiguration();
   2:  hubConfiguration.EnableDetailedErrors = true;
   3:  hubConfiguration.EnableJavaScriptProxies = false;
   4:  app.MapSignalR("/signalr", hubConfiguration);

How to create and use Hub classes

To create a Hub, create a class that derives from Microsoft.Aspnet.Signalr.Hub. The following example shows a simple Hub class for a chat application.

[!code-csharpMain]

   1:  public class ContosoChatHub : Hub
   2:  {
   3:      public void NewContosoChatMessage(string name, string message)
   4:      {
   5:          Clients.All.addNewMessageToPage(name, message);
   6:      }
   7:  }

In this example, a connected client can call the NewContosoChatMessage method, and when it does, the data received is broadcasted to all connected clients.

Hub object lifetime

You don???t instantiate the Hub class or call its methods from your own code on the server; all that is done for you by the SignalR Hubs pipeline. SignalR creates a new instance of your Hub class each time it needs to handle a Hub operation such as when a client connects, disconnects, or makes a method call to the server.

Because instances of the Hub class are transient, you can???t use them to maintain state from one method call to the next. Each time the server receives a method call from a client, a new instance of your Hub class processes the message. To maintain state through multiple connections and method calls, use some other method such as a database, or a static variable on the Hub class, or a different class that does not derive from Hub. If you persist data in memory, using a method such as a static variable on the Hub class, the data will be lost when the app domain recycles.

If you want to send messages to clients from your own code that runs outside the Hub class, you can???t do it by instantiating a Hub class instance, but you can do it by getting a reference to the SignalR context object for your Hub class. For more information, see How to call client methods and manage groups from outside the Hub class later in this topic.

Camel-casing of Hub names in JavaScript clients

By default, JavaScript clients refer to Hubs by using a camel-cased version of the class name. SignalR automatically makes this change so that JavaScript code can conform to JavaScript conventions. The previous example would be referred to as contosoChatHub in JavaScript code.

Server

[!code-csharpMain]

   1:  public class ContosoChatHub : Hub

JavaScript client using generated proxy

[!code-javascriptMain]

   1:  var contosoChatHubProxy = $.connection.contosoChatHub;

If you want to specify a different name for clients to use, add the HubName attribute. When you use a HubName attribute, there is no name change to camel case on JavaScript clients.

Server

[!code-csharpMain]

   1:  [HubName("PascalCaseContosoChatHub")]
   2:  public class ContosoChatHub : Hub

JavaScript client using generated proxy

[!code-javascriptMain]

   1:  var contosoChatHubProxy = $.connection.PascalCaseContosoChatHub;

Multiple Hubs

You can define multiple Hub classes in an application. When you do that, the connection is shared but groups are separate:

### Strongly-Typed Hubs

To define an interface for your hub methods that your client can reference (and enable Intellisense on your hub methods), derive your hub from Hub<T> (introduced in SignalR 2.1) rather than Hub:

[!code-csharpMain]

   1:  public class StrongHub : Hub<IClient>
   2:  {
   3:      public void Send(string message)
   4:      {
   5:          Clients.All.NewMessage(message);
   6:      }
   7:  }
   8:   
   9:  public interface IClient
  10:  {
  11:      void NewMessage(string message);
  12:  }

How to define methods in the Hub class that clients can call

To expose a method on the Hub that you want to be callable from the client, declare a public method, as shown in the following examples.

[!code-csharpMain]

   1:  public class ContosoChatHub : Hub
   2:  {
   3:      public void NewContosoChatMessage(string name, string message)
   4:      {
   5:          Clients.All.addNewMessageToPage(name, message);
   6:      }
   7:  }

[!code-csharpMain]

   1:  public class StockTickerHub : Hub
   2:  {
   3:      public IEnumerable<Stock> GetAllStocks()
   4:      {
   5:          return _stockTicker.GetAllStocks();
   6:      }
   7:  }

You can specify a return type and parameters, including complex types and arrays, as you would in any C# method. Any data that you receive in parameters or return to the caller is communicated between the client and the server by using JSON, and SignalR handles the binding of complex objects and arrays of objects automatically.

Camel-casing of method names in JavaScript clients

By default, JavaScript clients refer to Hub methods by using a camel-cased version of the method name. SignalR automatically makes this change so that JavaScript code can conform to JavaScript conventions.

Server

[!code-csharpMain]

   1:  public void NewContosoChatMessage(string userName, string message)

JavaScript client using generated proxy

[!code-javascriptMain]

   1:  contosoChatHubProxy.server.newContosoChatMessage(userName, message);

If you want to specify a different name for clients to use, add the HubMethodName attribute.

Server

[!code-csharpMain]

   1:  [HubMethodName("PascalCaseNewContosoChatMessage")]
   2:  public void NewContosoChatMessage(string userName, string message)

JavaScript client using generated proxy

[!code-javascriptMain]

   1:  contosoChatHubProxy.server.PascalCaseNewContosoChatMessage(userName, message);

When to execute asynchronously

If the method will be long-running or has to do work that would involve waiting, such as a database lookup or a web service call, make the Hub method asynchronous by returning a Task (in place of void return) or Task<T> object (in place of T return type). When you return a Task object from the method, SignalR waits for the Task to complete, and then it sends the unwrapped result back to the client, so there is no difference in how you code the method call in the client.

Making a Hub method asynchronous avoids blocking the connection when it uses the WebSocket transport. When a Hub method executes synchronously and the transport is WebSocket, subsequent invocations of methods on the Hub from the same client are blocked until the Hub method completes.

The following example shows the same method coded to run synchronously or asynchronously, followed by JavaScript client code that works for calling either version.

Synchronous

[!code-csharpMain]

   1:  public IEnumerable<Stock> GetAllStocks()
   2:  {
   3:      // Returns data from memory.
   4:      return _stockTicker.GetAllStocks();
   5:  }

Asynchronous

[!code-csharpMain]

   1:  public async Task<IEnumerable<Stock>> GetAllStocks()
   2:  {
   3:      // Returns data from a web service.
   4:      var uri = Util.getServiceUri("Stocks");
   5:      using (HttpClient httpClient = new HttpClient())
   6:      {
   7:          var response = await httpClient.GetAsync(uri);
   8:          return (await response.Content.ReadAsAsync<IEnumerable<Stock>>());
   9:      }
  10:  }

JavaScript client using generated proxy

[!code-javascriptMain]

   1:  stockTickerHubProxy.server.getAllStocks().done(function (stocks) {
   2:      $.each(stocks, function () {
   3:          alert(this.Symbol + ' ' + this.Price);
   4:      });
   5:  });

For more information about how to use asynchronous methods in ASP.NET 4.5, see Using Asynchronous Methods in ASP.NET MVC 4.

Defining Overloads

If you want to define overloads for a method, the number of parameters in each overload must be different. If you differentiate an overload just by specifying different parameter types, your Hub class will compile but the SignalR service will throw an exception at run time when clients try to call one of the overloads.

### Reporting progress from hub method invocations

SignalR 2.1 adds support for the progress reporting pattern introduced in .NET 4.5. To implement progress reporting, define an IProgress<T> parameter for your hub method that your client can access:

[!code-csharpMain]

   1:  public class ProgressHub : Hub
   2:  {
   3:      public async Task<string> DoLongRunningThing(IProgress<int> progress)
   4:      {
   5:          for (int i = 0; i <= 100; i+=5)
   6:          {
   7:              await Task.Delay(200);
   8:              progress.Report(i);
   9:          }
  10:          return "Job complete!";
  11:      }
  12:  }

When writing a long-running server method, it is important to use an asynchronous programming pattern like Async/ Await rather than blocking the hub thread.

How to call client methods from the Hub class

To call client methods from the server, use the Clients property in a method in your Hub class. The following example shows server code that calls addNewMessageToPage on all connected clients, and client code that defines the method in a JavaScript client.

Server

[!code-csharpMain]

   1:  public class ContosoChatHub : Hub
   2:  {
   3:      public void NewContosoChatMessage(string name, string message)
   4:      {
   5:          Clients.All.addNewMessageToPage(name, message);
   6:      }
   7:  }

JavaScript client using generated proxy

[!code-htmlMain]

   1:  contosoChatHubProxy.client.addNewMessageToPage = function (name, message) {
   2:      // Add the message to the page. 
   3:      $('#discussion').append('<li><strong>' + htmlEncode(name)
   4:          + '</strong>: ' + htmlEncode(message) + '<li>');
   5:  };

You can???t get a return value from a client method; syntax such as int x = Clients.All.add(1,1) does not work.

You can specify complex types and arrays for the parameters. The following example passes a complex type to the client in a method parameter.

Server code that calls a client method using a complex object

[!code-csharpMain]

   1:  public void SendMessage(string name, string message)
   2:  {
   3:      Clients.All.addContosoChatMessageToPage(new ContosoChatMessage() { UserName = name, Message = message });
   4:  }

Server code that defines the complex object

[!code-csharpMain]

   1:  public class ContosoChatMessage
   2:  {
   3:      public string UserName { get; set; }
   4:      public string Message { get; set; }
   5:  }

JavaScript client using generated proxy

[!code-javascriptMain]

   1:  var contosoChatHubProxy = $.connection.contosoChatHub;
   2:  contosoChatHubProxy.client.addMessageToPage = function (message) {
   3:      console.log(message.UserName + ' ' + message.Message);
   4:  });

Selecting which clients will receive the RPC

The Clients property returns a HubConnectionContext object that provides several options for specifying which clients will receive the RPC:

No compile-time validation for method names

The method name that you specify is interpreted as a dynamic object, which means there is no IntelliSense or compile-time validation for it. The expression is evaluated at run time. When the method call executes, SignalR sends the method name and the parameter values to the client, and if the client has a method that matches the name, that method is called and the parameter values are passed to it. If no matching method is found on the client, no error is raised. For information about the format of the data that SignalR transmits to the client behind the scenes when you call a client method, see Introduction to SignalR.

Case-insensitive method name matching

Method name matching is case-insensitive. For example, Clients.All.addContosoChatMessageToPage on the server will execute AddContosoChatMessageToPage, addcontosochatmessagetopage, or addContosoChatMessageToPage on the client.

Asynchronous execution

The method that you call executes asynchronously. Any code that comes after a method call to a client will execute immediately without waiting for SignalR to finish transmitting data to clients unless you specify that the subsequent lines of code should wait for method completion. The following code example shows how to execute two client methods sequentially.

Using Await (.NET 4.5)

[!code-csharpMain]

   1:  public async Task NewContosoChatMessage(string name, string message)
   2:  {
   3:      await Clients.Others.addContosoChatMessageToPage(data);
   4:      Clients.Caller.notifyMessageSent();
   5:  }

If you use await to wait until a client method finishes before the next line of code executes, that does not mean that clients will actually receive the message before the next line of code executes. ???Completion??? of a client method call only means that SignalR has done everything necessary to send the message. If you need verification that clients received the message, you have to program that mechanism yourself. For example, you could code a MessageReceived method on the Hub, and in the addContosoChatMessageToPage method on the client you could call MessageReceived after you do whatever work you need to do on the client. In MessageReceived in the Hub you can do whatever work depends on actual client reception and processing of the original method call.

How to use a string variable as the method name

If you want to invoke a client method by using a string variable as the method name, cast Clients.All (or Clients.Others, Clients.Caller, etc.) to IClientProxy and then call Invoke(methodName, args???).

[!code-csharpMain]

   1:  public void NewContosoChatMessage(string name, string message)
   2:  {
   3:      string methodToCall = "addContosoChatMessageToPage";
   4:      IClientProxy proxy = Clients.All;
   5:      proxy.Invoke(methodToCall, name, message);
   6:  }

How to manage group membership from the Hub class

Groups in SignalR provide a method for broadcasting messages to specified subsets of connected clients. A group can have any number of clients, and a client can be a member of any number of groups.

To manage group membership, use the Add and Remove methods provided by the Groups property of the Hub class. The following example shows the Groups.Add and Groups.Remove methods used in Hub methods that are called by client code, followed by JavaScript client code that calls them.

Server

[!code-csharpMain]

   1:  public class ContosoChatHub : Hub
   2:  {
   3:      public Task JoinGroup(string groupName)
   4:      {
   5:          return Groups.Add(Context.ConnectionId, groupName);
   6:      }
   7:   
   8:      public Task LeaveGroup(string groupName)
   9:      {
  10:          return Groups.Remove(Context.ConnectionId, groupName);
  11:      }
  12:  }

JavaScript client using generated proxy

[!code-javascriptMain]

   1:  contosoChatHubProxy.server.joinGroup(groupName);

[!code-javascriptMain]

   1:  contosoChatHubProxy.server.leaveGroup(groupName);

You don???t have to explicitly create groups. In effect a group is automatically created the first time you specify its name in a call to Groups.Add, and it is deleted when you remove the last connection from membership in it.

There is no API for getting a group membership list or a list of groups. SignalR sends messages to clients and groups based on a pub/sub model, and the server does not maintain lists of groups or group memberships. This helps maximize scalability, because whenever you add a node to a web farm, any state that SignalR maintains has to be propagated to the new node.

Asynchronous execution of Add and Remove methods

The Groups.Add and Groups.Remove methods execute asynchronously. If you want to add a client to a group and immediately send a message to the client by using the group, you have to make sure that the Groups.Add method finishes first. The following code example shows how to do that.

Adding a client to a group and then messaging that client

[!code-csharpMain]

   1:  public async Task JoinGroup(string groupName)
   2:  {
   3:      await Groups.Add(Context.ConnectionId, groupName);
   4:      Clients.Group(groupname).addContosoChatMessageToPage(Context.ConnectionId + " added to group");
   5:  }

Group membership persistence

SignalR tracks connections, not users, so if you want a user to be in the same group every time the user establishes a connection, you have to call Groups.Add every time the user establishes a new connection.

After a temporary loss of connectivity, sometimes SignalR can restore the connection automatically. In that case, SignalR is restoring the same connection, not establishing a new connection, and so the client???s group membership is automatically restored. This is possible even when the temporary break is the result of a server reboot or failure, because connection state for each client, including group memberships, is round-tripped to the client. If a server goes down and is replaced by a new server before the connection times out, a client can reconnect automatically to the new server and re-enroll in groups it is a member of.

When a connection can???t be restored automatically after a loss of connectivity, or when the connection times out, or when the client disconnects (for example, when a browser navigates to a new page), group memberships are lost. The next time the user connects will be a new connection. To maintain group memberships when the same user establishes a new connection, your application has to track the associations between users and groups, and restore group memberships each time a user establishes a new connection.

For more information about connections and reconnections, see How to handle connection lifetime events in the Hub class later in this topic.

Single-user groups

Applications that use SignalR typically have to keep track of the associations between users and connections in order to know which user has sent a message and which user(s) should be receiving a message. Groups are used in one of the two commonly used patterns for doing that.

How to handle connection lifetime events in the Hub class

Typical reasons for handling connection lifetime events are to keep track of whether a user is connected or not, and to keep track of the association between user names and connection IDs. To run your own code when clients connect or disconnect, override the OnConnected, OnDisconnected, and OnReconnected virtual methods of the Hub class, as shown in the following example.

[!code-csharpMain]

   1:  public class ContosoChatHub : Hub
   2:  {
   3:      public override Task OnConnected()
   4:      {
   5:          // Add your own code here.
   6:          // For example: in a chat application, record the association between
   7:          // the current connection ID and user name, and mark the user as online.
   8:          // After the code in this method completes, the client is informed that
   9:          // the connection is established; for example, in a JavaScript client,
  10:          // the start().done callback is executed.
  11:          return base.OnConnected();
  12:      }
  13:   
  14:      public override Task OnDisconnected()
  15:      {
  16:          // Add your own code here.
  17:          // For example: in a chat application, mark the user as offline, 
  18:          // delete the association between the current connection id and user name.
  19:          return base.OnDisconnected();
  20:      }
  21:   
  22:      public override Task OnReconnected()
  23:      {
  24:          // Add your own code here.
  25:          // For example: in a chat application, you might have marked the
  26:          // user as offline after a period of inactivity; in that case 
  27:          // mark the user as online again.
  28:          return base.OnReconnected();
  29:      }
  30:  }

When OnConnected, OnDisconnected, and OnReconnected are called

Each time a browser navigates to a new page, a new connection has to be established, which means SignalR will execute the OnDisconnected method followed by the OnConnected method. SignalR always creates a new connection ID when a new connection is established.

The OnReconnected method is called when there has been a temporary break in connectivity that SignalR can automatically recover from, such as when a cable is temporarily disconnected and reconnected before the connection times out. The OnDisconnected method is called when the client is disconnected and SignalR can???t automatically reconnect, such as when a browser navigates to a new page. Therefore, a possible sequence of events for a given client is OnConnected, OnReconnected, OnDisconnected; or OnConnected, OnDisconnected. You won???t see the sequence OnConnected, OnDisconnected, OnReconnected for a given connection.

The OnDisconnected method doesn???t get called in some scenarios, such as when a server goes down or the App Domain gets recycled. When another server comes on line or the App Domain completes its recycle, some clients may be able to reconnect and fire the OnReconnected event.

For more information, see Understanding and Handling Connection Lifetime Events in SignalR.

Caller state not populated

The connection lifetime event handler methods are called from the server, which means that any state that you put in the state object on the client will not be populated in the Caller property on the server. For information about the state object and the Caller property, see How to pass state between clients and the Hub class later in this topic.

How to get information about the client from the Context property

To get information about the client, use the Context property of the Hub class. The Context property returns a HubCallerContext object which provides access to the following information:

How to pass state between clients and the Hub class

The client proxy provides a state object in which you can store data that you want to be transmitted to the server with each method call. On the server you can access this data in the Clients.Caller property in Hub methods that are called by clients. The Clients.Caller property is not populated for the connection lifetime event handler methods OnConnected, OnDisconnected, and OnReconnected.

Creating or updating data in the state object and the Clients.Caller property works in both directions. You can update values in the server and they are passed back to the client.

The following example shows JavaScript client code that stores state for transmission to the server with every method call.

[!code-javascriptMain]

   1:  contosoChatHubProxy.state.userName = "Fadi Fakhouri";
   2:  contosoChatHubProxy.state.computerName = "fadivm1";

The following example shows the equivalent code in a .NET client.

[!code-csharpMain]

   1:  contosoChatHubProxy["userName"] = "Fadi Fakhouri";
   2:  chatHubProxy["computerName"] = "fadivm1";

In your Hub class, you can access this data in the Clients.Caller property. The following example shows code that retrieves the state referred to in the previous example.

[!code-csharpMain]

   1:  public void NewContosoChatMessage(string data)
   2:  {
   3:      string userName = Clients.Caller.userName;
   4:      string computerName = Clients.Caller.computerName;
   5:      Clients.Others.addContosoChatMessageToPage(message, userName, computerName);
   6:  }

[!NOTE] This mechanism for persisting state is not intended for large amounts of data, since everything you put in the state or Clients.Caller property is round-tripped with every method invocation. It???s useful for smaller items such as user names or counters.

In VB.NET or in a strongly-typed hub, the caller state object can???t be accessed through Clients.Caller; instead, use Clients.CallerState (introduced in SignalR 2.1):

Using CallerState in C#

[!code-csharpMain]

   1:  public void NewContosoChatMessage(string data)
   2:  {
   3:      string userName = Clients.CallerState.userName;
   4:      string computerName = Clients.CallerState.computerName;
   5:      Clients.Others.addContosoChatMessageToPage(data, userName, computerName);
   6:  }

Using CallerState in Visual Basic

[!code-vbMain]

   1:  Public Sub NewContosoChatMessage(message As String)
   2:      Dim userName As String = Clients.CallerState.userName
   3:      Dim computerName As String = Clients.CallerState.computerName
   4:      Clients.Others.addContosoChatMessageToPage(message, userName, computerName)
   5:  End Sub

How to handle errors in the Hub class

To handle errors that occur in your Hub class methods, use one or more of the following methods:

For more information about Hub pipeline modules, see How to customize the Hubs pipeline later in this topic.

How to enable tracing

To enable server-side tracing, add a system.diagnostics element to your Web.config file, as shown in this example:

[!code-htmlMain]

   1:  <configuration>
   2:    <configSections>
   3:      <!-- For more information on Entity Framework configuration, visit http://go.microsoft.com/fwlink/?LinkID=237468 -->
   4:      <section name="entityFramework" type="System.Data.Entity.Internal.ConfigFile.EntityFrameworkSection, EntityFramework, Version=5.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false" />
   5:    </configSections>
   6:    <connectionStrings>
   7:      <add name="SignalRSamples" connectionString="Data Source=(local);Initial Catalog=SignalRSamples;Integrated Security=SSPI;Asynchronous Processing=True;" />
   8:      <add name="SignalRSamplesWithMARS" connectionString="Data Source=(local);Initial Catalog=SignalRSamples;Integrated Security=SSPI;Asynchronous Processing=True;MultipleActiveResultSets=true;" />
   9:    </connectionStrings>
  10:    <system.web>
  11:      <compilation debug="true" targetFramework="4.5" />
  12:      <httpRuntime targetFramework="4.5" />
  13:    </system.web>
  14:    <system.webServer>
  15:      <modules runAllManagedModulesForAllRequests="true" />
  16:    </system.webServer>
  17:    <system.diagnostics>
  18:      <sources>
  19:        <source name="SignalR.SqlMessageBus">
  20:          <listeners>
  21:            <add name="SignalR-Bus" />
  22:          </listeners>
  23:        </source>
  24:       <source name="SignalR.ServiceBusMessageBus">
  25:          <listeners>
  26:              <add name="SignalR-Bus" />
  27:          </listeners>
  28:       </source>
  29:       <source name="SignalR.ScaleoutMessageBus">
  30:          <listeners>
  31:              <add name="SignalR-Bus" />
  32:          </listeners>
  33:        </source>
  34:        <source name="SignalR.Transports.WebSocketTransport">
  35:          <listeners>
  36:            <add name="SignalR-Transports" />
  37:          </listeners>
  38:        </source>
  39:        <source name="SignalR.Transports.ServerSentEventsTransport">
  40:            <listeners>
  41:                <add name="SignalR-Transports" />
  42:            </listeners>
  43:        </source>
  44:        <source name="SignalR.Transports.ForeverFrameTransport">
  45:            <listeners>
  46:                <add name="SignalR-Transports" />
  47:            </listeners>
  48:        </source>
  49:        <source name="SignalR.Transports.LongPollingTransport">
  50:          <listeners>
  51:              <add name="SignalR-Transports" />
  52:          </listeners>
  53:        </source>
  54:        <source name="SignalR.Transports.TransportHeartBeat">
  55:          <listeners>
  56:              <add name="SignalR-Transports" />
  57:          </listeners>
  58:        </source>
  59:      </sources>
  60:      <switches>
  61:        <add name="SignalRSwitch" value="Verbose" />
  62:      </switches>
  63:      <sharedListeners>
  64:        <add name="SignalR-Transports" 
  65:             type="System.Diagnostics.TextWriterTraceListener" 
  66:             initializeData="transports.log.txt" />
  67:          <add name="SignalR-Bus"
  68:             type="System.Diagnostics.TextWriterTraceListener"
  69:             initializeData="bus.log.txt" />
  70:      </sharedListeners>
  71:      <trace autoflush="true" />
  72:    </system.diagnostics>
  73:    <entityFramework>
  74:      <defaultConnectionFactory type="System.Data.Entity.Infrastructure.LocalDbConnectionFactory, EntityFramework">
  75:        <parameters>
  76:          <parameter value="v11.0" />
  77:        </parameters>
  78:      </defaultConnectionFactory>
  79:    </entityFramework>
  80:  </configuration>

When you run the application in Visual Studio, you can view the logs in the Output window.

How to call client methods and manage groups from outside the Hub class

To call client methods from a different class than your Hub class, get a reference to the SignalR context object for the Hub and use that to call methods on the client or manage groups.

The following sample StockTicker class gets the context object, stores it in an instance of the class, stores the class instance in a static property, and uses the context from the singleton class instance to call the updateStockPrice method on clients that are connected to a Hub named StockTickerHub.

[!code-csharpMain]

   1:  // For the complete example, go to 
   2:  // http://www.asp.net/signalr/overview/getting-started/tutorial-server-broadcast-with-aspnet-signalr
   3:  // This sample only shows code related to getting and using the SignalR context.
   4:  public class StockTicker
   5:  {
   6:      // Singleton instance
   7:      private readonly static Lazy<StockTicker> _instance = new Lazy<StockTicker>(
   8:          () => new StockTicker(GlobalHost.ConnectionManager.GetHubContext<StockTickerHub>()));
   9:   
  10:      private IHubContext _context;
  11:   
  12:      private StockTicker(IHubContext context)
  13:      {
  14:          _context = context;
  15:      }
  16:   
  17:      // This method is invoked by a Timer object.
  18:      private void UpdateStockPrices(object state)
  19:      {
  20:          foreach (var stock in _stocks.Values)
  21:          {
  22:              if (TryUpdateStockPrice(stock))
  23:              {
  24:                  _context.Clients.All.updateStockPrice(stock);
  25:              }
  26:          }
  27:      }

If you need to use the context multiple-times in a long-lived object, get the reference once and save it rather than getting it again each time. Getting the context once ensures that SignalR sends messages to clients in the same sequence in which your Hub methods make client method invocations. For a tutorial that shows how to use the SignalR context for a Hub, see Server Broadcast with ASP.NET SignalR.

Calling client methods

You can specify which clients will receive the RPC, but you have fewer options than when you call from a Hub class. The reason for this is that the context is not associated with a particular call from a client, so any methods that require knowledge of the current connection ID, such as Clients.Others, or Clients.Caller, or Clients.OthersInGroup, are not available. The following options are available:

If you are calling into your non-Hub class from methods in your Hub class, you can pass in the current connection ID and use that with Clients.Client, Clients.AllExcept, or Clients.Group to simulate Clients.Caller, Clients.Others, or Clients.OthersInGroup. In the following example, the MoveShapeHub class passes the connection ID to the Broadcaster class so that the Broadcaster class can simulate Clients.Others.

[!code-csharpMain]

   1:  // For the complete example, see
   2:  // http://www.asp.net/signalr/overview/signalr-20/getting-started-with-signalr-20/tutorial-server-broadcast-with-signalr-20
   3:  // This sample only shows code that passes connection ID to the non-Hub class,
   4:  // in order to simulate Clients.Others.
   5:  public class MoveShapeHub : Hub
   6:  {
   7:      // Code not shown puts a singleton instance of Broadcaster in this variable.
   8:      private Broadcaster _broadcaster;
   9:   
  10:      public void UpdateModel(ShapeModel clientModel)
  11:      {
  12:          clientModel.LastUpdatedBy = Context.ConnectionId;
  13:          // Update the shape model within our broadcaster
  14:          _broadcaster.UpdateShape(clientModel);
  15:      }
  16:  }
  17:   
  18:  public class Broadcaster
  19:  {
  20:      public Broadcaster()
  21:      {
  22:          _hubContext = GlobalHost.ConnectionManager.GetHubContext<MoveShapeHub>();
  23:      }
  24:   
  25:      public void UpdateShape(ShapeModel clientModel)
  26:      {
  27:          _model = clientModel;
  28:          _modelUpdated = true;
  29:      }
  30:   
  31:      // Called by a Timer object.
  32:      public void BroadcastShape(object state)
  33:      {
  34:          if (_modelUpdated)
  35:          {
  36:              _hubContext.Clients.AllExcept(_model.LastUpdatedBy).updateShape(_model);
  37:              _modelUpdated = false;
  38:          }
  39:      }
  40:  }

Managing group membership

For managing groups you have the same options as you do in a Hub class.

How to customize the Hubs pipeline

SignalR enables you to inject your own code into the Hub pipeline. The following example shows a custom Hub pipeline module that logs each incoming method call received from the client and outgoing method call invoked on the client:

[!code-csharpMain]

   1:  public class LoggingPipelineModule : HubPipelineModule 
   2:  { 
   3:      protected override bool OnBeforeIncoming(IHubIncomingInvokerContext context) 
   4:      { 
   5:          Debug.WriteLine("=> Invoking " + context.MethodDescriptor.Name + " on hub " + context.MethodDescriptor.Hub.Name); 
   6:          return base.OnBeforeIncoming(context); 
   7:      }   
   8:      protected override bool OnBeforeOutgoing(IHubOutgoingInvokerContext context) 
   9:      { 
  10:          Debug.WriteLine("<= Invoking " + context.Invocation.Method + " on client hub " + context.Invocation.Hub); 
  11:          return base.OnBeforeOutgoing(context); 
  12:      } 
  13:  }

The following code in the Startup.cs file registers the module to run in the Hub pipeline:

[!code-csharpMain]

   1:  public void Configuration(IAppBuilder app) 
   2:  { 
   3:      GlobalHost.HubPipeline.AddModule(new LoggingPipelineModule()); 
   4:      app.MapSignalR();
   5:  }

There are many different methods that you can override. For a complete list, see HubPipelineModule Methods.



Comments ( )
Link to this page: //www.vb-net.com/AspNet-DocAndSamples-2017/aspnet/signalr/overview/guide-to-the-api/hubs-api-guide-server.htm
< THANKS ME>