Introduction
In this article, I will walk you through an "Azure SignalR Service" using a Buyer-Supplier sample application. Azure SignalR service provides a real time communication between your application/pages.
- We will cover a couple more Azure Services like Azure Functions, Azure Service Bus & Azure SQL Database.
- We will have one Buyer application in Asp.net core Razor Forms and ONE Supplier application in Asp.net core MVC.
Prerequisites
- Azure Account for setting up Azure Services (SignalR, Functions, Service Bus etc)
- Visual Studio 2019 (For buyer and supplier application)
Application Flow
- Buyer Application - Buyer will create an order for an item with quantity.
- Supplier Application - Supplier will get notified (A prompt message on his screen) that a buyer has added a new order.
- Supplier Application - Supplier will accept or reject the buyer orders.
- Buyer Application - Buyer will get notified on his screen that supplier has accepted/rejected his order.
The notification(Buyer/Supplier) will get triggered by Azure SignalR Service. It means, we will be registering our application/pages to the SignalR service.
Project Structure
.
- 1. Entities - Contains a class "ActiveOrder" which is used for storing the active orders object from UI and Database
- 2. Common - Here we have AppSettings.cs class, it used for storing the appSettings values from app.config files in #5 UI projects
- 3. DB - DB Schema and Stored Procedures used in application
- 4. OrderProcessingFunctionApp - Azure Function application
- 5. UI - Buyer and Supplier - Client applications, one is for buyer and one is for supplier
Design/Flow
Azure SignalR Service
- Login to "portal.azure.com"
- Click on "Create a resource" link
- Search for "SignalR Service" in Azure market place:
- Click on "Create"
- Provide the details as shown below and click on "Next Networking"
- Keep the end-point public for our demo:
- Click on "Review and Create" and then "Create". Once your "SignalR Service" deployment is done, then verify it in your Resource Group that it is added there.
Azure Service Bus
- Go to Azure market place and search for Service Bus Or you can get it under "Integration" section on left:
- Fill the details like Resource Group, Service bus name etc:
- Click on "review + create" and "create".
Create Queues under the created Service bus
Once your deployment is done, then go to your "Resource Group" and click on your newly created "Service Bus" resource.
In this service bus, we will create 2 queues, which will get the data/message from Buyer web application and Supplier web application.
- Click on "+ Queue", It will open a "add new queue" wizard:
- Create a queue "buyerOrders" as below (It will receieve message/data/object related to buyer order details):
- Create a queue "supplierResponses" as below (It will used to recieve the supplier response against buyer order):
- You can see that both queues are created under service bus:
Create Azure SQL database
- Go to Azure market place and select "SQL Database" under "Databases" section:
- Fill the database details and click on "Create New" server:
- On Networking tab, make selections as below, to connect db from your local machine and so other Azure service could connect DB:
- Click on Create.
- Create a table in the database as "Orders" (Script is available attached code in DB Folder, Execute the stored procedures also)) :
In this table, The "ItemName", "Quantity" and "BuyerName" will get inserted when buyer creates an order and the "status" will be saved as "Draft".
When supplier provides a response, we just update the status field with either "Accepted" or "Rejected", based on the supplier input.
Create Azure Function App in Visual Studio and name it as "OrderProcessingFunctionApp" (Already available in source code, just covering so if anyone wants to know),
- Select "Service Bus Queue Trigger" and click on "create":
- It will create an Azure function project in your solution (I renamed function.cs to ProcessOrder.cs)
- Open ProcessOrder.cs file, you can see that we have implemented 3 functions,
- NewOrderSubmitted - This function will get called whenever a buyer submits a new order using buyer web application. So, it recieves the order details and we save it in the database and pass it to SignalR. Here is our function
- Here the function name is "NewOrderSubmitted" set it in attribute "FunctionName("NewOrderSubmitted")"
- "ServiceBusTrigger" - This function will get triggered when we send any data/message to Service bus queue named "buyerOrders", service bus connection string key is "ServiceBusConnectionString" and the buyer order data comes in parameter order of dataType "ActiveOrder".
- SignalR hub name is "notifications", we will use it in buyer application (In startup.cs file) later.
- SaveToDatabase - Function which saves the new order details into database
- SignalRMessage - Message which we will be sending to signalR
- Target - It is the name of the client action, which is registerted to SignalR, in our case its a Supplier application page. All these clients will get notified that a new order has been added into system
- Arguments - The data which we need to send to signal R, in our case it's order details
- SupplierResponse - This function will get triggered when Supplier accepts/rejects buyer order. So we will notify to buyer that your order is accepted or rejected.
- Here the function name is "SupplierResponse" set it in attribute "FunctionName("SupplierResponse")"
- "ServiceBusTrigger" - This function will get triggered when we send any data/message to Service bus queue name "supplierResponse", service bus connection string key is "ServiceBusConnectionString" and the message comes in parameter of dataType "string".
- SignalR hub name is notifications
- SignalRMessage - Message which we will be sending to signalR
- Target - It is the name of the client action, which is registerted to SignalR, in our case its a Buyer application page. Buyer will get notified that supplier either accepted or rejected his order.
- Arguments - The data which we need to send to signal R, in our case its a string message containing Accepted/Rejected detail
- Negotiate : This will talk to Azure SignalR service and provide a API key that will be used in further communication in sending messages.
- Deploy Azure function application on Azure:
- Right click on function app project and click on Publish
- It will open a publish wizard, Click on New:
- Specific Target as Azure Function App (Windows):
- Click on "Create a new azure function":
- Provide Name, Resource Group, Location etc and click on Create:
- Click on Finish on parent window.
- Click on Publish to deploy it on Azure :
- After Deployment, your Function app will be available on Azure in your resource group:
- Click on your function app, Check the URL, we will use it in our buyer and supplier applications (in document.ready() event on UI)
- Click on the Functions on left to get all three functions we created in function app:
- Setting Connection String in Function App for ServiceBus, SignalR and SQL database
- Open portal.azure.com and go to your Resource Group. We need to get the connection information of the below marked resources:
- Get the connection string of SignalR Service. Copy the below Connection String and copy it in one notepad file (We will use it later):
- Get the connection string of Service Bus. Copy the value og Primary connection string(right), and keep it in notepad
- Get the SQL connection string and keept it in notepad:
- Go to your Azure function and add new application settings as below (Set the respecticve values for these settings you copied from previous 3 steps):
- Go to your Azure function and add connection string for Service Bus (In previous step we added it as application setting), as below:
Web application (Buyer and Supplier)
- Setup Buyer application (Razor Forms)
- UI of buyer application. We have three fields, Buyer Name, Item and Quanity, on Click of submit this information will be going to Service Bus. The Service bus will trigger the Azure function, where we are saving it into database and sending the message to SignalR hub, so signal hub will send out the notification to all the connected clients (Supplier application):
- If you look the Buyer.cshtml page, you will find code block below:
- withUrl - We are creating SignalR connection using your function app URL. This is your function app URL.
- signalRHubConnection.start() - It will execute when SignalR connection is created
- signeRHubConnection.on('supplierResponses', - It is the target which we setup in out function app functions, So, when supplier provide response, the SignalR gets the message and looks for clients registered with 'supplierResponses' as target. So, all these clients will get notified. In our logic, buyer will get notified.
- If you look at the Buyer.cshtml.cs file, here is what we are doing on submit button click:
- 1. We are reading Service Bus Connection String and Queue Name from apsettings.json (It is copied from Azure Service bus):
- 2. Creating a queue client, using the Service bus connection string and Queue name.
- 3. Creating a message for Service bus with buyer order details
- 4. Sending data to Service Bus
- Service bus queue will trigger our NewOrderSubmitted Azure Function
- That function will save the data on to database and pass the object to Signal R service
- Startup.cs file. We have configured the SignalR and the default page as Buyer:
- Setup supplier application (MVC)
- UI of supplier application. We have a table, where we will show all the buyer orders, and supplier can either accept or reject the order. There is a refresh button which supplier will click, when he will get notification for new orders added in the system,
- If you look in Views/Supplier/index.cshtml file, you can see that if has bound a couple of events:
- In document.ready event on client side, we are setting the signalR hub connection by passing the url of azure function app.
- When signalR hub connection initializes, we log that in browser console.
- signalRHubConnection.on('newOrderSubmitted', function (orderDetails) - This will execute when we pass message to signalR and the target is set to newOrderSubmitted. In our code, it is used at azure function app [FunctionName("NewOrderSubmitted")]
- #btnRefresh click event - It just reloads the current page so we can load other new orders
- #btnAccept and #btnReject click event - It calls one method specified in "Controll/SupplierController.cs", which updates the status of the order and passes a message to service bus queue "supplierresponses", which triggers the Azure function [FunctionName("SupplierResponse")], and from this function we send a message to SiganlR service, which will notify all the buyers as the taget is set to "supplierresponse"
- If you look into Controllers/SupplierController.cs, you can see how we are loading the data and how we are updating the buyers order status:
- Supplier Controller - Supplier page controller
- Action -Index - It will get called as default page and it will fetch all the active orders and pass that to UI
- Method - SupplierResponse - It will get called on click of Accept/Reject buttons and it updates the status of order in database
- Contructs Message for Service Bus - For queue "supplierresponses". The service bus connection string, queue name and SQL connection string, we are reading from appsettings.json file
- Send the message to the queue. So buyer will get notified that order has been accepted or rejected
- These two applications run on https locally on port 44343 and 44322 , So, we need to allow these URLs in the CORS (Cross Origin Requests) settings of your function app,
- Go to buyer and supplier application, right click and select properties, then go to Debug
- So, the URLs, mapped with enable SSL on both the applications, we need to add these to the CORS list in Azure function app as:
- Note: If you get an error, while connecting SQL databse from local, then make sure that your local ip is allowed to connect with SQL database on Azure. Go to the SQL database on Azure and click on Set firewall rule:
- Click on Add client IP and Save:
- To debug, make both the buyer and supplier application as startup applications. Go to project solution (left), right click and select properties, then make the changes as shown below:
- Run the application in visual studio, and you will see that it will open two browsers, one is for buyer view, and one is for supplier view:
- When buyer fills a form and clicks on submit, you will see that supplier will get notification as below:
- When supplier provides the response, by clicking on Accept /Reject, you can see that the buyer will get notified that the supplier has accepted/rejected his order:
Conclusion
We have seen how we can use Azure SignalR service and how we can integrate it with other Azure services like Service Bus and Azure Functions. It is very a simple detailed example where we have two fixed clients but we can explore more from here to send the notification to single users when we have multi tenant applications.