I have an Azure Function (C#) that is triggered by an Event Grid. I am having difficulty debugging my Function locally as it can only be triggered via the Event Grid.
I'm not sure if there is a way to wire the Event Grid up to my local host address for my Function? I have tried using a Web Hook but it only support HTTPS which my localhost uses HTTP.
public static void Run([EventGridTrigger]EventGridEvent eventGridEvent, ILogger log)
{
ID = eventGridEvent.Subject;
log.LogInformation($"ID: {ID.ToString()}");
}
Any advice is appreciated.
I found this blog post that helped me resolve this when debugging event grid azure function locally: https://blog.mcilreavy.com/articles/2018-12/debug-eventgrid-triggered-azure-function (Web archive link)
One piece that was missing in my case was the aeg-event-type header.
aeg-event-type: Notification
After adding it, I was able to debug locally using this url:
http://localhost:7071/runtime/webhooks/EventGrid?functionName=nameOfYourFunction
And include this event json in the request body, something like this:
[ { "id": "'1", "eventType": "yourEventType", "eventTime":"10:59:00.000", "subject": "subject1", "data":{"make": "Ducati", "model": "Monster"}, "dataVersion": "1.0" } ]
Actually, there is a nice and easy way of doing this using a ngrok as a tunnel. So you basically create a EventGrid Subscription that publishes your events to your ngrok tunnel (e. g. https://ec291dd9.ngrok.io/runtime/webhooks/EventGrid?functionName=myfunc) and start debugging your function in Visual Studio. You don't need to change your function at all.
This approach is also well documented from Microsoft: Azure Function Event Grid Trigger Local Debugging
You're right. At this moment, tooling for Event Grid is being improved and there's no easy way to test it locally.
In my Event Grid Functions, I'm separating the logic from the trigger part, this way I can unit test the logic without the need of a real event in order to test it. After that, I'm capturing the event through Application Insights and a log.LogInformation(eventGridEvent.Data.ToString());
Related
I've implemented an Azure Function (v2 running on .Net Core 2.2) triggered by an HttpTrigger. Upon specifying either the Disable attribute or using the Application Settings ("AzureWebJobs.Function1.Disabled": "true"), I'm still able to hit this endpoint through Postman. This is ONLY happening with HttpTriggers. The ChangeFeed Triggers and QueueTriggers I am also using, are working as expected.
A few things I've tried when running locally:
1. Withing local.settings.json, I've added just the AzureWebJobs..Disabled value
2. I've added the Disable attribute
3. I've added the Disable attribute with a setting defined.
When starting up the function project, the console does show "Function Function1 is disabled."
I've tried it with my local.settings.json as such
{
"IsEncrypted": false,
"Values": {
"AzureWebJobsStorage": "UseDevelopmentStorage=true",
"FUNCTIONS_WORKER_RUNTIME": "dotnet",
"AzureWebJobs.Function1.Disabled": "true"
},
"Host": {
"LocalHttpPort": 7071,
"CORS": "*"
}
}
The Function has a general format as such:
[Disable, FunctionName("Function1")]
public async Task<IActionResult> RunAsync(
[HttpTrigger(AuthorizationLevel.Anonymous, "get")] HttpRequest req,
Binder binder, ILogger log)
{}
I would think I would receive a 404 within Postman. Any thoughts, direction, or other information is appreciated.
I could repro your issue as well. Despite the log saying that the function is disabled, you can still call the HTTP trigger. Looks like a bug to me. I opened an issue on Github here: https://github.com/Azure/azure-functions-host/issues/4764
Update from the github issue:
Does this only happen when running locally with the CLI (or VS)? Http
requests should return 404s unless invoked via an Admin request --
this allows the portal to continue to be able to test functions. When
running via the CLI, though, I believe all requests are treated as
admin requests.
Yes, I can confirm this is indeed different when deployed in Azure.
When I use the app setting there AND use the function key (not the
master key), the call returns 404.
I test local and got the same result as yours, and I found it could not only disable HTTP trigger function, if disable other like Timer function simultaneously, only HTTP could run. But I test with Azure It will respond 404.
So maybe you could use host.json to disable it, actually it should say run functions you want. If you only have only one or want to disable all functions, you could set the array with null string like below code.
{
"functions": [ null ],
"version": "2.0"
}
Or like this to only run Function2 then disable Function1 :
{
"functions": [ "Function2" ],
"version": "2.0"
}
Hope this could help you.
You can also disable by going to the portal:
I'm building as part of a larger process that analyzes the results of the build once it has completed. I used to work with XAML builds via C# code, and I had the following code:
QueuedBuild.Connect();
QueuedBuild.PollingCompleted += PrivateServerBuildRequest.BuildCompleted;
(QueuedBuild was IQueuedBuild type),
With new WebApi builds, do I have an event that let me know that the build has completed?
I found BuildCompletedEvent in Microsoft.TeamFoundation.Build.WebApi.Events but I didn't manage to find the way to use it.
Is there any equivalent to PollingCompleted event in WebApi builds? Something that'll fire once all build results are available?
One of the possible alternatives with the new REST API is to use Service Hooks. In particular, you might want to pay attention to the generic Web Hook, whcih can basically instruct VSTS to POST some JSON payload (once a certain event occurs) to some endpoint.
The endpoint can be anything: your custom home-made service hosted on-prem, OR an Azure Function, for instance. This article can give you an idea how to trigger an Azure Function in response to a VSTS event.
The 'Build Completed' event is in the list of available events.
So, to sum it all up, I would try the following in your case:
Create an Azure Function to accept the build info payload and process it accordingly
Subscribe to Build Completed event with the Web Hook and make sure the Azure Function URL is used as the endpoint
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.
Is there an event raised the moment a website is published and updated?
I've tried Application_End in global.asax but that event does not seem to be raised.
I suggest to use both Kudu and Microsoft ASP.NET WebHooks preview.
Kudu is the engine behind git deployments, WebJobs, and various other features in Azure Web Sites (Kudu source is on GitHub)
With Kudu, Azure Web Sites have a support for web hooks. There is an event "PostDeployment" that will be invoked whenever a deployment is complete with the result of that deployment.
Microsoft ASP.NET WebHooks preview provides a common model for receiving and processing WebHooks from any number of WebHook providers includign support for Kudu (Azure Web App Deployment).
So you may use Kudu WebHooks to get notified when an update has been deployed. (But that will require using Git Deploy instead of other ways to publish your web site).
Here is the way to do it :
First Install the Microsoft.AspNet.WebHooks.Receivers.Azure Nuget package.
The, Add these two lines to the WebApiConfig.Register method:
config.InitializeReceiveKuduWebHooks();
config.InitializeReceiveAzureAlertWebHooks();
Then Add a handler :
public class KuduWebHookHandler : WebHookHandler
{
public KuduWebHookHandler()
{
Receiver = "kudu";
}
public override Task ExecuteAsync(string generator, WebHookHandlerContext context)
{
// Convert to POCO type
KuduNotification notification = context.GetDataOrDefault<KuduNotification>();
// Get the notification message
string message = notification.Message;
// Get the notification author
string author = notification.Author;
return Task.FromResult(true);
}
}
Then configure a secret that can validates that the WebHook requests indeed come from Kudu.
Use high-entropy values such as a SHA256 hash or similar, which you can get from http://www.freeformatter.com/hmac-generator.html. Also, set them through the Azure Portal instead of hard-coding them in the Web.config file
Also, set them through the Azure Portal instead of hard-coding them in the Web.config file.
There is a more complete Post on the subject here (http://blogs.msdn.com/b/webdev/archive/2015/10/04/receive-webhooks-from-azure-alerts-and-kudu-azure-web-app-deployment.aspx)
Hope this helps
Best regards
Stéphane
I figured it out. In the Application_Start event I bind
RoleEnvironment.Stopping += RoleEnvironmentStopping;
private void RoleEnvironmentStopping(object sender, RoleEnvironmentStoppingEventArgs e)
{
// do something ...
}
We´re trying to create a new app for the Bigcommerce app store. We´ve working the install callback url, but the load & uninstall callback seems like it´s not being triggered when clicking on the Uninstall button (or the app icon, for the load callback). We´ve added a log line at the very beginning of the uninstall method, but doesn´t writes anything, so it´s like it´s not being called. The URL is OK (https://www.example.com/UnInstall) and the method is something like this:
public void UnInstall(string signed_payload)
{
Log.Instance.Write("Bigcommerce", "UnInstall", signed_payload);
}
(this code is just a silly example to try to find out if the method is being triggered).
Am I missing something?
Thanks mates!
Probably the issue is that you are using a local domain (not sure about that). But you need to use a public link in the uninstall callback, Maybe you get confused because the install callback can be a local one.
You need to use ngrok to test endpoints because bigcommerce need to "see" you online.
Eg: https://de93d105.ngrok.io/bigcommerce/uninstall
also uninstall callback url need to match with the one in you app technical settings
Auth Callback: loads in BigCommerce iframe
Load Callback: loads in BigCommerce iframe
Uninstall Callback: loads BigCommerce from server-side
For Auth & Load callbacks you can use your local environment. But for Uninstall callback you have to use public url (own domain or ngrok.io).
By the way, no needs to return redirect or any other responses in Uninstall callback. There are no views for user there.