How to Propagate Feedback from a Class Library to an ASP.Net Client using SignalR

A detailed look at how a callback mechanism at the library backend can be propagated to the web client frontend via SignalR groups

Sami Islam
6 min readAug 2, 2020
Photo by Harshal Desai on Unsplash

I recently had to figure out how to create a library that provides feedback to the user irrespective of whether the user is a simple .NET Console application or an ASP.Net Web client. The example code I am going to use in this article is vastly simplified, starting with the library:

The SimpleDLLFeedback class
SimpleDLLFeedback takes IWriter during instantiation

The SimpleDLLFeedback provides the core functionality and can be used both from a .NET Console application and from an ASP.Net Core Web API. The client using the API requires to show any feedback from the SimpleDLLFeedback on a dedicated UI region.

This article describes how to propagate the "SimpleMethod called"feedback from the SimpleDLLFeedback to the web client via the Web API layer using SignalR without modifying any code in the DLL. The article focuses only on the Web API layer and simulates the frontend by using:

  • the Postman tool - to send a request to the Web API layer
  • .Net Console application (HttpClient)- to receive the feedback "SimpleMethod called" from the SimpleDLLFeedback

ASP.Net Core Web API Layer

I created a standard ASP.Net Core Web API using the dotnet new webapi command and deleted the default controller code. I then ran dotnet add package Microsoft.AspNetCore.SignalR to add the SignalR nuget package and added the SignalR functionality in the Startup.cs file:

Configure SignalR in the ASP.Net Web API
Configure SignalR in the ASP.Net Web API

Create the SignalR Hub and store the client connection information

The SignalR Hub named FeedbackNotifierHub creates a client connection group using the subscriberID as shown below:

The SignalR Hub name FeedbackNotifierHub
The SignalR Hub name FeedbackNotifierHub

The Context.GetHttpContext().Request.Query[subscriberIdTag] looks for the subid query parameter in the client connection request and uses the value to add the connection to a group identified by the subscriberID Groups.AddToGroupAsync(Context.ConnectionId, subscriberID). Using the subscriberID this way allowed me to connect the client request to run a SimpleMethod via REST API to the “same” client’s http connection to receive the feedback "SimpleMethod called" via SignalR. It is important to realise that the subid value has to be used in two places:

  1. In the REST API call made by the Web client
  2. In the HTTP client connection to the SignalR Hub to receive the feedback

I added the FeedbackNotifierHub to the Startup.cs file as follows:

Configure the FeedbackNotifierHub
Configure the FeedbackNotifierHub

The exact connection URL for a client with a subscriberID of Client1 would be (my local server runs on port 5000):

http://localhost:5000/feedbacknotifierhub?subid=Client1

Use the SimpleDLLFeedback from the ASP.Net Controller

In order to add the SimpleDLLFeedback to the ASP.Net Controller I first created the NotifyingFeedbackWriter service:

The NotifyingFeedbackWriter allows to connect the ASP.Net client to the feedback
The NotifyingFeedbackWriter allows to connect the ASP.Net client to the feedback

The INotifyingFeedbackWriter is as follows:

The NotifyingFeedbackWriter interface
The NotifyingFeedbackWriter interface

The important thing to notice here is that I could not use the IWriter interface directly since I needed a way to connect the client REST API call to the “same” client’s HTTP connection to the SignalR Hub. The SetNotifier method is used for that.

Also notice how the IFeedbackNotifier pops up in this interface and also as the strongly-typed Hub used in the FeedbackNotifierHub : Hub<IFeedbackNotifier>. This indicates that the client interface for the SignalR Hub is being used to send the actual feedback notification to the client.

After creating the IWriter implementation I added the SimpleDLLFeedback service to the controller:

Configure the NotifyingFeedbackWriter
Configure the NotifyingFeedbackWriter

It is important to add the INotifyingFeedbackWriter service as a scoped service. I shall come back to that later in the article.

The ISimpleDLLFeedback is used by the controller as follows:

Using the SimpleDLLFeedback from the controller via a proxy
Using the SimpleDLLFeedback from the controller via a proxy

Well, it turns out that the Controller does not use the SimpleDLLFeedback directly but rather through a proxy called SimpleDLLFeedbackProxy . The proxy is just a wrapper to connect the REST API call to simplemethod to the HTTP client connection to the SignalR Hub via subid which is a required query parameter for the REST API call.

I have also used a Func object to make the call to SimpleDLLFeedback “cleaner”. Notice how the SimpleDLLFeedback(subid) :

  1. Takes a required parameter - subid
  2. Returns the actual SimpleDLLFeedback object to call the SimpleMethod on

Create an SimpleDLLFeedbackProxy to connect the calling client to the feedback

The SimpleDLLFeedbackProxy is as follows:

The SimpleDLLFeedbackProxy connecting the ASP.Net Client to the feedback “automagically”
The SimpleDLLFeedbackProxy connecting the ASP.Net Client to the feedback “automagically”

The proxy takes the following input parameters during instantiation:

  1. The INotifyingFeedbackWriter to set the actual notifier to be used for the feedback
  2. The IHubContext to obtain the current client connection using the subid to query the connection group
  3. The ISimpleDLLFeedback to return the actual object used to make the call

The only reason I used the proxy is to hide away the fact that every call to the SimpleDLLFeedback requires the subid to be set first via the REST API call.

The input constructor parameter INotifyingFeedbackWriter used here will create a new instance in the ASP.Net dependency injection model unless the service is added as a scoped service - which I have already done before. It is extremely important that the same instance is used for the REST API handling and in the creation of the SimpleDLLFeedback service.

I added the SimpleDLLFeedbackProxy to the controller:

Configure the SimpleDLLFeedbackProxy
Configure the SimpleDLLFeedbackProxy

The Simulated Frontend

Send a request

Now that I have created the ASP.Net WEB API I can just run it using dotnet run :

ASP.Net WebServer Console Output
ASP.Net WebServer Console Output

After starting the WebServer I sent a REST API GET request http://localhost:5000/simplemethod?subid=Client1 using Postman which returned 200 OK .

Postman GET Request Output
Postman GET Request Output

The WebServer output:

The ASP.Net WebServer output after sending a GET Request
The ASP.Net WebServer output after sending a GET Request

Receive the feedback

To receive the feedback SimpleMethod called from the library, I created a .NET Console application that connects to the SignalR Hub and listens for ReceiveFeedback calls on the client connection:

HTTPClient to receive the feedback from the library
HTTPClient to receive the feedback from the library

I also added the following nuget packages to the HttpClient:

1. dotnet add package Microsoft.AspNetCore.SignalR.Client
2. dotnet add package Microsoft.Extensions.Logging

After starting the server and the HttpClient with the parameter Client1 I see the following on the server console:

The ASP.Net WebServer Output after a Client connection to the SignalR Hub
The ASP.Net WebServer Output after a Client connection to the SignalR Hub

After sending a REST API Get request I see the following on the HttpClient console:

The HttpClient Console output after sending a GET Request from Postman
The HttpClient Console output after sending a GET Request from Postman

All code used in this article can be found in my GitHub repository.

I hope that my article helps others.

--

--

Sami Islam
Sami Islam

Written by Sami Islam

Non-binary thinker and a lifelong learner.

Responses (1)