【问题标题】:input-binding to table storage with an http-triggered function使用 http 触发函数将输入绑定到表存储
【发布时间】:2019-06-05 17:43:39
【问题描述】:

是否可以(输入)绑定到 http 触发函数中的表存储?

我正在尝试将输入绑定添加到具有以下属性的常规 http 触发函数内的 table-storage:

    [Table("MyTable", "MyPartition", "{httpTrigger}")] MyPoco poco

但是当我执行它时它返回以下错误:

[2019 年 6 月 5 日下午 5:36:38] 发生了未处理的主机错误。 [2019 年 6 月 5 日 下午 5:36:38] Microsoft.Azure.WebJobs.Host: 无法从 Azure 调用“tableStorageInputBindingHttpTriggered” 网络作业 SDK。是否缺少 Azure WebJobs SDK 属性?

另外在启动时,我得到这个异常:

[2019 年 6 月 5 日下午 6:17:17] tableStorageInputBindingHttpTriggered:Microsoft.Azure.WebJobs.Host:错误索引方法“tableStorageInputBindingHttpTriggered”。 Microsoft.Azure.WebJobs.Host:无法解析绑定参数“httpTrigger”。绑定表达式必须映射到触发器提供的值或触发器绑定到的值的属性,或者必须是系统绑定表达式(例如 sys.randguid、sys.utcnow 等)。

这是完整的功能:

public class MyPoco
{
    public string PartitionKey { get; set; }
    public string RowKey { get; set; }
    public string Directory { get; set; }
}

public static class tableStorageInputBindingHttpTriggered
{
    [FunctionName("tableStorageInputBindingHttpTriggered")]
    public static async Task<IActionResult> Run(
    [HttpTrigger(AuthorizationLevel.Function, "get", "post", Route = null)] HttpRequest req,
    [Table("MyTable", "MyPartition", "{httpTrigger}")] MyPoco poco,
        ILogger log)
    {


        string name = req.Query["name"];

        string requestBody = await new StreamReader(req.Body).ReadToEndAsync();
        dynamic data = JsonConvert.DeserializeObject(requestBody);
        name = name ?? data?.name;

        return name != null
            ? (ActionResult)new OkObjectResult($"PK={poco.PartitionKey}, RK={poco.RowKey}, Text={poco.Directory}")
            : new BadRequestObjectResult("");
    }
}

我做错了什么?如何绑定到 http 触发的 azure 函数中的表存储?

【问题讨论】:

  • 你能分享你的计划吗,你到底想做什么?
  • 对于每个http请求,我希望将请求的bbody添加到表存储中
  • 让我验证你想在调用 http 触发器时在表存储中读写?
  • @MdFaridUddinKiron 我想阅读(这是与表存储的输入绑定)
  • 请看一下。我试过这种方法。如果对你有帮助。很抱歉,我答复晚了。谢谢,编码愉快!

标签: c# .net azure azure-functions azure-table-storage


【解决方案1】:

问题是 http 触发器返回一个对象,所以它不知道如何提取你的密钥。

你需要使用路由,它会告诉函数如何获取参数,然后你就可以使用该参数了

  public static async Task<HttpResponseMessage> SetLatestAsync(
            [HttpTrigger(AuthorizationLevel.Anonymous, "post", Route = "release-set-latest/{program}")]
            HttpRequestMessage req,
            string program,
            [Table(TableName, "latest", "{program}")]FlymarkLatestVersion pocos)

