0

I have been trying to return Table Storage rows back in Queue Trigger Function URL, But could not getting success. Below is my code.

public static async Task<List<PatchesList>> Run([QueueTrigger("send-patches-list", Connection = 
"AzureWebJobsStorage")]string myQueueItem, [Table(tableName: "getpatcheslist", Connection = 
"AzureWebJobsStorage")]CloudTable cloudTable, ILogger log)
{
    log.LogInformation($"C# Queue trigger function processed: {myQueueItem}");

    TableQuery<PatchesList> projectionQuery = new TableQuery<PatchesList>().Select(
new string[] { "RowKey", "Name" });

    var grouprows = await cloudTable.ExecuteQuerySegmentedAsync(projectionQuery, null);
    List<PatchesList> groupslist = new List<PatchesList>();
    log.LogInformation($"C# Queue trigger function processed: {grouprows}");
    foreach (var c in grouprows.Results)
    {
        groupslist.Add(new PatchesList
        {
            RowKey = c.RowKey,
            Name = c.Name
        });
        log.LogInformation($"C# Queue trigger function processed: {groupslist[0].Name}");
    }

    return groupslist;
}

public class PatchesList : TableEntity
{
    public string PartitionKey { get; set; }
    public string RowKey { get; set; }
    public string Name { get; set; }
}

I am having trouble sending data back and Is this approach feasible, can Queue Trigger send back response?

Kashyap
  • 15,354
  • 13
  • 64
  • 103
bhupinder
  • 315
  • 1
  • 6
  • 23

2 Answers2

1

Queue-triggered Azure Functions don't have an http function URL and have output bindings, not returns. If you need to return a JSON version of your objects, then you need to use an HTTP-triggered function (which can return HTML/JSON/etc to the caller), not a queue. If you must use a queue, then you need to output your data to some other source using a binding or custom code that you create. If you explain your use case/needs a bit more, it may be possible to elaborate on a solution.

Update:

So based on your comment, you want to take your groupsList and send it to an HTTP endpoint (a URL). If that is correct, then you just need to use HttpClient to POST the data to that URL...no output binding.

First, for functions, it's best practice to use a static copy of HttpClient (see https://learn.microsoft.com/en-us/azure/azure-functions/manage-connections), so you would add the following line above your function:

private static HttpClient httpClient = new HttpClient();

Then use that httpClient to POST your data as JSON:

var json = JsonConvert.SerializeObject(groupsList);
var content = new StringContent(json, UnicodeEncoding.UTF8, "application/json");
var response = await httpClient.PostAsync(<yourUrl>, content);

You can inspect the response if you want to verify success and even use a 3rd party library such as Polly to retry requests should they fail. Once the POST is complete, you're done. No return or output binding from the Function, since it technically has no output.

Bryan Lewis
  • 5,629
  • 4
  • 39
  • 45
  • Triggers and bindings are not dependent. You can have any combination. And returns do work as shown in [this example](https://learn.microsoft.com/en-us/azure/azure-functions/functions-bindings-storage-table-output?tabs=csharp#example) – Kashyap Dec 01 '20 at 21:27
  • But that example (and your answer) is an HTTP triggered function, and so you can return an HTTP response. The OP seems to want to return an HTTP response to a queue-triggered function (unless I am reading i wrong)...which is not possible. – Bryan Lewis Dec 01 '20 at 21:34
  • Ha ha.. That's another way of looking at it. I saw it as "he wants a Q trigger and Table output". AFAIK You can have one trigger, many outputs and many input or output binding for a function. And in my reply, what is returned gets inserted into the Table, not returned as an HTTP response. I guess I second " If you explain your use case/needs a bit more, it may be possible to elaborate on a solution." @bhupinder – Kashyap Dec 01 '20 at 21:40
  • I need to send data back to http URL in queue based trigger, Can I do that using Output Bindings. – bhupinder Dec 02 '20 at 10:46
  • @bhupinder, see the update to my Answer to see if that covers your use case. – Bryan Lewis Dec 02 '20 at 15:01
  • Returning data back using httpendpoint was in my mind. so we cannot use outputbindings. Thanks for your reply This approach will also work. – bhupinder Dec 02 '20 at 17:08
0

You're using input binding for table, use output binding.

If you want to insert a single row you can use [return: Table("MyTable")] on your function and then return a single record as function's return value.

public class TableStorage
{
    public class MyPoco
    {
        public string PartitionKey { get; set; }
        public string RowKey { get; set; }
        public string Text { get; set; }
    }

    [FunctionName("TableOutput")]
    [return: Table("MyTable")]
    public static MyPoco TableOutput([HttpTrigger] dynamic input, ILogger log)
    {
        log.LogInformation($"C# http trigger function processed: {input.Text}");
        return new MyPoco { PartitionKey = "Http", RowKey = Guid.NewGuid().ToString(), Text = input.Text };
    }
}

If you want to insert multiple rows then you'll have to use the ICollector<T> as described here.

[FunctionName("TableOutput")] // don't forget this one
public static async Task<List<PatchesList>> Run(
    [QueueTrigger("send-patches-list", Connection = "AzureWebJobsStorage")]string myQueueItem,
    ICollector<PatchesList> outTable, ILogger log)
{
    // ...your code...
    // insert into outTable
    // some examples here: https://www.mudbath.com.au/insight/a-simple-guide-to-azure-table-storage-in-c/
    // ...your code...
}
Kashyap
  • 15,354
  • 13
  • 64
  • 103