I'm working on an API for an Azure Static Web App. The web app is implemented in Angular (although that isn't important for this question), and the API is implemented in C# (NET 6). Deployment to Azure is via a GitHub action.
I can create an HTTP trigger API endpoint that works fine, like so:
public static class Tester
{
[FunctionName("Tester")]
public static IActionResult Run(
[HttpTrigger(AuthorizationLevel.Anonymous, "get", Route = "v1/tester")] HttpRequest req,
ILogger log)
{
return new OkObjectResult("Hello World");
}
}
I'm also able to access this directly via the SWA URL: https://<sitename>.azurestaticapps.net/api/v1/tester.
However, as soon as I add a reference to an Azure storage NuGet package to the project file (specifically Microsoft.Azure.WebJobs.Extensions.Storage.Blobs), making no other changes to the code, the API endpoint no longer works once deployed (although it will work locally).
On deploying the code with that package referenced in the .csproj, hitting the API endpoint gives a 503 status code with the response:
Function host is not running.
I enabled Application Insights for this static web app, and a CryptographicException is being thrown on startup:
An error occurred while trying to encrypt the provided data. Refer to the inner exception for more information. For more information go to http://aka.ms/dataprotectionwarning Could not find any recognizable digits.
(The link in the message doesn't go anywhere useful).
I'm presuming this has something to do with the AzureWebJobsStorage setting, which cannot be set in an Azure Static Web App (for whatever reason).
Based on all of the above, it would seem that using Azure storage from within a static web app C# function is verboten. However, I can't find that stated explicitly online anywhere. Has anybody got this kind of thing to work?
I removed the following nuget packages to make it working:
Microsoft.Azure.EventGrid
Microsoft.Azure.WebJobs.Extensions.EventGrid
I decomposed my http functions to a separate project because SWA does not support the EventTriggers right now.
I've created an Azure Function and hosted it in Azure. It accepts "post" and "get" requests and I can run this locally and get some log output when I either GET or POST to it.
When I host this in Azure, I can get the output the same if I do a GET or POST, which is what I expect (via postman).
I'm using a third party tool for a callback to my Azure Function URL. When this callback gets sent, I don't get any output in the Azure CLI for logs. It is using the exact same address as I was using to get my output in the portal.
The third party tool is saying its getting an HTTP 301 response.
Why would the callback be getting an HTTP 301 when I can post/get to the same address from Postman and get a 200 back?
Function code:
[FunctionName("AddressNotification")]
public static async Task<IActionResult> Run(
[HttpTrigger(AuthorizationLevel.Anonymous, "get", "post", Route = null)] HttpRequest req,
ILogger log)
{
log.LogInformation($"Address Callback function hit from req: {req.Host.ToString()}");
var content = await new StreamReader(req.Body).ReadToEndAsync();
log.LogInformation($"Request body: {content}");
return new OkResult();
}
Third party tool saying I'm getting a 301:
I would assume you have https only enabled in your function
I have a REST API built in an Azure function. My PUT endpoints are returning the 202 async pattern, but all other endpoints are returning 200s.
This returns a 200 after updating the user's profile image
public async Task<IActionResult> PutProfileImage(
[HttpTrigger(AuthorizationLevel.Function, "post", Route = "profileimage")] HttpRequest req,
ILogger log)
This returns a 202 Accepted and never completes
[FunctionName("PutProfileImage")]
public async Task<IActionResult> PutProfileImage(
[HttpTrigger(AuthorizationLevel.Function, "put", Route = "profileimage")] HttpRequest req,
ILogger log)
Windows 10, VS 2019 16.9.4, Azure Functions V3, .NET Core 3.1. Happy to gather any more info that might help to understand this behavior.
Update 5/8/2021
This is a known issue being tracked here: https://github.com/Azure/Azure-Functions/issues/1878 and here https://github.com/Azure/azure-functions-host/issues/7260
If anyone else finds this, it's a known issue in the Azure Functions runtime. The issue being tracked here: https://github.com/Azure/Azure-Functions/issues/1878 and here https://github.com/Azure/azure-functions-host/issues/7260
I tried to use Azure function v1 that contains some WPF controls. while Azure funtion v1 supports .Net framework, and it is supposed to work with windows environment. whenever the debugger reaches the WPF control, exception is being thrown shows that
"InvalidOperationException: The calling thread must be STA, because many UI components require this.
"
This is how my code looks like, I tested the function within browser.
[FunctionName("Report1")]
public static async Task<HttpResponseMessage> RunReport([HttpTrigger(AuthorizationLevel.Anonymous, "get", "post", Route = "hash/{hash1}")]HttpRequestMessage req, string hash1, TraceWriter log, Microsoft.Azure.WebJobs.ExecutionContext context){}
Dont have this usage method, Azure Function does not support UI. WPF controls should not be handled in Azure Functions.
I have a few C# Azure Functions that run on a schedule using timer triggers. I've set them up like so, where %TimerSchedule% refers to a cron expression in the app settings:
public static void Run([TimerTrigger("%TimerSchedule%")]TimerInfo myTimer, TraceWriter log)
During development, I often want to run the functions locally using Azure Functions Tools for Visual Studio + Azure Functions Core Tools. But when I hit F5 to debug the function locally it (usually) doesn't run immediately. Instead, it starts waiting for the next occurrence as per the timer schedule. So for example, if my cron expression says to run daily at 8PM, I'd have to wait until 8PM for the function to actually run on my machine.
So my question is: What is the simplest and best way to make a function run once locally?
Things I have tried or considered:
Use a more frequent timer schedule just for local development
This is OK but not perfect – you still have to wait a little bit unless it's very frequent, and if it's very frequent then the function might run multiple times. This is what I'm doing now.
Write a console app or unit test that directly calls the function's Run() method
This isn't 100% straightforward because you have to provide TimerInfo and TraceWriter arguments to Run() – and I've found surprisingly little documentation for that.
Microsoft's Strategies for testing your code in Azure Functions page is not very helpful on this topic – it only mentions timer triggers as a way to test other trigger types.
In a perfect world, I'd hit F5 and the function would immediately run once – just like developing a "normal" .NET app.
I had the same question, and used the DEBUG-flag to have the RunOnStartup only while debugging:
public static void Run(
[TimerTrigger("* 0 7 * * 1-5"
#if DEBUG
, RunOnStartup=true
#endif
)]TimerInfo myTimer, TraceWriter log)
{
You could perhaps use the RunOnStartup flag as documented here. It doesn't quite meet your brief regarding it only running once, but it should at least execute it locally once the app has started.
/// Gets or sets a value indicating whether the function should be invoked
/// immediately on startup. After the initial startup run, the function will
/// be run on schedule thereafter.
Example using attribute binding:
[TimerTrigger("%TimerSchedule%", RunOnStartup = true)]TimerInfo myTimer
From https://learn.microsoft.com/en-us/azure/azure-functions/functions-run-local?tabs=windows%2Ccsharp%2Cbash#non-http-triggered-functions
Non-HTTP triggered functions
For all kinds of functions other than HTTP triggers and webhooks, you can test your functions locally by calling an administration endpoint. Calling this endpoint with an HTTP POST request on the local server triggers the function. You can optionally pass test data to the execution in the body of the POST request. This functionality is similar to the Test tab in the Azure portal.
You call the following administrator endpoint to trigger non-HTTP functions:
http://localhost:{port}/admin/functions/{function_name}
To pass test data to the administrator endpoint of a function, you must supply the data in the body of a POST request message. The message body is required to have the following JSON format:
{
"input": "<trigger_input>"
}
If you are using VS Code, use the Azure Functions extension:
Hit F5 to enter debug mode, this starts the function app.
Go to the Azure icon in the Activity bar.
Under Local Project, find the function you want to run, right click, and select "Execute Function Now".
Check out this MS quickstart guide.
Using postman should do the trick. Follow the below steps to Run or debug you Timer Trigger Locally.
1 . RUN your Project.
Open Postman and past this url http://localhost:{port}/admin/functions/{function_name}
Make sure to use a POST Method with Json body of
{
"input": ""
}
Press SEND.
You Should receive a response of 202.
I had the same question. I fixed it with a Unittest.
Indeed you need to stub out the TraceWriter and the TimerInfo.
Here some code how I did this.
TimerInfo:
public class ScheduleStub : TimerInfo
{
public ScheduleStub(TimerSchedule schedule, ScheduleStatus status, bool isPastDue = false) : base(schedule, status, isPastDue)
{
}
}
And the TraceWriter:
public class TraceWriterStub : TraceWriter
{
protected TraceLevel _level;
protected List<TraceEvent> _traces;
public TraceWriterStub(TraceLevel level) : base(level)
{
_level = level;
_traces = new List<TraceEvent>();
}
public override void Trace(TraceEvent traceEvent)
{
_traces.Add(traceEvent);
}
public List<TraceEvent> Traces => _traces;
}
Start your function with this curl command
curl --request POST -H "Content-Type:application/json" --data '{"input":""}' http://localhost:7071/admin/functions/{function_name}
The input data is required, without it the function won't be triggered.
Another approach is to trigger manually the function from Postman:
Manually run a non HTTP-triggered function.
POST /admin/functions/<function name> HTTP/1.1
Host: localhost:<port>
Content-Type: application/json
{}
For me, it looks like that on postman for a timerTrigger function called Function1:
Just add another function with HTTP trigger type within the same class, add your code, or call your Run method from that function and invoke it from your browser.
Be sure to comment/remove that function when deployed to prod, or you will have the ability to trigger the function via HTTP calls in prod.