0
votes

I have a webapi project where I have configured SignalR hub. I am able to send messages to client from within the api project but I have to send the messages from the repository project.

MyAAPIProject > Controller:

[HttpGet]
[Route("test")]
public IHttpActionResult UpdateEmployees()
{
    _empRepo.Update();
    // This is working fine =>
    // MessageHub hub = new MessageHub();
    // hub.SendMessage("something");
}

MyAPIProject > SignalR Hub:

namespace MyAPIProject.Hubs
{
    public class MessageHub : Hub
    {
        public async void SendMessage(MessageDto p, string connectionId)
        {
            await Context.Clients.Client(connectionId).OnProgress(p);
        }
    }
}

I have added SignalRHub in WebApi project because as per documentation, we need to configure signalr in OWIN Startup class which can only be called in web projects(like my webapi project) not in class libraries(like my repository project).

MyAPIProject > StartUp:

public class Startup
{
    public void Configuration(IAppBuilder app)
    {
        app.MapAzureSignalR(this.GetType().FullName);
    }
}

RepositoryProject > EmpRepo:

public void Update()
{
    <<some task>>
    // This is what I want to do =>
    // MessageHub hub = new MessageHub();
    // hub.SendMessage("something");
    <<some task>>
}

Basically, from my webapi controller method, I am calling a repository(separate project) method which does the entire task and has to send task progress at regular intervals. In order to use SignalRHub to send message, I'll have to reference webapi project from repository.

But I am afraid that this will create circular dependency.

Can anyone please suggest how can I achieve this functionality without circular dependency?

1
Create an interface that in a location that is shared by the web api project and the repo project. Implement that interface in the web api project and use dependency injection when creating the repo class to inject the web api's implemention of your message sender.Grax32
Thanks a ton @Grax32. Don't know why I couldn't think of this earlier.Sachin Parashar
Can you add an answer mentioning the same. I will mark it as answer.Sachin Parashar

1 Answers

0
votes

Sounds like you need to implement a SignalR client using Microsoft.AspNet.SignalR.Client. You can add this from nuget.

Let's say your SignlaR hub implements a NotifyUpdateMethod. As a simplified example, you might create a messenger service.

public class MessengerService : IDisposable
    {
        private readonly HubConnection hubConnection;
        private readonly IHubProxy hubProxy;

        public MessengerService(HubConnection hubConnection)
        {
            this.hubConnection = hubConnection ?? throw new ArgumentNullException(nameof(hubConnection));
            hubProxy = hubConnection.CreateHubProxy(HubName);
        }

        public void Connect()
        {
            hubConnection.Start().Wait();
        }

        public void NotifyUpdate(int id)
        {
            hubProxy.Invoke(NotifyUpdateMethod, id);
        }
    }
}

You could create an instance of this service to connect to the hub and send messages.