Introduction
Azure Function is a service that separates Azure Web Job, one of the functions included in Azure App Service, into separate products. Unfortunately, the rich IDE support in Visual Studio is not yet available. In addition, the method published in Microsoft Docs is also referred to as using the Azure Function setting indirectly or utilizing the CLI for Node.
My intention is to use Visual Studio’s console project and the Azure Storage Emulator. It is about developing and testing C# Azure Function as a normal C# Compiler-based project, not C# Script, and migrating it to C# Azure Function. If you are purchasing and using the LINQPAD Premium Version, you can do the same in LINQPAD, so you will be able to develop Azure Function more actively.
Getting Started
Because Azure Function is based on Azure Web Job, there is some compatibility between Azure Function and Web Job SDK which was originally released for .NET. In other words, rather than writing something new with C# scripts, it’s more like the nature of an Azure function that you packaged your existing SDK for use in C# scripts. Unfortunately, it’s not exactly the same code base, but there is an advantage to be able to do because of compatibility, and that’s part of it.
To begin, check that the following software stack is installed:
- Azure Storage Emulator (included in the Azure Cloud Service SDK)
- Visual Studio 2015 or later
- .NET Framework 4.6 or later
If your environment is not Windows development environment, Azure Storage Emulator is not provided. In this case, you will inevitably have to create and connect the actual Azure Storage account. For the IDE, you can use Visual Studio Code, Visual Studio for Mac, or Rider instead. And you can install Mono to proceed with development. Unfortunately, .NET Core is not supported as of April 2017.
Create a console project with your preferred IDE, then install the following NuGet packages:
Microsoft.Azure.WebJobs
(2.0.0+) Microsoft.Azure.WebJobs.Extensions
(2.0.0+)
Using the Code
Then code the Main
method as follows:
var jobHostConfig = new JobHostConfiguration("UseDevelopmentStorage=true");
jobHostConfig.UseCore();
jobHostConfig.UseFiles();
jobHostConfig.UseTimers();
jobHostConfig.UseDevelopmentSettings();
using (var cts = new CancellationTokenSource())
using (var jobHost = new JobHost(jobHostConfig))
{
jobHost.StartAsync(cts.Token);
Console.WriteLine("Press Ctrl + C to stop the service.");
Console.CancelKeyPress += (s, e) => cts.Cancel();
cts.Token.WaitHandle.WaitOne(Timeout.Infinite);
}
In Windows environment that can use the Local Azure Storage Emulator, specify the “UseDevelopmentStorage=true
” connection string. In other environments, the connection string of the actual Azure Storage Account must be found and assigned on the property blade.
Then, code the function you want to host in the Azure function as follows:
public static void Run(
[TimerTrigger("* * * * * *", UseMonitor = true)]
TimerInfo myTimer,
TraceWriter log)
{
log.Info($"C# Timer trigger function executed at: {DateTime.Now}");
}
Note that the TimerTrigger
is specified in the TimerInfo
method argument. The first argument to TimerTrigger
indicates the interval at which the timer runs. It is recommended that you learn the grammar because it is convenient to migrate to Azure Function by configuring to specify the value by referring to the repeat interval display syntax used in Crontab.
To check if it is running well, start the Azure Storage Emulator and press F5 to run the sample program. If the output is similar to the following, it is normal.
Press Ctrl + C to stop the service.
Development settings applied
Found the following functions:
TimerSample.Run
Singleton lock acquired (1ce1ebaf1e584866b90488a9e1b5d19f/TimerSample.Run.Listener)
The next 5 occurrences of the schedule will be:
2017-04-24 AM 12:16:59
2017-04-24 AM 12:17:00
2017-04-24 AM 12:17:01
2017-04-24 AM 12:17:02
2017-04-24 AM 12:17:03
Job host started
Executing 'TimerSample.Run' (Reason='Timer fired at 2017-04-24T00:16:59.0273081+09:00', Id=aa02dc0a-5a89-4ebd-bf08-8182cce53a0c)
C# Timer trigger function executed at: 2017-04-24 AM 12:16:59
Executed 'TimerSample.Run' (Succeeded, Id=aa02dc0a-5a89-4ebd-bf08-8182cce53a0c)
Executing 'TimerSample.Run' (Reason='Timer fired at 2017-04-24T00:17:00.0061625+09:00', Id=f8161e5d-c989-4d2d-9a49-cb5d9d269134)
C# Timer trigger function executed at: 2017-04-24 AM 12:17:00
Executed 'TimerSample.Run' (Succeeded, Id=f8161e5d-c989-4d2d-9a49-cb5d9d269134)
Migration
There is one useful service that you can use to check if this Azure function is really doing well. Try Azure App Service allows you to sign in with a Google (GMAIL), Facebook, or Github account in addition to your Microsoft account to get a one-hour test Azure Function account, regardless of your actual Microsoft Azure subscription.
Visit https://azure.microsoft.com/en-us/try/app-service/ to create a new account.
Next, copy the code for the Run
method above. However, there are some parts to be corrected or confirmed before some copying.
- You must specify a reference to the NuGet package referenced during development. The project.json file is not created by default, so you need to create the following skeleton and copy the contents of the package.config file in the project you are currently developing into. Except for the packages that are automatically installed depending on the dependency, you can specify only those packages that you actually added.
{
"frameworks": {
"net46":{
"dependencies": {
"Microsoft.ProjectOxford.Face": "1.1.0"
}
}
}
}
- If you refer to an assembly or individual .NET DLL file in the BCL rather than in the NuGet package, use the
#r
directive, which is unique to C # scripts, to specify a reference.
- The .NET DLL files installed in the GAC or separately referenced manually must be uploaded directly to the bin folder.
- It cannot be used if it is a DLL that is explicitly built for x86, or when it requires operations such as system registry changes during preparation and use.
- Before you move the function, check that the method name and signature are the same as when you first created the Azure function. If it does not run normally, refer to the function.json file.
{
"disabled": false,
"bindings": [
{
"name": "myTimer",
"type": "timerTrigger",
"direction": "in",
"schedule": "0 */5 * * * *"
}
]
}
- Lastly, check the value of the argument specified in the trigger, such as
TimerTrigger
, BlobTrigger
, or ServiceBusTrigger
, and modify the function.json file. In the example above, we set it to run every second, so we need to change the schedule property of function.json to “* * * * * *
”.
Wrapping-up
You can freely distribute the final version of the CSX file created as a result with the actual Azure Function service. For continuous development, it might be more convenient to set it up to distribute through the version control repository.
Here are some of the things that I think I might have a little more worrying about as I write this article:
Supplement to HTTP Triggers
HTTP Trigger is a unique function that exists only in Function. It differs from existing Web Job based development method. It is provided as an output function that waits for HTTP requests and returns an HTTP response. Unfortunately, the Azure function only supports output for HTTP responses, and as of May 2017, it does not support output that invokes Web Invocation from somewhere else.
The method I introduced in this article is about local development of triggers that indirectly call a function in conjunction with several Azure components.
If you need to develop based on HTTP triggers that can be called directly, rather than in the form of Web Jobs, refer to Justin Yoo’s article and develop Azure Function App as an ASP.NET Web Project and publish it to Function App It is recommended to choose.
For more information, please visit http://blog.aliencube.org/en/2017/04/30/precompiled-azure-functions-revisited/.
It would be very helpful if you could give me some more details, a part to supplement, or a part to fix.
History
- 6th May, 2017 - First edition