简体   繁体   中英

How do I use a DocumentDB database input binding with a Service Bus trigger binding and BrokeredMessage in Microsoft Azure Functions?

I'm writing a simple function that gets triggered when a new message comes to the Service Bus queue. The input for that function is a DocumentDB document. I need to access a value in the document and type it into the console log.

When you create a Service Bus queue trigger binding, it is automatically created as this:

public static void Run(string myQueueItem, TraceWriter log)
{
    log.Info($"C# ServiceBus queue trigger function processed message: {myQueueItem}");
}

Now to access the correct document in my database, according to this page it is possible to set your bindings so that you get a document ID from your queue message:

id supports bindings similar to {queueTrigger}, which uses the string value of the queue message as the document Id.

That means that you can send a message to the queue and then bind to your document like this:

{
    "name": "inputDocument",
    "type": "documentDB",
    "databaseName": "MyDatabase",
    "collectionName": "MyCollection",
    "id" : "{myQueueItem}",//<<<
    "connection": "MyAccount_DOCUMENTDB",     
    "direction": "in"
}

So far, everything seems to work as intended. However, in order to send a message to the Service Bus queue, you have to send it as a BrokeredMessage type ( link ). And when you do that, you can't access the message as string anymore, making the automatically created function useless.

It is possible to work with BrokeredMessages through this:

project.json:

{
    "frameworks": {
        "net46":{
            "dependencies": {
                "WindowsAzure.ServiceBus": "2.7.6"
            }
        }
    }
}

run.csx:

using Microsoft.ServiceBus.Messaging;
....
log.Info($"C# ID: {queueItem.GetBody<string>()})

But I haven't been able to find out how to pass {queueItem.GetBody<string>()} into the id attribute of the input document binding. So I can no longer use the aforementioned method of binding my documentdb input through "id" : "{myQueueItem}" and thus am unable to read any values from any documents.

  • Is there a way of sending a raw string to the Bus Queue or is BrokeredMessage really the only possibility? (from what I've been able to find out, raw string is not possible)

  • If BrokeredMessage is indeed the only way, is it possible to still get the string value from the message and use it as an ID for a DocumentDB document?

  • If neither of the above are possible, could you please point me in the right direction with this?

A more complete explanation of my function:

An application periodically sends new documents into the DocumentDB database. Together with the document (after waiting for the insert to complete) it sends a message with the new document's ID into the Service Bus queue. Then the trigger connects to the new document and checks an integer value inside it. If the value is larger than 10, it sends an email notification about it.

I have successfully created this and tested it through the web-based editor's manual Run with a string id of one of the documents as the test input. However, when I tried to use it with the app that sends the documents and messages automatically, I ran into the BrokeredMessage problem as described above.

Below is the whole code for the wórking function without BrokeredMessage:

using System;
using System.Net;
using System.Net.Mail;

public static void Run(string queueItem, dynamic inputDocument, TraceWriter log)
{
    log.Info($"C# ID: {queueItem}, Value: {inputDocument.Value}");

    if (inputDocument.Value > 10)
    {
        var fromAddress = new MailAddress("---@gmail.com", "From ---");
        var toAddress = new MailAddress("---@gmail.com", "To ---");
        const string fromPassword = "---";
        const string subject = "Notification";
        const string body = "Temperature too high!";

        var smtp = new SmtpClient
        {
            Host = "smtp.gmail.com",
            Port = 587,
            EnableSsl = true,
            DeliveryMethod = SmtpDeliveryMethod.Network,
            UseDefaultCredentials = false,
            Credentials = new NetworkCredential(fromAddress.Address, fromPassword)
        };
        using (var message = new MailMessage(fromAddress, toAddress)
        {
            Subject = subject,
            Body = body
        })
        {
            smtp.Send(message);
        }
    }
}

Here's a working example showing how to receive a ServiceBus message as a POCO and bind to it's properties.

If you send a message to the queue with the correct application/json content type, the function will deserialize into the POCO for you, and the Document DB input binding will bind to the DocumentId property and retrieve the document for you. You don't need to add anything in the project.json for this to work.

The function.json file:

{
  "bindings": [
    {
      "name": "input",
      "type": "serviceBusTrigger",
      "direction": "in",
      "queueName": "<your-queue.",
      "connection": "<your-connection>",
      "accessRights": "Manage"
    },
    {
      "type": "documentDB",
      "name": "document",
      "databaseName": "<your-db>",
      "collectionName": "<your-collection>",
      "id": "{DocumentId}",
      "connection": "<your-connection>",
      "direction": "in"
    }
  ]
}

The function code:

using System;
using System.Threading.Tasks;

public class Input
{
    public string DocumentId { get; set; }
    public int Value { get; set; }
}

public static void Run(Input input, dynamic document, TraceWriter log)
{
    log.Info($"Message received (DocumentId: {input.DocumentId}, Value {input.Value})");
    log.Info($"Document read {document.id}");
}

For C# functions, to use binding parameters (eg the {DocumentId} parameter) the trigger input must be bound to a POCO object defining those properties.

For sending email messages, you might also look into our SendGrid output binding. We have a complete sample "SendGrid-CSharp" available in the portal under "Samples" :)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM