chris
chris

Reputation: 131

SignalR C# (both client and Hub)-strongly typed example

SignalR C# - Checking if someone could forward me to a SIMPLE example of C# SignalR that uses Strongly Typed calls to client methods via Hub (not passing a string) and also does NOT have javascript involved but the client side is in C# and lastly has an API controller endpoint exposed for an external call to the Hub side.

Upvotes: 11

Views: 8674

Answers (1)

Asif
Asif

Reputation: 334

In .NET Core Web App you can inject strongly typed signalR hub context like this

public interface IClient
{
    Task ReceiveMessage(string message);
}

public class DevicesHub : Hub<IClient>
{
}

public class HomeController : ControllerBase
{
    private readonly IHubContext<DevicesHub, IClient> _devicesHub;

    public HomeController(IHubContext<DevicesHub, IClient> devicesHub)
    {
        _devicesHub = devicesHub;
    }       

    [HttpGet]
    public IEnumerable<string> Get()
    {
       _devicesHub.Clients
          .All
          .ReceiveMessage("Message from devices.");

       return new string[] { "value1", "value2" };
    }
}

if you want a tutorial you can use this link https://darchuk.net/2019/07/19/signalr-strongly-typed-hubs/

communication between client and server. The general process that is followed won't allow to have strongly typed calls on the server and also in client code. We will look into how to make strongly typed calls on the server through interface and client end through TypeScript.

SignalR - making strong type on server side code Since client-side methods are very dynamic in nature, so calling those from server side behaves similarly to allow any calls.

SignalR Hubs are derived from Microsoft.AspNet.SignalR.Hub class, there is also a generic version available to follow typed items. Ex:

The interface is the replication of possible calls that would be received on the client end and calling of client-side methods on server code.

/// <summary>  
 /// Client(JS) side chatting interface callbacks.  
 /// </summary>  
 public interface IChatHub  
 {  
      /// <summary>  
      /// Gets the online users.  
      /// </summary>  
      /// <param name="chattingUsers">The chatting users.</param>  
      void GetOnlineUsers(IEnumerable<ChatAvailableUserOrGroup> chattingUsers);  

      /// <summary>  
      /// Determines whether the user is typing.  
      /// </summary>  
      /// <param name="userFullName">Full name of the user.</param>  
      void IsTyping(string userFullName);  

      /// <summary>  
      /// Member initialization through login.  
      /// </summary>  
      /// <param name="isSuccess">if set to <c>true</c> success login.</param>  
      void Login(bool isSuccess);  
 }  

The above interface can be implemented on generic hub inheritance.

 /// <summary>  
   /// SignalR Hub for chat application.  
   /// </summary>  
   public class ChatHub  
   : Hub<IChatHub>  
   {  
   }  

After implementation of an interface on Hub, the IntelliSense would come automatically.

Clients.Caller.IsTyping("viku"); 

That is all on server-side code implementation.

Strong type implementation on the client-side.

The calls of server and client-side callbacks need to be wrapped under the interface. The calls are wrapped with server and client properties. Let's have a look at the interface.

interface SignalRExtended extends SignalR {  
         chatHub: ChatHub;  
       }  

       interface ChatHub  
         extends HubConnection {  
         client: {  // callbacks on client side through server
           GetOnlineUsers(json: string);  
           ReceiveMessage(message: Model.ChatReceiveMessage);  
           IsTyping(connectionId: string, message: string);  
           Login(): boolean;  
           UserChatHistory(chattingHistory);  
         };  
         server: {  // Calling of server side hubs
           login(): () => void;  
           sendPrivateMessage(toUserId: string, message: string);  
           chatHistory(toUserId: number);  
           groupChatHistory(toGroupId: number);  
           sendGroupMessage(toGroupId: number, message: string);  
           userTyping(targettedUserOrGroup: number, requestType: string);  
           markAsRead(messageIds: Array<number>, targetedUserOrGroup: number, requestType: ChatSourceType);  
         }  
   }  

The TypeScript gets a property can be created and parsed based on the above interface.

 get ChatHub(): ChatHub {  
           return <ChatHub>(<any>$.connection).chatHub;  
         }  

Now, through the above property, we can access all methods of server and client calls with IntelliSense on TS.

The shown example is Skelton of the implementation but it can give an idea of how to make SignalR strongly typed.

Upvotes: 12

Related Questions