3
votes

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?

3

3 Answers

2
votes

Read "How to Receive Messages from a Queue" in http://www.windowsazure.com/en-us/documentation/articles/service-bus-dotnet-how-to-use-queues/

But, if you have a worker role generating messages and you want to use SignalR, I'd recommend using that worker role as a broadcast hub for SignalR - see Tutorial: Server Broadcast with SignalR 2.0

2
votes

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.

-1
votes
 //Fetch connection string from config  
        string connectionString = ConfigurationManager.AppSettings["connectionString"];
        // Create the connection 
        MessagingFactory factory = MessagingFactory.CreateFromConnectionString(connectionString);
        //Provide the queue name in the service bus
        MessageReceiver receiver = factory.CreateMessageReceiver("queue Name");
        BrokeredMessage retrievedMessage = receiver.Receive();
        if (retrievedMessage != null)
        {
            try
            {
                string output = retrievedMessage.GetBody<string>();
                //In the output string you will get the message from the queue.
                retrievedMessage.Complete();
            }
            catch (Exception ex)
            {
                retrievedMessage.Abandon();
            }
        }