Dapr Invoke output binding for Azure Functions

The Dapr invoke output binding allows you to invoke another Dapr application during a function execution.

For information on setup and configuration details of the Dapr extension, see the Dapr extension overview.

Example

A C# function can be created using one of the following C# modes:

Execution model Description
Isolated worker model Your function code runs in a separate .NET worker process. Use with supported versions of .NET and .NET Framework. To learn more, see Develop .NET isolated worker process functions.
In-process model Your function code runs in the same process as the Functions host process. Supports only Long Term Support (LTS) versions of .NET. To learn more, see Develop .NET class library functions.

The following example demonstrates using a Dapr invoke output binding to perform a Dapr service invocation operation hosted in another Dapr-ized application. In this example, the function acts like a proxy.

[FunctionName("InvokeOutputBinding")]
public static async Task<IActionResult> Run(
    [HttpTrigger(AuthorizationLevel.Function, "get", Route = "invoke/{appId}/{methodName}")] HttpRequest req,
    [DaprInvoke(AppId = "{appId}", MethodName = "{methodName}", HttpVerb = "post")] IAsyncCollector<InvokeMethodParameters> output,
    ILogger log)
{
    log.LogInformation("C# HTTP trigger function processed a request.");

    string requestBody = await new StreamReader(req.Body).ReadToEndAsync();

    var outputContent = new InvokeMethodParameters
    {
        Body = requestBody
    };

    await output.AddAsync(outputContent);

    return new OkResult();
}

The following example creates a "InvokeOutputBinding" function using the DaprInvokeOutput binding with an HttpTrigger:

@FunctionName("InvokeOutputBinding")
public String run(
        @HttpTrigger(
            name = "req",
            methods = {HttpMethod.GET, HttpMethod.POST},
            authLevel = AuthorizationLevel.ANONYMOUS,
            route = "invoke/{appId}/{methodName}")
            HttpRequestMessage<Optional<String>> request,
        @DaprInvokeOutput(
            appId = "{appId}", 
            methodName = "{methodName}", 
            httpVerb = "post")
        OutputBinding<String> payload,
        final ExecutionContext context)

In the following example, the Dapr invoke output binding is paired with an HTTP trigger, which is registered by the app object:

const { app, trigger } = require('@azure/functions');

app.generic('InvokeOutputBinding', {
    trigger: trigger.generic({
        type: 'httpTrigger',
        authLevel: 'anonymous',
        methods: ['POST'],
        route: "invoke/{appId}/{methodName}",
        name: "req"
    }),
    return: daprInvokeOutput,
    handler: async (request, context) => {
        context.log("Node HTTP trigger function processed a request.");

        const payload = await request.text();
        context.log(JSON.stringify(payload));

        return { body: payload };
    }
});

The following examples show Dapr triggers in a function.json file and PowerShell code that uses those bindings.

Here's the function.json file for daprInvoke:

{
  "bindings":
    {
      "type": "daprInvoke",
      "direction": "out",
      "appId": "{appId}",
      "methodName": "{methodName}",
      "httpVerb": "post",
      "name": "payload"
    }
}

For more information about function.json file properties, see the Configuration section.

In code:

using namespace System.Net

# Input bindings are passed in via param block.
param($req, $TriggerMetadata)

# Write to the Azure Functions log stream.
Write-Host "Powershell InvokeOutputBinding processed a request."

$req_body = $req.Body

$invoke_output_binding_req_body = @{
    "body" = $req_body
}

# Associate values to output bindings by calling 'Push-OutputBinding'.
Push-OutputBinding -Name payload -Value $invoke_output_binding_req_body

Push-OutputBinding -Name res -Value ([HttpResponseContext]@{
    StatusCode = [HttpStatusCode]::OK
    Body = $req_body
})

The following example shows a Dapr Invoke output binding, which uses the v2 Python programming model. To use daprInvoke in your Python function app code:

import logging
import json
import azure.functions as func

app = func.FunctionApp()

@app.function_name(name="InvokeOutputBinding")
@app.route(route="invoke/{appId}/{methodName}", auth_level=dapp.auth_level.ANONYMOUS)
@app.dapr_invoke_output(arg_name = "payload", app_id = "{appId}", method_name = "{methodName}", http_verb = "post")
def main(req: func.HttpRequest, payload: func.Out[str] ) -> str:
    # request body must be passed this way "{\"body\":{\"value\":{\"key\":\"some value\"}}}" to use the InvokeOutputBinding, all the data must be enclosed in body property.
    logging.info('Python function processed a InvokeOutputBinding request from the Dapr Runtime.')

    body = req.get_body()
    logging.info(body)
    if body is not None:
        payload.set(body)
    else:
        logging.info('req body is none')
    return 'ok'

Attributes

In the in-process model, use the DaprInvoke attribute to define a Dapr invoke output binding, which supports these parameters:

Parameter Description Can be sent via Attribute Can be sent via RequestBody
AppId The Dapr app ID to invoke. ✔️ ✔️
MethodName The method name of the app to invoke. ✔️ ✔️
HttpVerb Optional. HTTP verb to use of the app to invoke. Default is POST. ✔️ ✔️
Body Required. The body of the request. ✔️

Annotations

The DaprInvokeOutput annotation allows you to have your function invoke and listen to an output binding.

Element Description Can be sent via Attribute Can be sent via RequestBody
appId The app ID of the application involved in the invoke binding. ✔️ ✔️
methodName The name of the method variable. ✔️ ✔️
httpVerb Post or get. ✔️ ✔️
body Required. The body of the request. ✔️

Configuration

The following table explains the binding configuration properties that you set in the code.

Property Description Can be sent via Attribute Can be sent via RequestBody
appId The app ID of the application involved in the invoke binding. ✔️ ✔️
methods Post or get. ✔️ ✔️
body Required. The body of the request. ✔️

The following table explains the binding configuration properties that you set in the function.json file.

function.json property Description Can be sent via Attribute Can be sent via RequestBody
appId The app ID of the application involved in the invoke binding. ✔️ ✔️
methodName The name of the method variable. ✔️ ✔️
httpVerb Post or get. ✔️ ✔️
body Required. The body of the request. ✔️

The following table explains the binding configuration properties for @dapp.dapr_invoke_output that you set in your Python code.

Property Description Can be sent via Attribute Can be sent via RequestBody
app_id The app ID of the application involved in the invoke binding. ✔️ ✔️
method_name The name of the method variable. ✔️ ✔️
http_verb Set to post or get. ✔️ ✔️
body Required. The body of the request. ✔️

If properties are defined in both Attributes and RequestBody, priority is given to data provided in RequestBody.

See the Example section for complete examples.

Usage

To use the Dapr service invocation output binding, learn more about how to use Dapr service invocation in the official Dapr documentation.

To use the daprInvoke in Python v2, set up your project with the correct dependencies.

  1. Create and activate a virtual environment.

  2. In your requirements.text file, add the following line:

    azure-functions==1.18.0b3
    
  3. In the terminal, install the Python library.

    pip install -r .\requirements.txt
    
  4. Modify your local.setting.json file with the following configuration:

    "PYTHON_ISOLATE_WORKER_DEPENDENCIES":1
    

Next steps

Learn more about Dapr service invocation.