如何在HTTP触发的Azure函数中绑定模型集合?

时间:2019-03-13 13:40:32

标签: c# json azure azure-functions

我有一个Azure Function v2。该功能由POST HTTP请求触发,并被提供一个帐户列表。

这是Azure功能:

public sealed class AccountFunction
{
    private readonly ILogger m_logger;

    public AccountFunction(ILoggerFactory loggerFactory)
    {
        m_logger = loggerFactory.CreateLogger<AccountFunction>();
    }

    [FunctionName("AccountFunction")]
    public IActionResult Run([HttpTrigger(AuthorizationLevel.Anonymous, "post", Route = "v1/accounts")] List<Account> accounts)
    {
        m_logger.LogInformation("C# HTTP trigger function processed a request.");

        return new OkObjectResult(accounts);
    }
}

Account类是一个简单的POCO:

public class Account
{
    public string Name { get; set; }
    public string Description { get; set; }
}

我启动该功能,然后发送以下POST请求:

http://localhost:7071/api/v1/accounts

我在请求的正文中设置了JSON集合:

[{ 
    "name":"A",
    "description":"covfefe"
},
 { 
    "name":"B",
    "description":"huuuggge"
}]

Azure函数返回一个空集合,并且跟踪没有显示任何错误:

[2019-03-13 1:34:13 PM] Executing HTTP request: { 
[2019-03-13 1:34:13 PM]   "requestId": "3ee0483f-7e26-4bbf-a4ea-550dbbd86563", [2019-03-13 1:34:13 PM]   "method": "POST", 
[2019-03-13 1:34:13 PM]   "uri": "/api/v1/accounts" 
[2019-03-13 1:34:13 PM] } 
[2019-03-13 1:34:13 PM] Request successfully matched the route with name 'AccountFunction' and template 'api/v1/accounts' 
[2019-03-13 1:34:14 PM] Executing 'AccountFunction' (Reason='This function was programmatically called via the host APIs.', Id=92b40b1a-8bb1-4699-a590-d057c5eb7353) 
[2019-03-13 1:34:14 PM] C# HTTP trigger function processed a request. 
[2019-03-13 1:34:14 PM] Executed 'AccountFunction' (Succeeded, Id=92b40b1a-8bb1-4699-a590-d057c5eb7353) [2019-03-13 1:34:14 PM] Executed HTTP request: { 
[2019-03-13 1:34:14 PM]   "requestId": "3ee0483f-7e26-4bbf-a4ea-550dbbd86563",
[2019-03-13 1:34:14 PM]   "method": "POST", [2019-03-13 1:34:14 PM]   "uri": "/api/v1/accounts", 
[2019-03-13 1:34:14 PM]   "identities": [ [2019-03-13 1:34:14 PM]     { 
[2019-03-13 1:34:14 PM]       "type": "WebJobsAuthLevel", 
[2019-03-13 1:34:14 PM]       "level": "Admin" 
[2019-03-13 1:34:14 PM] } 
[2019-03-13 1:34:14 PM]   ], 
[2019-03-13 1:34:14 PM]   "status": 200, 
[2019-03-13 1:34:14 PM]   "duration": 517 
[2019-03-13 1:34:14 PM] }

在调试功能时,我发现account参数未正确填写:

Accounts is empty

问题

如何在Azure函数中绑定模型集合?

我正在运行最新的Azure Function Core工具2.4.419和Azure Function运行时2.0.12332.0。

Function App面向.NET Core 2.1。

更新

我尝试了其他几种选择。

第一个是要有一个Accounts派生的新List<Account>类,但结果是相同的。

public class Accounts : List<Account>
{        
}

第二项测试是使“帐户”包含一个帐户列表作为属性:

public class Accounts
{        
    public List<Account> Items {get;set;}
}

除了返回的对象现在是:

{
    "items": null
}

1 个答案:

答案 0 :(得分:0)

我已经尝试过,并且还在本地复制了此问题。首先,我尝试使用单个Account对象,然后将方法签名更新为接受List<Account>。经过快速检查,我发现以下GitHub issue描述了此行为。

在该问题上有一个comment指向以下source file line,其中代码明确排除了数组

var additionalBindingData = parsed.Children<JProperty>()
    .Where(p => p.Value != null && (p.Value.Type != JTokenType.Array))

看来实现此目标的唯一方法是使用workaround

另一种方法是使用ReadAsAsync<T>扩展方法。

namespace StackOverflow.AccountsQuestion
{
    public sealed class AccountFunction
    {
        private readonly ILogger m_logger;

        public AccountFunction(ILoggerFactory loggerFactory)
        {
            m_logger = loggerFactory.CreateLogger<AccountFunction>();
        }

        [FunctionName("AccountFunction")]
        public async Task<IActionResult> Run([HttpTrigger(AuthorizationLevel.Anonymous, "post", Route = "v1/accounts")] HttpRequestMessage request)
        {
            m_logger.LogInformation("C# HTTP trigger function processed a request.");
            var accounts = await request.Content.ReadAsAsync<List<Account>>();
            return new OkObjectResult(accounts);
        }
    }

    public class Account
    {
        public string Name { get; set; }
        public string Description { get; set; }
    }
}