привязка ввода к хранилищу таблиц с помощью функции http - PullRequest
0 голосов
/ 05 июня 2019

Возможно ли (входное) связывание с хранилищем таблицы в функции, запускаемой по протоколу http?

Я пытаюсь добавить привязку ввода к табличному хранилищу внутри обычной функции, запускаемой по протоколу http, со следующим атрибутом:

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

Однако при запуске я получаю следующую ошибку:

[05.06.2009 17:36:38] Произошла необработанная ошибка хоста. [6/5/2019 5:36:38 PM] Microsoft.Azure.WebJobs.Host: tableStorageInputBindingHttpTriggered не может быть вызван из Azure WebJobs SDK. В нем отсутствуют атрибуты Azure WebJobs SDK?.

Дополнительно при запуске я получаю следующее исключение:

[05.06.2009 18: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("");
    }
}

Что я делаю не так? Как связать хранилище таблиц с помощью функции azure, запускаемой по протоколу http?

Ответы [ 3 ]

3 голосов
/ 06 июня 2019

Проблема в том, что http-триггер возвращает вам объект, поэтому он не знает, как извлечь ваш ключ.

Вам нужно использовать route, который сообщит Function, как получить параметр, и тогда вы сможете использоватьчто параметры

  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 голосов
/ 07 июня 2019

Кажется, вы пытаетесь прочитать Azure Table Storage из HTTP Trigger Function. Пожалуйста, посмотрите фрагмент кода ниже:

Ваш класс 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"
}

См. Снимок экрана:

enter image description here

Ответ почтальона:

Ответ зависит от моего собственного дизайна таблицы

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

См. Снимок экрана ниже:

enter image description here

Примечание: Мне нравится писать код в простой и удобочитаемой форме. Я только что попробовал это для твоего случая. Если это решит вашу проблему, мои усилия будут Успех тогда. Это самый простой способ, насколько я знаю, читать из azure table storage.

Если у вас все еще есть вопросы, не стесняйтесь поделиться. Спасибо и счастливого кодирования!

1 голос
/ 06 июня 2019

Вставляет тело запроса в хранилище таблиц, связывая с 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"
  }
}
...