Search code examples
c#azure-functionshttprequestazure-functions-isolated

How do I pass an int array into an HTTP-triggered, dotnet-isolated V4 Azure Function as a body parameter?


I can make it work if I create a custom class that just serves as a wrapper for an integer array, but I'd rather not do that extra step. I want to just pass in an integer array.


This was my latest attempt:

using System.Net;
using Microsoft.Azure.Functions.Worker;
using Microsoft.Azure.Functions.Worker.Http;
using Microsoft.Extensions.Logging;

public HttpResponseData Run([HttpTrigger(AuthorizationLevel.Anonymous, "post")]
            HttpRequestData req)
        {
            var ids = JsonSerializer.Deserialize<int[]>(req.Body);
            ...
        }

I'm testing locally with Postman. I set the Body to JSON and my input looked like this:

{
    "ids": [1, 2, 3]
}

I'm getting a JSON serialization error, obviously, b/c it's expecting an object with just an array as it's only field, named "ids". But that's not how I want to solve this.

Previously, I was trying this (based on Mircosoft's own documentation):

using System.Net;
using Microsoft.Azure.Functions.Worker;
using Microsoft.Azure.Functions.Worker.Http;
using Microsoft.Extensions.Logging;
using FromBodyAttribute = Microsoft.Azure.Functions.Worker.Http.FromBodyAttribute;

public HttpResponseData Run([HttpTrigger(AuthorizationLevel.Anonymous, "post")]
            HttpRequestData req, [FromBody] int[] ids)
        {
             ....
        }

When I use the JSON Body input approach above via Postman, I get the same serialization error.

When I try just passing it in as raw text like [1, 2, 3] I get a System.InvalidOperationException with the message: 'System.Int32[]' is not supported by the 'DefaultFromBodyConversionFeature'

Obviously based on that last exception, it seems like [FromBody] isn't the way to go. But there has to be some way to do this that I'm missing. This seems like a trivial problem and I'm frustrated that I haven't found a solution. Any help would be much appreciated.


Solution

  • If the content of your body is simply:

    [1,2,3]
    

    You can deserialize it using:

    public HttpResponseData Run([HttpTrigger(AuthorizationLevel.Anonymous, "post")] HttpRequestData req)
    {
       var ids = JsonSerializer.Deserialize<List<int>>(req.Body);
       ...
    }
    

    Otherwise, if you're input is:

    {
       "ids": [1,2,3]
    }
    

    Then you can't deserialize the contents without a class definition like:

    public class IdsDto
    {
       public List<int> ids { get; set; }
    }
    

    That you could then use like this:

    var idsDto = JsonSerializer.Deserialize<IdsDto>(req.Body);
    var ids = idsDto.ids;
    

    If you really want to avoid the intermediate class, you could perform some dirty string manipulation to leave yourself with only the int[]:

    var intArrayString = req.Body.substring(req.Body.IndexOf('['), req.Body.IndexOf(']') - req.Body.IndexOf('[') + 1);
    // And then:
    var intArray = JsonSerializer.Deserialize<List<int>>(intArrayString);
    

    But, honestly, I would go with the intermediate class.