Is there now a way to set the Trigger Properties(Name/Connection) using the value from Azure App Configuration?.
I added a startup class that reads the data from Azure App Configuration but it seems the trigger set its properties earlier than that, therefore not able to bind the data that came from the app configuration.
I also found this thread about it but im not sure if there is a new update?:
https://github.com/MicrosoftDocs/azure-docs/issues/63419
https://github.com/Azure/AppConfiguration/issues/203
You can do this. The following code gets the name of the queue to monitor from an app setting, and it gets the queue message creation time in the insertionTime parameter:
public static class BindingExpressionsExample
{
[FunctionName("LogQueueMessage")]
public static void Run(
[QueueTrigger("%queueappsetting%")] string myQueueItem,
DateTimeOffset insertionTime,
ILogger log)
{
log.LogInformation($"Message content: {myQueueItem}");
log.LogInformation($"Created at: {insertionTime}");
}
}
Similarly, you can use this approach for other triggers.
Related
I am following on a possible upgrade of azure function runtime from v3 to v4 with dotnet. While doing so, I am testing out the isolated option for the project. However I am unable to get message metadata such as DequeueCount, MessageId etc in the queue trigger.
Previously with in-process option, I used to bind CloudQueueMessage but that doesn't seem to work in the isolated mode. Doing so, throws and error -
Cannot convert input parameter 'myQueueItem' to type 'Microsoft.WindowsAzure.Storage.Queue.CloudQueueMessage' from type 'System.String'
This was my isolated queue function binding
[Function("TestApp")]
public void Run([QueueTrigger("sample-queue", Connection = "")] CloudQueueMessage myQueueItem, FunctionContext context)
After looking for a while, I think here it says that, in isolated process we can only bind string. Simple JSON - Object also works.
Is there any way to get these message metadata (members of the CloudQueueMessage) in the isolated azure function?
Thanks.
For DequeueCount property I use this:
[Function("MyQueueTrigger")]
public void Run([QueueTrigger("my-queue-name")] string myQueueItem, int dequeueCount)
{
_logger.LogInformation("Queue item: {item}. Dequeue count: {dequeueCount}.", myQueueItem, dequeueCount);
}
I have a console application which I want to convert to an Azure Function Timer Trigger app which will run every hour after some data processing and uploads are done. The data processing and uploads are being done via classes which are injected in the program.cs file of the console application. Somewhere in the classes I have a task.delay by 1hour where it will query new data after the data has been queried and uploaded for the first time. So, I copied the entire code of the console application with its packages to the Azure Function Timer trigger app. What I am trying to do is to run the program.cs file of the console application first in the azure function app in order to do its job (data processing, querying data, uploading data to azure...). and then initiate the timer trigger. Is that doable ? What line of code can I add in the run method of the azure function app to execute the program.cs file first and then initiate the trigger. You can find here the startup code of the azure function time trigger app.
using System;
using Microsoft.Azure.WebJobs;
using Microsoft.Extensions.Logging;
namespace ExportServiceFunctionApp
{
public static class ExportServiceFunctionApp
{
[FunctionName("ExportServiceFunctionApp")]
public static void Run([TimerTrigger("0 0 */1 * * * ")]TimerInfo myTimer, ILogger log)
{
log.LogInformation($"C# Timer trigger function executed at: {DateTime.Now}");
}
}
}
There are a few solutions to achieve this.
Solution 1. Temporarily replace the timer trigger with http trigger
While debugging the app we just comment the first line of the original Run function and add an http trigger instead like this:
public static async Task Run([HttpTrigger] Microsoft.AspNetCore.Http.HttpRequest req, ILogger log)
// public static async Task Run([TimerTrigger("0 0 * * * *")] TimerInfo myTimer, ILogger log)
{
// YOUR REGULAR CODE HERE
}
Then when running the app you'll see an endpoint like this:
Just open the endpoint in browser (or postman) and the function will get called.
And right before pushing the code to the repo, just bring back the original Run function and remove the http trigger one.
Solution 2: Add another http trigger that calls the timer function
Add the following function to your app to expose an http trigger.
[FunctionName("Test")]
public static async Task Test([HttpTrigger] Microsoft.AspNetCore.Http.HttpRequest req, ILogger log)
{
Run(null, log);
}
The function basically calls the Run function.
So when you run the app, again you'll get an endpoint from the console that can be used from the browser to trigger the function.
The url will look like this:
http://localhost:7071/api/Test
Azure functions is event driven in nature. If function trigger means the event handled.
Run method of function means that function has triggered and its entry point for it.
If you want any processing or code execution before it you may need to write one more function and perform the steps and then trigger another function of either timer trigger or ant different type.
I've created an Azure Function that retrieves new form inputs from a website, processes them and stores the result in another system by using an API call. I only want to retrieve the form inputs that have not been processed before. This is supported by the website.
I'm reading the timestamp of the most recent form input that has already been processed. This works fine.
I'm using the following function to read the setting from the Azure function environment:
private static string GetEnvironmentVariable(string name)
{
return System.Environment.GetEnvironmentVariable(name, EnvironmentVariableTarget.Process);
}
After I've processed a form input, I store the timestamp of the form with the following function:
private static void SetEnvironmentVariable(string name, string value)
{
System.Environment.SetEnvironmentVariable(name, value, EnvironmentVariableTarget.Process);
}
Everything seems to be working fine. I see in the logs that form inputs don't get processed more than once. However, when I take a look at the environment variables in the Azure dashboard, I can see that the initial value of the variable is still present. This initial value will be used when the environment 'shuts down' and is restarted (e.g. after changing the value of another environment variable).
I've tried to change the target from 'Process' to 'Machine', but this results in access control errors. There are some questions on SO that are related to my issue, but none of them provides me with an answer for my situation.
I would like to know whether:
Environment variables are the / a suited solution for my use case;
If so, how can I prevent that a variable will be reset to its initial value after resetting the Azure environment.
Thanks in advance!
Firstly, the Environment.SetEnvironmentVariable method already worked in your case.
Here is an answer from Hury Shen:
When you set the variable by Environment.SetEnvironmentVariable, it
will not show in application setting. But we can use it by
Environment.GetEnvironmentVariable as expected. Although the solution
you mentioned is not so good, but it can implement your requirement.
The adverse effect is when you restart the function app, the variables
will be lost.
About the target Machine: The environment variable is stored or retrieved from the HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\Session Manager\Environment key in the Windows operating system registry. This value should be used on .NET implementations running on Windows systems only.
One way to achieve but not set inside code:
In App Service, you can set app settings outside of your app code.
Then you can access them in any class using the standard ASP.NET Core
dependency injection pattern:
using Microsoft.Extensions.Configuration;
namespace SomeNamespace
{
public class SomeClass
{
private IConfiguration _configuration;
public SomeClass(IConfiguration configuration)
{
_configuration = configuration;
}
public SomeMethod()
{
// retrieve nested App Service app setting
var myHierarchicalConfig = _configuration["My:Hierarchical:Config:Data"];
// retrieve App Service connection string
var myConnString = _configuration.GetConnectionString("MyDbConnection");
}
}
}
I'm trying to bind to MessageReceiver in an Azure Service Bus Triggered Function.
My goal is to handle dead letter queue messages and complete them.
public static class Function1
{
[FunctionName("Function1")]
public static async Task Run(
[ServiceBusTrigger(
"<topicName>",
"<subscriptionName>/$DeadLetterQueue",
Connection = "connectionstring")]
Message message,
ILogger logger,
MessageReceiver messageReceiver)
{
// TODO: Perform some actions
await messageReceiver.CompleteAsync(message.SystemProperties.LockToken);
}
The problem is that it fails to bind to the MessageReceiver class.
Microsoft.Azure.WebJobs.Host: Error indexing method 'Function1'. Microsoft.Azure.WebJobs.Host: Cannot bind parameter 'receiver' to type MessageReceiver. Make sure the parameter Type is supported by the binding. If you're using binding extensions (e.g. Azure Storage, ServiceBus, Timers, etc.) make sure you've called the registration method for the extension(s) in your startup code (e.g. builder.AddAzureStorage(), builder.AddServiceBus(), builder.AddTimers(), etc.).
Any ideas why the binding fails?
I figured out what was wrong. I was using 'receiver' as parameter name for MessageReceiver. It turned out that the parameter name has to be 'messageReceiver'. The example I was looking at first used 'receiver', so is this maybe something that has changed?
with a very simple Azure Function program, I will test Azure Event Grid. My goal is if a file is uploaded to Storage account, then my Azure function should be triggered and log a message like Hello World. I have this block of code in my Azure Function:
namespace BlobTrigger
{
public static class BlobEventGrid
{
[FunctionName("BlobEventGrid")]
public static void Run([EventGridTrigger]JObject eventGridEvent,
[Blob("{data.url}", Connection = "BlobConnection")] string file,
TraceWriter log)
{
log.Info("Hello World");
}
}
}
I have set my Event grid from this article.
If I upload more than 50 file to my container, and then control the Live Metrics of my Azure Functions I can only see 4 incoming events:
By controlling metrics in event subscription, I see such metrics:
Delivered Events:66
Matched Events: 51
Do you have any Idea, why I only 4 events are tracked by my azure functions?