Jakie typy można przekazać jako parametr do aplikacji funkcji platformy Azure w języku C # tylko dla administratora?

Jan 11 2021

Jakie typy są dozwolone jako parametry dla aplikacji funkcji platformy Azure napisanych w języku C #, które można wywołać tylko za pośrednictwem punktu końcowego administratora?

Przeczytałem dużo dokumentacji i kodu źródłowego i nadal nie znam odpowiedzi. Szukam ostatecznych odniesień i jasnych wyjaśnień, co to oznacza i dlaczego, a także przykładów implementacji funkcji z innymi typami parametrów.

Zastanawiam się, czy zespół platformy Azure oczekuje, że zaakceptujesz ciąg JSON i sam przeanalizujesz go na odpowiednie typy, ale dokumentacja, którą znalazłem, nie mówi.

Dodatkowy kontekst

Konkretna funkcja, nad którą pracuję, ma być wywoływana tylko przez interfejs administratora, więc nie ma żadnych powiązań HTTP itp.

[NoAutomaticTrigger]
[FunctionName(nameof(SomeFunctionName))]
public async Task SomeFunctionName(ParameterTypeHere someParameterName)
{
...

Co mogę włożyć zamiast ParameterTypeHere?

Specyficzne zastosowanie, które mam (tym razem) polega na tym, że chcę przekazać coś takiego jak List<Guid>lub Guid[], nie mam nic przeciwko, jeśli muszę zawinąć to w klasę lub coś, ale nic, co próbowałem, nie zadziałało, więc skończyło się na podzieleniu struny przecinek i parsowanie przewodników, co wydaje się kiepskim rozwiązaniem.

Obecnie mam parametr typu string i wywołuję go za pomocą:

$ curl -v http://localhost:7071/admin/functions/SomeFunctionName \
  -d '{"input": "699F3073-9BFD-4DA7-9E61-4E6564D032EC,197DA362-C281-4E0F-BB92-8759F7A5B4B4"}' \
  -H "Content-Type:application/json"

Dotychczasowe badania

Rzeczy, którym już się przyjrzałem, pozostawiają mnie nadal niepewne, czego mogę użyć poza stringbardziej złożonymi danymi wejściowymi:

  • Azure Functions: typ ogólny jako parametr wejściowy
    • https://github.com/Azure/Azure-Functions/issues/735
  • Błąd usługi Azure Functions - nie można powiązać parametru z typem String
  • Nie można powiązać parametru, ponieważ typ parametru nie jest obsługiwany przez powiązanie (HttpTrigger z Azure Functions)
  • Nie można powiązać ILogger w Azure Function v1
  • https://docs.microsoft.com/en-us/azure/azure-functions/functions-manually-run-non-http
  • https://github.com/Azure/azure-functions-host/blob/dev/src/WebJobs.Script/Binding/Manual/ManualTriggerAttributeBindingProvider.cs#L39
    • https://github.com/Azure/azure-functions-host/blob/9b2fa0f3ea69c41ce819f046213eab4f40a5db5f/src/WebJobs.Script/Binding/StreamValueBinder.cs#L24-L30
    • https://github.com/Azure/azure-functions-host/blob/9b2fa0f3ea69c41ce819f046213eab4f40a5db5f/src/WebJobs.Script/Utility.cs#L245
  • ServiceBusTrigger z argumentem enqueueTimeUtc kończy się niepowodzeniem po wyzwoleniu za pośrednictwem punktu końcowego HTTP

Nazwa parametru jest ignorowana i musisz ją przekazać z nazwą „ input” niezależnie od rzeczywistej nazwy parametru. Kolejna rzecz, o którą można się potknąć.

Jeszcze więcej kontekstu

Jeśli zastanawiasz się, dlaczego kiedykolwiek chciałbyś mieć funkcję tylko dla administratora, było to jednorazowe zadanie wykonywane przez kogoś innego, kto ma dostęp do punktów końcowych administratora. Wydawało się, że to najprostsza rzecz, która może zadziałać. I HttpTriggerbyłoby w porządku, po prostu wydawało się, że narusza YAGNI.

Odpowiedzi

2 RoarS. Jan 11 2021 at 22:56

Kilka tygodni temu testowałem, jak konwertować API przy użyciu funkcji ze szczególnym uwzględnieniem DI (niepokazanego w poniższym przykładzie) i walidacji. Może to nie jest bezpośrednia odpowiedź na twoje pytanie, ale pokazuje, że można używać zwykłych klas modeli.

public class MyRequestModel
{
    [Display(Name = "Message")]
    [Required, MinLength(3)]
    public string Message { get; set; }
}

public static class MyHttpExample
{
    [FunctionName(nameof(MyHttpExample))]
    public static IActionResult Run(
        [HttpTrigger(AuthorizationLevel.Function, "get", Route = "test/{message}")] MyRequestModel req, ILogger log)
    {
        log.LogInformation("C# HTTP trigger function processed a request.");

        var validationResults = new List<ValidationResult>();
        if (!Validator.TryValidateObject(req, new ValidationContext(req, null, null), validationResults, true))
        {
            return new BadRequestObjectResult(validationResults);
        }

        var responseMessage = $"Hello, {req.Message}. This HTTP triggered function executed successfully.";
        return new OkObjectResult(responseMessage);
    }
}

Więcej informacji na temat wzorców wyrażeń powiązań usługi Azure Functions https://docs.microsoft.com/en-us/azure/azure-functions/functions-bindings-expressions-patterns

Czytając powyższy dokument, pamiętaj, że function.json jest generowane na podstawie adnotacji w języku C #, ale dokument pokazuje, co jest dostępne. Wygenerowano function.json dla powyższego przykładu:

{
  "generatedBy": "Microsoft.NET.Sdk.Functions-3.0.11",
  "configurationSource": "attributes",
  "bindings": [
    {
      "type": "httpTrigger",
      "route": "test",
      "methods": [
        "get"
      ],
      "authLevel": "function",
      "name": "req"
    }
  ],
  "disabled": false,
  "scriptFile": "../bin/MyFunctions.dll",
  "entryPoint": "MyFunctions.MyHttpExample.Run"
}

Zobacz też https://stackoverflow.com/a/54489040/14072498