left-icon

Real-Time ASP.NET Core 3 Apps with SignalR Succinctly®
by Dirk Strauss

Previous
Chapter

of
A
A
A

CHAPTER 5

Creating the Hub and Configuring SignalR

Creating the Hub and Configuring SignalR


The hub is what will handle client-server communication. Start by adding a folder called Hubs to your realtimechat project. Inside this folder, create a class called ChatHub. Inside this class, add the following code.

Code Listing 5

using Microsoft.AspNetCore.SignalR;

using System.Threading.Tasks;

namespace realtimechat.Hubs

{

    public class ChatHub : Hub

    {

        public async Task MessageSender(string user, string message)

        {

            await Clients.All.SendAsync("MessageReceiver", user, message);

        }

    }

}

Let’s pause here for a minute. Inside the MessageSender method, you will notice that we are using an object that invokes a method on all the clients connected to this hub. It does this via the All property.

Additional Clients Methods

Figure 22: Additional Clients Methods

The Clients object implements the IHubCallerClients interface. This interface has the following properties:

  • All—Invokes methods on all clients connected to the hub.
  • Caller—Gets a caller to the connection that triggered the current invocation.
  • Others—Gets a caller to all connections except the one that triggered the current invocation.

It also includes methods such as:

  • AllExcept—Invokes methods on all clients connected to the hub, but excludes the specified connections passed as a read-only list of strings.
  • Client—Invokes methods on a specific client connection.
  • Clients—Invokes methods on the specified read-only list of client connections.
  • Group—Invokes methods on all connections in the specified group.
  • GroupExcept—Invokes methods on all connections in the specified group, but excludes the specified connections passed as a read-only list of strings.
  • Groups—Invokes methods on all connections in the specified read-only list of groups.
  • OthersInGroup—Gets a caller to all connections in the specified group, except the one which triggered the current invocation.
  • User—Invokes methods on all connections associated with the specified user.
  • Users—Invokes methods on all connections associated with the users specified in the read-only list of strings.

You will also notice that the ChatHub class inherits from the SignalR Hub class. This Hub base class is responsible for managing connections, groups, and messaging.

Tip: To view the Hub metadata, place your cursor on the Hub class name and press F12.

Having a look at the metadata for the Hub class, we can see the following properties:

  • Clients—Gets or sets an object that is used to invoke methods on the clients that are connected to this hub. You can see this in Code Listing 1.
  • Context—Allows you to get or set the hub caller context. (I discuss this in more detail in the section on Hubs.)
  • Groups—Allows you to get or set the group manager.

The Hub class also has the following properties:

  • OnConnectedAsync—This is called when a new connection is established with the hub and returns a task representing the asynchronous connect.
  • OnDisconnectedAsync—This is called when the connection to the hub is terminated and returns a task representing the asynchronous disconnect.
  • Dispose—The Hub class implements IDisposable and, therefore, will be able to dispose of all the resources currently in use by this hub instance.

Referring back to the code in Code Listing 5, the MessageSender method is therefore called by a connected client and will send a message to all the clients.

Configuring SignalR

Let’s focus our attention on the Startup class of the project. Start by adding the using realtimechat.Hubs statement to the Startup class.

The next line of code we need to add is to the ConfigureServices method, as shown in Code Listing 6.

Code Listing 6

public void ConfigureServices(IServiceCollection services)

{

    services.AddRazorPages();

    services.AddSignalR();

}

In the Configure method, add the following endpoint: endpoints.MapHub<ChatHub>("/chatHub"). Your code should look like Code Listing 7.

Code Listing 7

app.UseEndpoints(endpoints =>

{

     endpoints.MapRazorPages();

     endpoints.MapHub<ChatHub>("/chatHub");

});

If you have added everything correctly, your Startup class will look as in Code Listing 8.

Code Listing 8

using Microsoft.AspNetCore.Builder;

using Microsoft.AspNetCore.Hosting;

using Microsoft.Extensions.Configuration;

using Microsoft.Extensions.DependencyInjection;

using Microsoft.Extensions.Hosting;

using realtimechat.Hubs;

namespace realtimechat

{

    public class Startup

    {

        public Startup(IConfiguration configuration)

        {

            Configuration = configuration;

        }

        public IConfiguration Configuration { get; }

        // Use this method to add services to the container.

        public void ConfigureServices(IServiceCollection services)

        {

            services.AddRazorPages();

            services.AddSignalR();

        }

        //Use this method to configure the HTTP request pipeline.

        public void Configure(IApplicationBuilder app, IWebHostEnvironment env)

        {

            if (env.IsDevelopment())

            {

                app.UseDeveloperExceptionPage();

            }

            else

            {

                app.UseExceptionHandler("/Error");

                app.UseHsts();

            }

            app.UseHttpsRedirection();

            app.UseStaticFiles();

            app.UseRouting();

            app.UseAuthorization();

            app.UseEndpoints(endpoints =>

            {

                endpoints.MapRazorPages();

                endpoints.MapHub<ChatHub>("/chatHub");

            });

        }

    }

}

Let’s have a look at the Startup class in more detail.

The Startup class

If you have been a .NET developer for any length of time, you will know that there is a requirement in .NET for command-line applications. That requirement is to have a static void Main method, typically in a class called Program.

Opening up the Program class of the realtimechat project, you will see the code shown in Code Listing 9.

Code Listing 9

namespace realtimechat

{

    public class Program

    {

        public static void Main(string[] args)

        {

            CreateHostBuilder(args).Build().Run();

        }

        public static IHostBuilder CreateHostBuilder(string[] args) =>

            Host.CreateDefaultBuilder(args)

                .ConfigureWebHostDefaults(webBuilder =>

                {

                    webBuilder.UseStartup<Startup>();

                });

    }

}

Here you will see the public static void Main method mentioned previously. This is the entry point (where execution will start) when the realtimechat application starts running. The Main method is used to create a host builder, specifically a default builder.

A builder, in this case, knows how to create a web host. The default builder also sets up some of the default services behind the scenes. In Code Listing 9, you will also see that we are telling this default builder to configure our application using the Startup class by adding the line of code webBuilder.UseStartup<Startup>().

In Code Listing 10, in the Main method, we Build() the builder. This gives us a web host instance that knows how to listen for connections and how to process and receive HTTP messages. Finally, we tell the web host to Run().

Code Listing 10

public static void Main(string[] args)

{

    CreateHostBuilder(args).Build().Run();

}

Once we call Run(), everything that happens in the application is determined by the code that is contained in the Startup class.

If you place your mouse cursor on the Startup in UseStartup<Startup> and press F12, you will jump to the Startup class we added our code to earlier, as outlined in Code Listing 8. ASP.NET Core now knows that it’s going to instantiate the Startup class and invoke two methods.

The first method is ConfigureServices. The ConfigureServices method will allow us to add our own custom services in ASP.NET Core. This will then inject those services into pages, controllers, and wherever else we might need them.

The second is the Configure method. This will determine what middleware it will execute for every incoming HTTP message.

Note: The request pipeline comprises of a series of middleware components. Each middleware component performs some operation on the HttpContext, and then invokes the next middleware in the pipeline or terminates the request.

You can also create custom middleware components, but this is beyond the scope of this book.

Scroll To Top
Disclaimer
DISCLAIMER: Web reader is currently in beta. Please report any issues through our support system. PDF and Kindle format files are also available for download.

Previous

Next



You are one step away from downloading ebooks from the Succinctly® series premier collection!
A confirmation has been sent to your email address. Please check and confirm your email subscription to complete the download.