Search code examples
asp.net-mvcazuresignalrservicebus

How do I get an ASP.NET MVC app to read from an Azure Service Bus Queue?


I have a worker role running in windows azure which generates messages. I have an ASP.NET MVC app which has a SignalR hub. I'd like to push messages from the worker role to the SignalR hub which would then push these out to connected clients in real-time. My thoughts would be to use an Azure service bus queue which the ASP.NET MVC app would read from. It all seems straightforward enough of a concept but I'm not sure how to wire up a service bus QueueClient in the MVC app. I can find plenty of samples with ASP.NET MVC putting messages in a queue to be picked up by a worker role service but not the other way round.

Question: Is there are way to do this? Could anyone point me in the direction of some samples etc?


Solution

  • In our project we are using this on MvcApplication > Application_Start:

    new Thread(t => Container.Resolve<IMessageRouter>().StartRouting()).Start();
    

    We are also using DI (Windsor container), router is registered as Transient. Router starting with web-application in parallel thread and working all the time.

    Router has SignalR hub connection context and topic listener (topic client wrapper):

    public class MessageRouter : IMessageRouter
    {
        private string _subscriptionName = "Subscription_0";
    
        private IHubConnectionContext ClientContext
        {
            get { return GlobalHost.ConnectionManager.GetHubContext<MessageHub>().Clients; }
        }
    
        private RoleInstance CurrentRoleInstance
        {
            get // try to get current Azure role instance
            {
                if (RoleEnvironment.IsAvailable && RoleEnvironment.CurrentRoleInstance != null)
                {
                    return Microsoft.WindowsAzure.ServiceRuntime.RoleEnvironment.CurrentRoleInstance;
                }
    
                return null; // return null if not Azure environment
            }
        }
    
        private string TopicName
        {
            get { return ConfigurationHelper.TopicName; }
        }
    
        private string TopicConnectionString
        {
            get { return ConfigurationHelper.TopicConnectionString; }
        }
    
        public ITopicListener TopicListener { get; set; }
    
        public void OnMessage(QueueMessage message)
        {
            ClientContext.Group(message.GetRecipientGroup()).updateProgress(message.GetBody<string>());
        }
    
        public void StartRouting()
        {
            TopicListener.Bind(TopicConnectionString, TopicName, _subscriptionName).StartListening(OnMessage);
        }
    
        public MessageRouter()
        {
            if (CurrentRoleInstance != null) // check Azure environment is exist
            {
                int instanceIndex = 0; string instanceId = CurrentRoleInstance.Id;
    
                if (!int.TryParse(instanceId.Substring(instanceId.LastIndexOf(".") + 1), out instanceIndex)) // on cloud
                {
                    int.TryParse(instanceId.Substring(instanceId.LastIndexOf("_") + 1), out instanceIndex); // on compute emulator
                }
    
                _subscriptionName = String.Format("{0}_{1}", CurrentRoleInstance.Role.Name, instanceIndex);
            }
        }
    }
    

    And it works. Hope this helps.