-
Notifications
You must be signed in to change notification settings - Fork 54
(Insider Preview) New Programming Model
The v2 programming model is designed to provide a development experience that is more familiar to PowerShell developers. The new programming model is currently not released, and timeline is TBD. You can use the following guidance to learn more about it, and test out a private local version.
Note that leveraging the v2 programming model will provide an improved and seamless way to create functions, with the underlying deployment, debugging, and monitoring experience remaining the same.
- General Notes
- Supported Today
- Examples
- Get Started
-
The only files that are scanned for functions are the ones in the function app root folder. Any other files may be used to contain helper functions, but function declarations must be at the root. EXAMPLE: bug-bash-app/functions.psm1 is scanned, but bug-bash-app/src/functions.psm1 will not be
-
For the binding attributes, only named arguments are supported. Positional arguments will not work.
Comparing the v1 and v2 programming models
v1
function StripForPs1Example {
[Function()]
param(
[HttpTrigger()]
$Request,
$TriggerMetadata
)
$value = ([HttpResponseContext]@{
StatusCode = [HttpStatusCode]::OK
Body = 'New Programming Model rules! (Hero executed)'
})
$value | Push-OutputBinding -Name Response
}
run.ps1
using namespace System.Net
# Input bindings are passed in via param block.
param($Request, $TriggerMetadata)
# Write to the Azure Functions log stream.
Write-Host "PowerShell HTTP trigger function processed a request."
$body = "Hello from PowerShell v1 programming model"
# Associate values to output bindings by calling 'Push-OutputBinding'.
Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{
StatusCode = [HttpStatusCode]::OK
Body = $body
})
function.json
{
"bindings": [
{
"authLevel": "function",
"type": "httpTrigger",
"direction": "in",
"name": "Request",
"methods": [
"get",
"post"
]
},
{
"type": "http",
"direction": "out",
"name": "Response"
}
]
}
v2
[Function()]
param(
[HttpTrigger()]
$Request,
$TriggerMetadata
)
$value = ([HttpResponseContext]@{
StatusCode = [HttpStatusCode]::OK
Body = 'New Programming Model rules! (Hero executed)'
})
$value | Push-OutputBinding -Name Response
Comparing the folder structure of v1 and v2:
The following is the folder structure for a function application containing three functions.
v1
- .vscode
- EventGridTrigger1
- function.json
- run.ps1
- HttpTrigger1
- function.json
- run.ps1
- TimerTrigger1
- function.json
- run.ps1
- .funcignore
- .gitignore
- host.json
- local.settings.json
- profile.ps1
- requirements.psd1
v2
- .vsode
- .funcignore
- .gitignore
- functions.ps1
- host.json
- local.settings.json
- profile.ps1
- requirements.psd1
As you can see, the folder structure of a function application using the v2 programming model is simpler and flat.
Triggers:
- HTTP
- Timer
- EventGrid
- EventHub
- Orchestration
- Activity
Output Bindings:
- HTTP
- EventHub
DurableClient is also supported!
You can also use a combination of InputBinding
, OutputBinding
, and AdditionalInformation
to construct bindings of any other type. InputBinding
and OutputBinding
should be used to specify the type of binding, and AdditionalInformation
allows you to add key-value pairs to that binding.
HTTP Trigger
using namespace System.Net
using module AzureFunctions.PowerShell.SDK
function HttpTriggerMinimal {
[Function()]
param(
[HttpTrigger()]
$Request,
$TriggerMetadata
)
$value = ([HttpResponseContext]@{
StatusCode = [HttpStatusCode]::OK
Body = 'New Programming Model rules! (Hero executed)'
})
$value | Push-OutputBinding -Name Response
}
function HttpTriggerMaximal {
[Function(Name='Trig')]
[HttpOutput(Name='Resp')]
param(
[HttpTrigger(AuthLevel='anonymous', Methods=('Get', 'Post'), Route='rerouted')]
$Request,
$TriggerMetadata
)
$value = ([HttpResponseContext]@{
StatusCode = [HttpStatusCode]::OK
Body = 'The Http trigger invocation was successful'
})
$value | Push-OutputBinding -Name Resp
}
Timer Trigger:
function TimerTriggerMinimal {
# Input bindings are passed in via param block.
param(
[TimerTrigger(Chron='0 */5 * * * *')]
$Timer
)
# Get the current universal time in the default string format
$currentUTCtime = (Get-Date).ToUniversalTime()
# The 'IsPastDue' property is 'true' when the current function invocation is later than scheduled.
if ($Timer.IsPastDue) {
Write-Host "PowerShell timer is running late!"
}
# Write an information log with the current time.
Write-Host "PowerShell timer trigger function ran! TIME: $currentUTCtime"
}
EventGrid
function EventGridTrigger() {
[Function()]
param(
[EventGridTrigger()]
$Request,
$TriggerMetadata
)
$value = ([HttpResponseContext]@{
StatusCode = [HttpStatusCode]::OK
Body = 'The Http trigger invocation was successful'
})
$value | Push-OutputBinding -Name Response
}
EventHub
# NOTE: all 4 arguments are required.
function EventHubTrigger() {
[Function()]
param(
[EventHubTrigger(EventHubName='', ConsumerGroup='', Cardinality='', Connection='')]
$Request,
$TriggerMetadata
)
$value = ([HttpResponseContext]@{
StatusCode = [HttpStatusCode]::OK
Body = 'The Http trigger invocation was successful'
})
$value | Push-OutputBinding -Name Response
}
# HttpOutput syntax:
# [HttpOutput(Name='<name>')]
# EventHubOutput syntax:
# [EventHubOutput(Name='<binding name>', EventHubName='<event hub name>', Connection='<event hub connection>')]
Durable
function DurableFunctionsHttpStart1 {
[Function()]
param(
[DurableClient(Name='starter')]
[HttpTrigger(AuthLevel='anonymous', Methods=('get', 'post'), Route='DurableStart')]
$Request,
$TriggerMetadata
)
$FunctionName = "DurableFunctionsOrchestrator1"
$InstanceId = Start-DurableOrchestration -FunctionName $FunctionName
Write-Host "Started orchestration with ID = '$InstanceId'"
$Response = New-DurableOrchestrationCheckStatusResponse -Request $Request -InstanceId $InstanceId
Push-OutputBinding -Name Response -Value $Response
}
function DurableFunctionsOrchestrator1 {
[Function()]
param(
[OrchestrationTrigger()]
$Context
)
$output = @()
$output += Invoke-DurableActivity -FunctionName 'Hello1' -Input 'Tokyo'
$output += Invoke-DurableActivity -FunctionName 'Hello1' -Input 'Seattle'
$output += Invoke-DurableActivity -FunctionName 'Hello1' -Input 'London'
$output
}
function Hello1 {
[Function()]
param(
[ActivityTrigger()]
$name
)
"Hello $name!"
}
Generic Binding Syntax Following is an HTTP trigger written in the style of the generic, but use your imagination!
function GenericTrigger() {
[Function()]
[OutputBinding(Type='http', Name='Response')]
[AdditionalInformation(BindingName='', Name='', Value='')]
param(
[InputBinding(Type='httpTrigger')]
[AdditionalInformation(BindingName='Request', Name='authLevel', Value='anonymous')]
[AdditionalInformation(BindingName='Request', Name='methods', Value=('GET', 'POST'))]
$Request,
$TriggerMetadata
)
}