In this blog, I am going to cover some of the most frequent issues/requirements people face when developing Azure Functions via Visual Studio. These topics are based on my learnings while developing Azure Functions and I wanted to share the same with community out there.
Here are the topics that I will cover in this blog post -
So let's get started.
- Local Debugging of Service Bus Triggered Azure Functions
When you try to debug your Service Bus triggered Azure Function locally, you would need to ensure that there are no other listeners active for your Service Bus Topic and Subscription. Listeners here refer to other people trying to debug on same Service Bus, Topic and Subscription, other Azure Functions or any WebJobs deployed on Azure and running continuously and listening to same Service Bus, etc. This is important because if there are other listeners active for the same Service Bus, Topic and Subscription combination, then there is a HIGH chance that the messages might get picked up by other listeners and your Debug point is not hit.
The approach mentioned below works for both version 1 and version 2 of Azure Functions.
Having said that, now lets set up our local environment to be able to debug the Service Bus Triggered Azure Function -
- Place a break point in the Azure Function.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | using Microsoft.Azure.WebJobs; using Microsoft.Extensions.Logging; namespace ASBListenerNameSpace { public static class ASBListener { [FunctionName("ASbListener")] public static void Run([ServiceBusTrigger("test", "test", Connection = "SBConnectionString")]string mySbMsg, ILogger log) { log.LogInformation($"C# ServiceBus topic trigger function processed message: {mySbMsg}"); } } } |
- Add a localsettings.json file in your Azure Functions project and ensure it has the Service Bus Connection string added to it.
1 2 3 4 5 6 7 8 | { "IsEncrypted": false, "Values": { "AzureWebJobsStorage": "UseDevelopmentStorage=true", "FUNCTIONS_WORKER_RUNTIME": "dotnet", "SBConnectionString": "Your-Service-Bus-connection-string-goes-here" } } |
- Run the Azure Function by pressing F5
- Send a message to Service Bus Topic.
- You will see that your break point is hit in Visual Studio and if you analyze the message parameter, it will have the message contents that was just sent to Service Bus Topic.
- Solving CORS Issue - while Local Debugging and after deployment to Azure
Often when we develop HTTP Triggered Azure Functions, we can easily test them out using Postman or VS Code, but there are scenarios when we are using the HTTP Triggered Azure Functions from within another Web Application, and during debugging locally, we might encounter CORS issue and the error as follows -
Access to XMLHttpRequest at 'http://localhost:5860/api/Function1' from origin 'null' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.
Here is a sample HTML app that i build to demonstrate this issue, it has a button and a div tag to show output of the response returned by Azure Function -
And here is the output that my Azure Function returns upon calling via Get HTTP method -
Now when I click on the Test Azure Function button, internally it will invoke the Azure Function URL via AJAX and then return the response if all good, else return a user friendly message in case of an error -
You can see the CORS error being logged in browser console window on the right.
CORS issue is basically because our Web Application and Azure Functions are running on a different port, thereby making their origins different. The same scenario will occur if you deploy the Web Application and Azure Function to Azure.
To solve this issue, we need to enable CORS in our Azure Function project. This will take care of our local debugging requirements of allowing CORS. For the deployed version on Azure, we need to enable CORS in the deployed Azure Function App Service in Azure.
Let's tackle both these scenarios one by one.
First, the local debugging issue. So, to enable CORS in your Azure Functions project, from within Visual Studio go to localsettings.json file within your project and add an entry for CORS like shown below -
Now, if you restart the Azure Function by pressing F5, and click on the Test Azure Function again, you should see the output returned by Azure Function being displayed in the UI, and no error this time in the browser console window -
So we have successfully enabled CORS in our Azure Function via localsettings.json file and this will take care of the local debugging scenario that we were talking about.
Now about the deployed version of Azure Function on Azure, you need to follow below steps to enable CORS there -
Access to XMLHttpRequest at 'http://localhost:5860/api/Function1' from origin 'null' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.
Here is a sample HTML app that i build to demonstrate this issue, it has a button and a div tag to show output of the response returned by Azure Function -
And here is the output that my Azure Function returns upon calling via Get HTTP method -
Now when I click on the Test Azure Function button, internally it will invoke the Azure Function URL via AJAX and then return the response if all good, else return a user friendly message in case of an error -
You can see the CORS error being logged in browser console window on the right.
CORS issue is basically because our Web Application and Azure Functions are running on a different port, thereby making their origins different. The same scenario will occur if you deploy the Web Application and Azure Function to Azure.
To solve this issue, we need to enable CORS in our Azure Function project. This will take care of our local debugging requirements of allowing CORS. For the deployed version on Azure, we need to enable CORS in the deployed Azure Function App Service in Azure.
Let's tackle both these scenarios one by one.
First, the local debugging issue. So, to enable CORS in your Azure Functions project, from within Visual Studio go to localsettings.json file within your project and add an entry for CORS like shown below -
1 2 3 4 5 6 7 8 9 10 11 | { "IsEncrypted": false, "Values": { "AzureWebJobsStorage": "UseDevelopmentStorage=true", "FUNCTIONS_WORKER_RUNTIME": "dotnet" }, "Host": { "LocalHttpPort": 7079, "CORS": "*" } } |
Now, if you restart the Azure Function by pressing F5, and click on the Test Azure Function again, you should see the output returned by Azure Function being displayed in the UI, and no error this time in the browser console window -
So we have successfully enabled CORS in our Azure Function via localsettings.json file and this will take care of the local debugging scenario that we were talking about.
Now about the deployed version of Azure Function on Azure, you need to follow below steps to enable CORS there -
- Navigate to your Function App in Azure
- Go to Platform Features -> CORS
- Then in the Allowed Origins section, add all your origin URLs that will be calling your Azure Function. To enable all origins, just enter * there.
- Save and restart your Function App.
That it, this will take care of CORS for your deployed Function App in Azure now.
- Run Azure Functions Locally on a different Port
Often people encounter this issue when the default port used by Azure Functions CLI i.e. 7071 is already used by any other process and when we try to debug Azure Function locally, we get this error-
Port 7071 is unavailable. Close the process using that port, or specify another port using --port [-p].
Now in order to overcome this error, you have two options,
Second option is more easy and straight forward, as we never know if the port 7071 is going to be used again by any other process. Hence here are the simple steps to run Azure Functions on a different port -
Port 7071 is unavailable. Close the process using that port, or specify another port using --port [-p].
Now in order to overcome this error, you have two options,
- Either ensure that the port 7071 is not used by any other process
- Configure your Azure Functions project so that it runs on a different port.
Second option is more easy and straight forward, as we never know if the port 7071 is going to be used again by any other process. Hence here are the simple steps to run Azure Functions on a different port -
- In your localsettings.json, add a entry for LocalHttpPort, and specify the port number that you want your Azure Function to run on.
1 2 3 4 5 6 7 8 9 10 | { "IsEncrypted": false, "Values": { "AzureWebJobsStorage": "UseDevelopmentStorage=true", "FUNCTIONS_WORKER_RUNTIME": "dotnet" }, "Host": { "LocalHttpPort": 7079 } } |
- Go to your Azure Functions project properties, and add below command in Application Arguments section under Debug
host start --pause-on-error
- Now run the Azure Function again by pressing F5 and you will see your Function running on the port specified in localsettings.json file.
- Alternatively, you can just specify the port number in the Application arguments like below, and you don't have to add anything in localsettings.json file.
host start --pause-on-error --port 5860
- An interesting point to notice here is that if you specify the port in both places - in localsettings.json and in Application Arguments also, then your Application Arguments will take precedence and your Azure Function will run on the port number specified in the Application Arguments itself. This can be an interview question though, right ? 😃😃
- Debug Timer Triggered Azure Functions
Debugging Timer Triggered Azure Functions can be a little tricky, as unlike HTTP or Service Bus Triggered Azure Functions, you can't really invoke them via a Request or Message. However with the right knowledge, you can Debug Timer Triggered Azure Functions as well in a really simple way.Let's say our Timer Triggered Azure Function looks like this -
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | using System; using Microsoft.Azure.WebJobs; using Microsoft.Extensions.Logging; namespace FunctionApp1 { public static class Function1 { [FunctionName("Function1")] public static void Run([TimerTrigger("0 */5 * * * *")]TimerInfo myTimer, ILogger log) { log.LogInformation($"C# Timer trigger function executed at: {DateTime.Now}"); } } } |
So our NCRONTAB Expression for Timer Trigger is 0 */5 * * * * this tells Functions CLI that the Azure Function should run every 5 minutes. You can read more about NCRONTAB Expressions here.
Now if you run this Azure Function by pressing F5, you will see that Functions CLI automatically detects your NCRONTAB expression, and also list down the next 5 schedules of your Function run in the CLI command window -
Now you can either wait for the schedule to see the break point being hit, or add the RunOnStartup attribute to your Function method. This attribute ensures that whenever you run your Azure Function locally, your debug point will hit. Basically it does what its name suggests, it runs your Function Code on startup. 🙂
So, your Function Class should look like this after adding the RunOnStartup attribute -
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | using System; using Microsoft.Azure.WebJobs; using Microsoft.Extensions.Logging; namespace FunctionApp1 { public static class Function1 { [FunctionName("Function1")] public static void Run([TimerTrigger("0 */5 * * * *", RunOnStartup = true)]TimerInfo myTimer, ILogger log) { log.LogInformation($"C# Timer trigger function executed at: {DateTime.Now}"); } } } |
Now if you run your Azure Function by pressing F5, you will see your break point being hit.
Hope this read was helpful to you.
Happy Learning !! 🙂🙂
Microsoft azure has it own unique features. I am also the learner of Microsoft azure
ReplyDeleteAre you looking to know about azure cloud migration services. This blog provides a completed guide on it. Keep sharing like this informative blog.
ReplyDeleteazure cloud migration services