How can we leverage Azure Functions and Service Bus Queues to enable background processing in an ERP application.

In a typical ERP system, new customers are created continuously and these customer entities are pushed as messages to the Service Bus Queues to process and store into the database systems.  

Azure Functions and Service bus Queues for background processing in eRP application
Fig:- 1

In this application scenario, Web App supports multiple users to enter customer entities data simultaneously. The time the Web App takes to return a view determines the responsiveness of the Web application. To avoid long-running processes and get faster responses from Web site views, we use Azure Service Bus Queues. These Queues allow Web Apps to store messages containing the details to be processed and they can remain responsive. In the background, another component reads the queue and performs the required processing for each message. This way we can achieve de-coupleing between the Web App and processes running at the background. In this case, Service Bus queue is ideal because it is inexpensive, easy to use and has great integration with Azure Functions. So, it is ideally suited for for doing this kind of background processing. In the ERP applications, Service Bus Queues are often used for processing Sales Orders and Financial Transactions also.

Other Azure services like Storage queues, EventHubs and EventGrid also performs similar functions, but each one suits best for other scenarios. I will discuss when to use which service in a separate blog post.

In this article, I will demonstrate how we can leverage Azure Functions and Service Bus queues to enable background processing for a webapp. Customer details are entered from ERPCRMWebApplication into Azure Service Bus Queue as shown in the Fig:-1.

We will begin with creating a Service Bus Namespace and a Service Bus Queue using the below instructions. You can follow the article on Create a Service Bus in Microsoft resouce page or follow my instructions using the steps I have given below.

Create a Service Bus namespace using the Azure portal

To create a namespace:

  1. Sign in to the Azure portal.
  2. In the left navigation pane of the portal, click + Create a resource, then click Integration, and then click Service Bus. Refer Fig:-2.
Azure Service Bus
Fig:- 2

In the Create namespace dialog, enter a namespace name. The system checks for validity and makes sure the name is globally unique since it is used as part of the URI to the service. I have given the name erpcrmservicebusns to my Service Bus Namespace. Refer Fig:-3. Choose the pricing tier as either Basic, Standard, or Premium. I have choosen Standard Pricing tier. If you are planning to use Topics/subscriptions, choose either Standard or Premium. The other fields Subscription, Resource group and Location are self explanatory. Select the same Location that you are going to deploy the application to ensure a best performance of the application.

Creating a new Azure ServiceBus Namespace
Fig:- 3

Clicking on Create button creates a new namespace and resources are provisioned for your account. Now, you can see the Dashboard which is showing the newly created Servciebus namespace. Refer Fig:-4.

ServiceBus namespace resource in Dashboard
Fig:- 4

Clicking on the resource will give you the details of the resource. Refer Fig:- 5.

Selecting ServiceBus namespace in Dashboard
Fig:- 5.

Now we need to create a Queue in the Azure servcie Bus to store Customer details as messages which are entered in a web app. Follow the steps which are given below to create a Queue.

Create a queue using the Azure portal

Select the Service bus Namespace in which we would like to create the Queue. Here, it is erpcrmservicebusns. Refer Fig:- 6. Click Queues on the left under Entities and then in the Queues window, click + Queue.

Azure Service Bus Queue
Fig: -6.

In the Create queue dialog as shown below, give a name to the queue and Click the Create button. I have named queue as customerqueue. Refer Fig:-7.

Create Azure Service bus Queue
Fig:- 7


Obtain the default management credentials for the namespace

To perform operations, we should get the default management credentials for the namespace. A SAS key is generated when a service namespace is created. Applications can authenticate to the Service Bus using Shared Access Signature (SAS) authentication. In the namespace window, click Shared access policies and click RootManageSharedAccessKey. Refer Fig:-8.

Service Bus Shared Acess Policies
Fig:-8

Clicking on Copy button next to Primary Connection String copies the connection string to your clipboard. You should copy these values in a safe place so that we can use them in the application that requires these credentials. When we create a Service Bus client application we can use either the SAS coneection string or ACS connection string to connect to the namespace.

The credentials for Service Bus to authenticate access to an application is the combination of namespace and SAS key as shown below.
Endpoint=sb://erpcrmservicebusns.servicebus.windows.net/;SharedAccessKeyName=RootManageSharedAccessKey;SharedAccessKey=PzfCoQ=”;

Azure Function

Before we build a Service Bus client application (.Net Core Console app or ASP.Net core web app) in Visual studio, let us create a Service Bus triggered Azure function. Let us now see how to implement an architecture where Azure Service Bus receives messages to signal a new Customer into the system, which will trigger an Azure Function to process and store these details into the database system.

Create a Service Bus triggered Azure Function

Select Compute > Function App and in the Function app dialog, fill the function app settings as shown below. Here, I have given the Function App name as erpcrmfunctionapp. It should be a globally unique name. Refer Fig:-9. Click on Create button provisions and deploys the function app.

Azure Function App Creation
Fig:-9

After we create a Function App, we can go to the Dashboard and see the list of resouces created. Refer Fig:-10.

Azure Function app resources in Dash board
Fig:- 10.

Next, we create a function in the new function app. Add a new Function to the Function App by pressing the + sign next the the Functions menu item, Refer Fig:-11.

Creating a Function in ERP CRM Function App
Fig:-11

Choose More Template option. Refer Fig:-11. Find and select the Azure Service Bus Queue Trigger. Refer Fig:-12.

Selecting Azure Service Bus Queue TriggerTemplate
Fig:-12.

We will get a prompt to install
Microsoft.Azure.WebJobs.Extension.ServiceBus extension. Refer Fig:- 13. Click on the Install button.

Installing Azure ServiceBus Extension in the Azure function
Fig:-13.

