2
votes

I have an Azure function that successfully queues storage table records as I can see in Azure Storage Explorer.

I have an Azure Function that successfully sends messages through SendGrid, and is supposed to trigger when the aforementioned queue is added to, but it does not.

I'm guessing there's a config issue. They're both in the same Function app and using the same connection string, but the SendGrid Function doesn't trigger. Both the functions themselves are vanilla minus my email address changes. Is there some other config to use?

HttpPost(CRUD)-CSharp1

{
  "bindings": [
    {
      "type": "httpTrigger",
      "direction": "in",
      "name": "req",
      "methods": [
        "post"
      ],
      "authLevel": "function"
    },
    {
      "type": "http",
      "direction": "out",
      "name": "res"
    },
    {
      "type": "table",
      "name": "outTable",
      "tableName": "orders",
      "connection": "matching_connection_string",
      "direction": "out"
    }
  ],
  "disabled": false
}

SendGridCSharp1

{
  "bindings": [
    {
      "type": "sendGrid",
      "name": "message",
      "direction": "out",
      "subject": "",
      "text": ""
    },
    {
      "type": "queueTrigger",
      "name": "order",
      "queueName": "orders",
      "connection": "matching_connection_string",
      "direction": "in"
    }
  ],
  "disabled": false
}

Update per @DAXaholic's answer

DAXaholic suggested I was writing to a table but triggering from a queue. I updated my outbound config (changed the last binding type to queue) and I'm receiving an error about not knowing which constructor to use: Function ($HttpPOST(CRUD)-CSharp1) Error: Can't figure out which ctor to call. I tried changing the namespace to Microsoft.WindowsAzure.Storage.Queue, but that didn't seem to have an effect.

Code below:

#r "Microsoft.WindowsAzure.Storage"

using System.Net;
using Microsoft.WindowsAzure.Storage.Table;

public static async Task<HttpResponseMessage> Run(HttpRequestMessage req, ICollector<Order> outTable, TraceWriter log)
{
    var formData = await req.Content.ReadAsFormDataAsync();

    if(string.IsNullOrWhiteSpace(formData.Get("Name")))
    {
        return req.CreateResponse(HttpStatusCode.BadRequest, new {
           error = "no 'Name' property" 
        });
    }

    string name = formData["Name"].ToString();

    outTable.Add(new Order()
    {
        PartitionKey = "Functions",
        RowKey = Guid.NewGuid().ToString(),
        OrderId = string.Format("order{0}", name),
        CustomerName = name,
        CustomerEmail = string.Format("{0}@{1}.com", name, name)
    });
    return req.CreateResponse(HttpStatusCode.Created);
}

public class Order : TableEntity
{
    public string OrderId { get; set; }
    public string CustomerName { get; set; }
    public string CustomerEmail { get; set; }
}
1

1 Answers

3
votes

I guess the problem is your trigger is based on a Azure Storage Queue but you are writing to an Azure Storage Table so the former is not triggered. That said, try to replace the outbound binding to the Azure Storage Table with a binding to an appropriate queue like so (see here as a reference)

{
  "bindings": [
    {
      "type": "httpTrigger",
      "direction": "in",
      "name": "req",
      "methods": [
        "post"
      ],
      "authLevel": "function"
    },
    {
      "type": "http",
      "direction": "out",
      "name": "res"
    },
    {
      "type": "queue",
      "name": "outTable",
      "queueName": "orders",
      "connection": "matching_connection_string",
      "direction": "out"
    }
  ],
  "disabled": false
}

Update outbound code to:

#r "Microsoft.WindowsAzure.Storage"

using System.Net;
using Microsoft.WindowsAzure.Storage.Queue;

public static async Task<HttpResponseMessage> Run(HttpRequestMessage req, ICollector<Order> outQueue, TraceWriter log)
{
    var formData = await req.Content.ReadAsFormDataAsync();

    if(string.IsNullOrWhiteSpace(formData.Get("Name")))
    {
        return req.CreateResponse(HttpStatusCode.BadRequest, new {
           error = "no 'Name' property" 
        });
    }

    string name = formData["Name"].ToString();

    outQueue.Add(new Order()
    {
        OrderId = string.Format("order{0}", name),
        CustomerName = name,
        CustomerEmail = string.Format("{0}@{1}.com", name, name)
    });
    return req.CreateResponse(HttpStatusCode.Created);
}

public class Order
{
    public string OrderId { get; set; }
    public string CustomerName { get; set; }
    public string CustomerEmail { get; set; }
}