7

I am migrating some functions from netcore 3.1 to net5, to use isolated model. However, I have come across this incompatibility that I have not resolve; the documentation has not led me to find a solution. It's about using an Azure function to put a row in a storage table, this code snippet works perfect:

// netcoreapp3.1, works OK
[FunctionName("PlaceOrder")]
public static async Task<IActionResult> Run(
   [HttpTrigger(AuthorizationLevel.Anonymous, "post")] 
   OrderPlacement orderPlacement,
   
   [Table("Orders")] IAsyncCollector<Order> orders)
{
   await orders.AddAsync(new Order {
       PartitionKey = "US",
       RowKey = Guid.NewGuid().ToString(),
       CustomerName = orderPlacement.CustomerName,
       Product = orderPlacement.Product
   });
   return new OkResult();
}

The attempt to do it in net5, would be very similar to the following:

// net5.0 approach
[Function("PlaceOrder")]
public static async Task<IActionResult> Run(

   [HttpTrigger(AuthorizationLevel.Anonymous, "post")]
   HttpRequestData req,

   [Table("Orders")] IAsyncCollector<Order> orders)
{
   var orderPlacement = await req.ReadFromJsonAsync<OrderPlacement>();

   await orders.AddAsync(new Order {
       PartitionKey = "US",
       RowKey = Guid.NewGuid().ToString(),
       CustomerName = orderPlacement.CustomerName,
       Product = orderPlacement.Product
   });
   return new OkResult();
}

But the line of Table bind indicates the error: The attribute 'TableAttribute' is a WebJobs attribute and not supported in the .NET Worker (Isolated Process). - What is the correct equivalent?

Sith2021
  • 3,245
  • 30
  • 22
  • There isn't one. This is because Azure Functions is a steaming mess of incompatibility and you should avoid "upgrading" to version 5 at all costs. Hopefully by .NET 6 they will have resolved this nonsense, but sadly I would not hold my breath. – Ian Kemp Jun 15 '21 at 23:20

3 Answers3

17

You should be using Microsoft.Azure.Functions.Worker.Extensions.* package for Azure function .net 5.

You can read this official documentation for further information.

enter image description here

So for table binding use Microsoft.Azure.Functions.Worker.Extensions.Storage package and also use TableOutput attribute for binding.

Like shown below:

    [Function("TableFunction")]
    [TableOutput("OutputTable", Connection = "AzureWebJobsStorage")]
    public static MyTableData Run([QueueTrigger("table-items")] string input,
        [TableInput("MyTable", "MyPartition", "{queueTrigger}")] MyTableData tableInput,
        FunctionContext context)
    {
        var logger = context.GetLogger("TableFunction");

        logger.LogInformation($"PK={tableInput.PartitionKey}, RK={tableInput.RowKey}, Text={tableInput.Text}");

        return new MyTableData()
        {
            PartitionKey = "queue",
            RowKey = Guid.NewGuid().ToString(),
            Text = $"Output record with rowkey {input} created at {DateTime.Now}"
        };
    }

You can check the sample for various supported bindings at here.

user1672994
  • 10,509
  • 1
  • 19
  • 32
  • That can be a strategic solution, when combined with more functions. Although I don't see where a new row writes in the Table. The issue is that through a single POST an object, part of the identity, is passed and the function writes it to the Azure table. I know there is a solution, - Things in code do not evolve to be less than their predecessor. Thanks for the attention. – Sith2021 Jun 16 '21 at 15:18
  • The new row will be written in `OutputTable` as defined in `TableOutput` attribute. You can update the value appropriately. – user1672994 Jun 16 '21 at 17:13
  • If you are still confused, maybe you want to have a look at Microsoft sample code here - https://github.com/Azure/azure-functions-dotnet-worker/tree/main/samples – Kelvin Jul 12 '22 at 08:37
  • I have the package Microsoft.Azure.Functions.Worker.Extensions.Storage Version="5.0.0" but VS doesn't recognize TableOutput attribute at all. Not sure what I'm doing wrong. – Oliver Nilsen Oct 03 '22 at 15:32
  • For those looking for the .net isolated custom bindings support (that was previously enabled using WebJobs), Azure.Functions.Worker.Extensions doesn't seem to provide the same support. Awkward workaround: https://blog.maartenballiauw.be/post/2021/06/01/custom-bindings-with-azure-functions-dotnet-isolated-worker.html – Josh Mc Mar 09 '23 at 22:26
2

The solution is a single line. The equivalent is the following:

public static class PlaceOrder
{
    [Function("PlaceOrder")]
    [TableOutput("Orders")]
    public static async Task<Order> TableOutput(
        [HttpTrigger(AuthorizationLevel.Anonymous, "post")] HttpRequestData req)
    {
        var orderPlacement = await req.ReadFromJsonAsync<OrderPlacement>();
        return new Order {
            PartitionKey = "US",
            RowKey = Guid.NewGuid().ToString(),
            CustomerName = orderPlacement.CustomerName,
            Product = orderPlacement.Product
        };
    }
}
Sith2021
  • 3,245
  • 30
  • 22
2

I had the same Issue and added the following references to my *.csproj file:

<ItemGroup>
    <PackageReference Include="Microsoft.Azure.Functions.Worker" Version="1.5.1" />
    <PackageReference Include="Microsoft.Azure.Functions.Worker.Sdk" Version="1.0.4" OutputItemType="Analyzer" />
    <PackageReference Include="Microsoft.Azure.Functions.Worker.Extensions.Http" Version="3.0.13" />
</ItemGroup>
ping
  • 663
  • 6
  • 13