Refer Fig:-14. Next, select the new link to create a Service Bus connection.  When the new link is selected, you will be prompted by a windows similar to that seen in Fig:-15.  The Service Bus connection will contain the RootManageSharedAccessKey which is part of the Service Bus connection string and accessible via the “erpcrmservicebusns_RootManageSharedAccessKey_SERVICEBUS” application setting.

Setting the Azure Service Bus Connection in Service Bus Queue Triggered Azure function
Fig:-14
Azure Function ServiceBus Connection
Fig:-15.

Refer Fig:-16. Give a name to a function and add the Queue Name customerqueue which we created earlier. Click on the Create button.

Setting Queue name in Azure Service Bus Triggered Azure Function
Fig:-16

You get the default Run() method as shown in Fig:- 17. When a new message is posted to Service Bus queue – customerqueue, the Azure Function is instantiated and its Run method is invoked.

Azure Function run.csx default code
Fig:-17

Refer Fig:-18. Run() method has a string input parameter, now, we can run the new function by sending a string value customer1 and click on Run button. When the function runs, trace information is written to the logs as you can see in the below screenshot.

Testing Azure Function by sending a Customer name as string parameter
Fig:-18.

Create a console application to Send messages to the queue

In the actual implementation, ASP.Net Core MVC Web App that sends messages to the Service Bus Queue as soon as Customer details are entered in a web form. However, to make it simple I have created a simple Console app project in Visual studio that sends messages to the ServiceBus Queue.

Create a new Console App (.NET Core) project in a Visual Studio. Refer Fig:-19.

Creating console app in Visual Studio
Fig:-19

Add the Service Bus NuGet package

Microsoft.Azure.ServiceBus is the NuGet package that must be added as a new dependency:

  1. Right-click the newly created project and select Manage NuGet Packages.
  2. Refer Fig:-20. Click the Browse tab, search for Microsoft.Azure.ServiceBus, and then select the Microsoft.Azure.ServiceBus item. Click Install to complete the installation, then close this dialog box.
Adding Microsoft.Azure.ServiceBus nuget package to the .Net Core Console app
Fig:-20.

Write code to send messages to the queue

  1. In Program.cs, add the following using statements at the top of the namespace definition.
using System;
using System.Text;
using System.Threading.Tasks;
using Microsoft.Azure.ServiceBus;
using Newtonsoft.Json;

In the Program.cs file, declare the following two variables.

  • ServiceBusConnectionString
  • QueueName

Set the ServiceBusConnectionString variable to the connection string that we obtained and saved after creating the Service Bus namespace. Set QueueName to the name that we created in the Azure Service Bus.

Setting Azure Service Bus Connection String in .Net Core console App
Fig:-20
static void Main(string[] args)
{
MainAsync().GetAwaiter().GetResult();
}
static async Task MainAsync()
{
 queueClient = new QueueClient(ServiceBusConnectionString,  QueueName);
   
  Console.WriteLine("=========================");
  Console.WriteLine("Press ENTER key to exit.");
  Console.WriteLine("==========================");

  // Send Messages
  await SendMessagesAsync(numberOfMessages);
  Console.ReadKey();
  await queueClient.CloseAsync();
 }

static async Task SendMessagesAsync(int numberOfMessagesToSend)
{
   try
    {
                var customer = new Customer();
                customer.CustomerId = 1;
                customer.Name = "Chris";
 var message = new Message(Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(customer)));
                // Send the message to the queue
                await queueClient.SendAsync(message);
              
            }
            catch (Exception exception)
            {
           Console.WriteLine($"{DateTime.Now} :: Exception: {exception.Message}");
            }
        }

        class Customer
        {
            public int CustomerId { get; set; }
            public string Name { get; set; }
        }
   }
}

A QueueClient object is instantiated with the Service Bus connection string and the Queue name in input, and its SendAsync method is used to send a new Message object, which is created with the json produced by serialising a Customer object. Customer contains the CustomerId and Name of customer.

If we run this Console Application, it sends Customer object to the customer queue and we can see that in the Azure portal, the ‘Message Count’ in the queue is increased. Now, these messages are be picked up and processed.

Now we will edit the ServiceBusQueueTrigger1 Function code as shown below.

Azure Servcie Bus Function run.csx code
Fig:-21
using System;
using System.Net;
using System.Threading.Tasks;
using System.Runtime.Serialization.Json;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Text;
using System.Data;
using System.IO;

public static void Run(string myQueueItem,ILogger log)
{
   log.LogInformation($"C# service bus queue triggered function processed message:{myQueueItem}");
   Customer msg = GetCustomerFromJson(myQueueItem);
   log.LogInformation($"Notification for customer id {msg.CustomerId} there!");
   log.LogInformation($"Customer Name {msg.Name} there!");    
}

public class Customer
{
    public int CustomerId { get; set; }
    public string Name { get; set; }
}

 public static Customer GetCustomerFromJson(string json)  
{  
  using (MemoryStream ms = new MemoryStream(Encoding.UTF8.GetBytes(json)))
   {
    DataContractJsonSerializer ser = new DataContractJsonSerializer(typeof(Customer));  
    Customer msg = ser.ReadObject(ms) as Customer;  
    return msg;  
    }
} 

Whenever a new message is posted to Service Bus queue, the Azure Function is instantiated and its Run method is invoked. Run has a string input parameter, which is the json of the Message created previously, that contains the CustomerId and Name attributes. The json body is deserialised into a Customer object. If everything goes well, the log window on the Azure Function should display CustomerId as 1 and Name as Chris. This confirms that the Function was invoked by the Service Bus Queue trigger and displayed log messages.

In the next part of this article, I will explain how to connect to the Azure SQL database from Azure function and save the Customer details to ERP CRM database.

Leave a Reply