Azure Function V1 with WPF Controls - c#

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.

Related

Is Azure storage supported in Azure Static Web App functions?

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.

Does the Azure service bus client automatically use a retries for transient errors returned from the service bus?

I have a very simple Azure function that uses an Http Trigger to send messages to an Azure Service Bus topic. I want to retry this function if the service bus returns a transient error. I have reviewed the default policy, but I don't know how to verify if it will be used out of the box. Do I need to add anything to my function code to ensure that such a retry policy will be used?
I also want to log messages that fail to be loaded onto the service bus after the retry policy fails. Should I wrap the contents of the function in a try-catch block and perform the log in the catch statement?
[FunctionName("MessageLoader")]
[return: ServiceBus("%Topic_Name%", Connection = "Topic_Connection")]
public static async Task<TopicMessage> Run(
[HttpTrigger(AuthorizationLevel.Function, "get", "post", Route = "domain/load-message")] HttpRequestMessage req)
{
var stringRequestBody = await req.Content.ReadAsStringAsync();
return JsonConvert.DeserializeObject<TopicMessage>(stringRequestBody);
}
Yes, in this case (Service Bus binding), the default retry policy is used. You do not need to do anything special. To verify if it's working, you should see failed dependencies in app insights whenever a call fails if you integrated it correctly.
To your second question, if it fails after the retry gives up, you do not need to log manually. You should see error logged in app insights automatically captured if you integrated it correctly.
If you want to log custom error on failure, you should use Servicebus message sender by creating it yourself instead of Function output binding.

What is the simplest way to run a timer-triggered Azure Function locally once?

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.

Calling WCF service functions on a windows 8 mobile app

I'm trying to call functions that are on the WCF service from a windows 8 phone app, but the only options I get have Async and Completed at the end. e.g. CustLogin appears as CustLoginAsync and CustLoginCompleted.
When I use functions with Async they are interpreted as Void even though they are not void in the WCF service
isn't there a way to call these functions normally?
Maybe you should get parameters from CustLoginCompleted method.
For example: e.Result...
I hope it will help.
It looks like you generate service reference automatically with Visual Studio and async methods are generated automatically. You can disable this behavior in:
Add Service Reference -> Advanced -> Disable allow generation of async operations. If you don't need them then disable them. Otherwise you should read about how to receive a result from async operations in c#.

Running a repeating task in an ASP.NET MVC website

I'm working on an ASP.NET MVC application where I need to keep updating a file in a time-interval. I will eventually be hosting this website on Windows Azure.
I was just wondering if the approach mentioned in Phil Haack's post
The Dangers of Implementing Recurring Background Tasks In ASP.NET is still the best approach or if I should look into creating a console app or so and use Azure Web Jobs to run it?
Any thoughts appreciated.
Thanks,
Daniel
You can do something like this:
private void AddHourlyTask(string task)
{
DateTime expiration = DateTime.Now.AddHours(1);
expiration = new DateTime(expiration.Year, expiration.Month, expiration.Day, expiration.Hour, expiration.Minute, expiration.Second, expiration.Kind);
OnCacheRemove = new CacheItemRemovedCallback(CacheItemRemoved);
HttpRuntime.Cache.Insert(
task,
task,
null,
expiration,
Cache.NoSlidingExpiration,
CacheItemPriority.NotRemovable,
OnCacheRemove);
}
And then in a separate function:
public void CacheItemRemoved(string k, object v, CacheItemRemovedReason r)
{
if (k == "HelloWorld")
{
Console.Write("Hello, World!");
AddHourlyTask(k);
}
This would go into your Application_Start() function as:
AddHourlyTask("HelloWorld");
In order for this to work, you also need to add this somewhere in your class:
private static CacheItemRemovedCallback OnCacheRemove = null;
The functions would all sit in your Global.asax.cs file
You might look at scheduling a simple console app, batch file, perl script, etc. with the windows task scheduler. Depending on what it needs to do, it could be as simple as invoking a web method in your ASP.Net MVC web app.
One option is looking into Quartz.
Quartz.NET is a full-featured, open source job scheduling system that can be used from smallest apps to large scale enterprise systems.
I asked a similar question on Programmers: How do I make my ASP.NET application take an action based on time?
Accepted Answer:
A scheduled task triggered by either the Task Scheduler or Sql Server is the way to go here. But if you really want to manage it within your webapp, you might want to look at something like Quartz.NET. It will let you do scheduled tasks from the CLR. Then your challenge is "how do I make sure the AppDomain stays up to run the tasks."
Another way to do it as a scheduled task yet keep most of the "smarts" on the server is to make it a task that can be called over HTTP with some sort of authorization key. This lets you write a relatively simple program to call it -- if not a simple shell script -- and to keep most of the complexity in the web app which is likely already capable of running the task.
Either way rolling your own task manager is really a path fraught with peril.
Scheduling tasks in an ASP.NET MVC project is possible using the Revalee open source project.
Revalee is a service that allows you to schedule web callbacks to your web application). In your case, you would schedule a callback that would perform your desired action (i.e., update a file). Revalee works very well with tasks that are discrete transactional actions, like updating a database value or sending an automated email message (read: not long running). The code to perform your action would all reside within your MVC app. When your application launches for the very first time, then you would schedule the first web callback. When your application is called back to generate the report, then you would schedule the next callback.
To use Revalee, you would:
Install the Revalee Service, a Windows Service, on your server. The Windows Service is available in the source code (which you would compile yourself) or in a precompiled version available at the Revalee website.
Use the MVC-specific Revalee client library in your Visual Studio project. (There is a non-MVC version too.) The client library is available in the source code (which, again, you would compile yourself) or in a precompiled version available via NuGet.
You would register a future callback when your application launches for the very first time via the ScheduleHourlyCallback() method (this example is assuming that you need your action to run once per hour).
private void ScheduleHourlyCallback()
{
// Schedule your callback for an hour from now
var callbackTime = DateTimeOffset.Now.AddHours(1.0);
// Your web app's Uri, including any query string parameters your app might need
Uri callbackUrl = new Uri("http://yourwebapp.com/Callback/UpdateFile");
// Register the callback request with the Revalee service
RevaleeRegistrar.ScheduleCallback(callbackTime, callbackUrl);
}
When Revalee calls your application back, your app would perform whatever action you have coded it to do and your app schedules the next callback too (by calling the ScheduleHourlyCallback() method from within your controller's action).
I hope this helps.
Note: The code example above uses a synchronous version of ScheduleCallback(), the Revalee client library also supports asynchronous calls à la:
RevaleeRegistrar.ScheduleCallbackAsync(callbackTime, callbackUrl);
Disclaimer: I was one of the developers involved with the Revalee project. To be clear, however, Revalee is free, open source software. The source code is available on GitHub.

Categories