【讨论】:

    【解决方案2】:

    这通过绑定到CloudTable 将请求正文插入到表存储中

    using System;
    using System.IO;
    using System.Threading.Tasks;
    using Microsoft.AspNetCore.Mvc;
    using Microsoft.Azure.WebJobs;
    using Microsoft.Azure.WebJobs.Extensions.Http;
    using Microsoft.AspNetCore.Http;
    using Microsoft.Extensions.Logging;
    using Microsoft.WindowsAzure.Storage.Table;
    
    namespace AzureFunctionsSandbox
    {
        public class MyPoco : TableEntity
        {
            public string Body { get; set; }
        }
    
        public static class Function1
        {
            [FunctionName("Function1")]
            public static async Task<IActionResult> Run(
                [HttpTrigger(AuthorizationLevel.Function, "get", "post", Route = null)] HttpRequest req,
                [Table("Sandbox", "StorageConnectionString")] CloudTable table,
                ILogger log)
            {
                log.LogInformation("C# HTTP trigger function processed a request.");
    
                string requestBody = await new StreamReader(req.Body).ReadToEndAsync();
    
                var poco = new MyPoco { PartitionKey = "HttpTrigger", RowKey = Guid.NewGuid().ToString(), Body = requestBody };
    
                var insertOperation = TableOperation.Insert(poco);
    
                await table.ExecuteAsync(insertOperation);
    
                return new OkObjectResult($"PK={poco.PartitionKey}, RK={poco.RowKey}, Text={poco.Body}");
            }
        }
    }
    

    注意MyPoco 继承自 TableEntity,它允许您创建 TableOperation.Insert(poco),因为 .Insert() 采用 ITableEntity

    local.settings.json

    {
      "IsEncrypted": false,
      "Values": {
        "AzureWebJobsStorage": "UseDevelopmentStorage=true",
        "FUNCTIONS_WORKER_RUNTIME": "dotnet",
    
        "StorageConnectionString": "UseDevelopmentStorage=true"
      }
    }
    

    【讨论】:

      【解决方案3】:

      您似乎正在尝试从HTTP Trigger Function 读取您的Azure Table Storage。请看下面的代码sn-p:

      您的 POCO 课程:

        public class MyPoco
          {
      
              public string PartitionKey { get; set; }
              public string RowKey { get; set; }
              public string Directory { get; set; }
      
          }
      

      表存储类:

       public class TableStorageClass
          {
              public TableStorageClass()
              {
      
              }
              public TableStorageClass(DynamicTableEntity entity)
              {
                  PartitionKey = entity.PartitionKey;
                  RowKey = entity.RowKey;
      
              }
      
              public string PartitionKey { get; set; }
              public string RowKey { get; set; }
      
      
          }
      

      Azure HTTP 触发函数 V2:

      public static class FunctionReadFromTableStorage
          {
              [FunctionName("FunctionReadFromTableStorage")]
              public static async Task<IActionResult> Run(
                  [HttpTrigger(AuthorizationLevel.Anonymous, "get", "post", Route = null)] HttpRequest req,
                  ILogger log)
              {
                  log.LogInformation("C# HTTP trigger function processed a request.");
      
                  //Read Request Body
                  var content = await new StreamReader(req.Body).ReadToEndAsync();
      
                  //Extract Request Body and Parse To Class
                  MyPoco objMyPoco = JsonConvert.DeserializeObject<MyPoco>(content);
      
                  // Validate param because PartitionKey and RowKey is required to read from Table storage In this case , so I am checking here.
                  dynamic validationMessage;
      
                  if (string.IsNullOrEmpty(objMyPoco.PartitionKey))
                  {
                      validationMessage = new OkObjectResult("PartitionKey is required!");
                      return (IActionResult)validationMessage;
                  }
                  if (string.IsNullOrEmpty(objMyPoco.RowKey))
                  {
                      validationMessage = new OkObjectResult("RowKey is required!");
                      return (IActionResult)validationMessage;
                  }
      
      
                  // Table Storage operation  with credentials
                  var client = new CloudTableClient(new Uri("https://YourStorageURL.table.core.windows.net/"),
                            new Microsoft.WindowsAzure.Storage.Auth.StorageCredentials("YourStorageName", "xtaguZokAWbfYG4QDkBjT+YourStorageKey+T/kId/Ng+cl3TfYHtg=="));
                  var table = client.GetTableReference("YourTableName");
      
                  //Query filter
                  var query = new TableQuery()
                  {
                      FilterString = string.Format("PartitionKey eq '{0}' and RowKey eq '{1}'", objMyPoco.PartitionKey, objMyPoco.RowKey)
                  };
      
      
                  //Request for storage query with query filter
                  var continuationToken = new TableContinuationToken();
                  var storageTableQueryResults = new List<TableStorageClass>();
                  foreach (var entity in table.ExecuteQuerySegmentedAsync(query, continuationToken).GetAwaiter().GetResult().Results)
                  {
                      var request = new TableStorageClass(entity);
                      storageTableQueryResults.Add(request);
                  }
      
                  //As we have to return IAction Type So converting to IAction Class Using OkObjectResult We Even Can Use OkResult
                  var result = new OkObjectResult(storageTableQueryResults);
                  return (IActionResult)result;
              }
          }
      

      要记住的要点:

      1. 如果执行Azure Portal,只需摆脱FunctionReadFromTableStorage
      2. 您需要以下参考来执行上述代码
      using System;
      using System.IO;
      using System.Threading.Tasks;
      using Microsoft.AspNetCore.Mvc;
      using Microsoft.Azure.WebJobs;
      using Microsoft.Azure.WebJobs.Extensions.Http;
      using Microsoft.AspNetCore.Http;
      using Microsoft.Extensions.Logging;
      using Newtonsoft.Json;
      using Microsoft.WindowsAzure.Storage.Table;
      using System.Collections.Generic;
      

      邮递员请求模式:

      函数调用示例:

      {
         "PartitionKey": "Your Param According to Table Storage Design" ,
         "RowKey": "Your Param According to Table Storage Design",
         "Directory": "Your Param According to Table Storage Design"
      }
      

      查看屏幕截图:

      邮递员回复:

      响应以我自己的表格设计为准

      [
          {
              "partitionKey": "Microsoft SharePoint Server",
              "rowKey": "2016"
          }
      ]
      

      请参阅下面的屏幕截图:

      注意:我喜欢以简单易读的方式编写代码。我只是为您的情况尝试过。如果它解决了您的问题,我的努力将是 那么成功。这是迄今为止我所知道的最简单的阅读方式 azure table storage.

      如果您仍有任何问题,请随时分享。感谢和快乐的编码!

      【讨论】:

      • 非常感谢,这非常有用,但是应该有一种更简单/更具声明性的方式,您只需将输出绑定到表格
      • 我同意你关于输出绑定的看法。无论如何,很高兴收到你的来信。我尝试了自己的方法来解决您的问题。现在评估是你的 ?
      • 我看不到与输入绑定的任何关系??!
      • 我试图展示如何使用分区键和行键来查找特定对象。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-07-24
      • 1970-01-01
      • 2014-04-09
      • 2016-10-01
      • 2020-09-09
      • 1970-01-01
      相关资源
      最近更新 更多