I if may point out I don't have a code issue nor the requirement for code review, hence posting here.
I'm generally looking for a better understanding on how to truly architect a SignalR .Net Client
project to prevent multiple HubConnections
being instantiated.
I/We have a prototype in a staging environment, which successfully passes print information from remote distribution centres to our app.
What truly baffles me is that I am instantiating a HubConnection
every time I need to send a message accessed directly on the Hub, not an api endpoint.
Please allow me to demonstrate some code, So our system talks to a locked down api, which then talks to a hub hosted else where.
[IdentityBasicAuthentication]
[Authorize]
[RoutePrefix("api/v1")]
public class PrinterStatusV1Controller : ApiController
{
//logic removed
private HubConnection _hubConnection;
public PrinterStatusV1Controller()
{
//logic removed
}
[HttpPost]
[Route("dummy")]
public async Task<IHttpActionResult> AddPrinterStatusAsync([FromBody]PrinterStatus printerStatus)
{
try
{
var identity = User.Identity as ClaimsIdentity;
var identityInstance = new IdentityInstance(identity);
if (identityInstance == null)
return StatusCode(HttpStatusCode.Forbidden);
if (printerStatus == null)
return NotFound();
IHubProxy aProxy = Create(dummy);
if(printerProxy != null)
await printerProxy.Invoke("dummy", dummy);
await _printerStatusRepo.Dummy(dummy);
return Ok();
}
catch (System.Exception ex)
{
return InternalServerError();
}
}
private IHubProxy Create(string dummy)
{
try
{
/logic removed
_hubConnection = new HubConnection("dummy", dictionary);
var hubProxy = _hubConnection.CreateHubProxy("dummy");
_hubConnection.Start().Wait();
_hubConnection.Closed += () => {
var connected = false;
while (!connected)
{
System.Threading.Thread.Sleep(2000);
_hubConnection = new HubConnection("dummy", dictionary);
hubProxy = _hubConnection.CreateHubProxy("dummy");
_hubConnection.Start().Wait();
connected = true;
}
};
return hubProxy;
}
catch
{
return null;
}
}
protected override void Dispose(bool disposing)
{
if (disposing)
{
if (_hubConnection != null)
{
_hubConnection.Stop();
_hubConnection.Dispose();
}
//logic removed
}
base.Dispose(disposing);
}
}
}
I should get to the point, What is the generally the best pattern/architecture to avoid creating a HubConnection
, every time I call an endpoint? any hints greatly appreciated. I can put many abstractions in place but theoretically it's going instantiate a new HubConnection
each time..
Best Answer
Maintain a reference to one
HubConnection
object, and re-use it for subsequent API calls.This can be done in a number of different ways, without overly complicating your architecture. For example, if you're using a DI container, you can tell your container to use a Singleton lifetime, so that when you ask for a
HubConnection
object, you get the same one back each time.Instance members of
HubConnection
are not thread safe. Treat them accordingly.