未为 Azure Function 生成 OpenApi 文档

问题描述 投票:0回答:1

我有一个函数定义如下:

public class RegistrationFunction(
    IUserExistsQuery userExistsQuery,
    IRegisterUserCommand registerUser)
{
    [Function(nameof(RegistrationFunction))]
    [OpenApiOperation(operationId: "RegisterUser", Visibility = OpenApiVisibilityType.Important)]
    [OpenApiSecurity("function_key", SecuritySchemeType.ApiKey, Name = "x-functions-key", In = OpenApiSecurityLocationType.Header)]
    [OpenApiRequestBody(contentType: MediaTypeNames.Application.Json, bodyType: typeof(UserDataRequestBody))]
    [OpenApiResponseWithoutBody(statusCode: HttpStatusCode.OK)]
    [OpenApiResponseWithoutBody(statusCode: HttpStatusCode.Conflict)]
    [OpenApiResponseWithBody(statusCode: HttpStatusCode.BadRequest, bodyType: typeof(RegistrationErrorResponseBody), contentType: MediaTypeNames.Application.Json)]
    public async Task<HttpResponseData> Run(
        [HttpTrigger(AuthorizationLevel.Function, "post")] HttpRequestData req,
        [FromBody] UserDataRequestBody userData)
    {
        // code removed for brevity
    }
}

我还使用正确的包参考来启用 OpenApi 文档:

<PackageReference Include="Microsoft.Azure.WebJobs.Extensions.OpenApi" Version="1.5.1" />

我的 Program.cs 包含此代码,我也认为这是正确的:

var host = new HostBuilder()
    .UseServiceProviderFactory(new AutofacServiceProviderFactory())
    .ConfigureContainer<ContainerBuilder>(builder =>
    {
        builder.RegisterType<UserExistsQuery>().AsImplementedInterfaces().SingleInstance();
        builder.RegisterType<RegisterUserCommand>().AsImplementedInterfaces().SingleInstance();
    })
    .ConfigureServices(services =>
    {
        services.AddDbContext<MLTRContext>(options =>
        {
            var connectionString = Environment.GetEnvironmentVariable("PostgresConnectionString");
            
            options.UseNpgsql(connectionString);
        });
        services.AddSingleton<IOpenApiConfigurationOptions>(_ =>
        {
            var options = new OpenApiConfigurationOptions
            {
                Info = new OpenApiInfo
                {
                    Version = DefaultOpenApiConfigurationOptions.GetOpenApiDocVersion(),
                    Title = $"{DefaultOpenApiConfigurationOptions.GetOpenApiDocTitle()} (Injected)",
                    Description = DefaultOpenApiConfigurationOptions.GetOpenApiDocDescription(),
                    TermsOfService = new Uri("https://github.com/Azure/azure-functions-openapi-extension"),
                    Contact = new OpenApiContact
                    {
                        Name = "Enquiry",
                        Email = "[email protected]",
                        Url = new Uri("https://github.com/Azure/azure-functions-openapi-extension/issues"),
                    },
                    License = new OpenApiLicense
                    {
                        Name = "MIT",
                        Url = new Uri("http://opensource.org/licenses/MIT"),
                    }
                },
                Servers = DefaultOpenApiConfigurationOptions.GetHostNames(),
                OpenApiVersion = DefaultOpenApiConfigurationOptions.GetOpenApiVersion(),
                IncludeRequestingHostName = DefaultOpenApiConfigurationOptions.IsFunctionsRuntimeEnvironmentDevelopment(),
                ForceHttps = DefaultOpenApiConfigurationOptions.IsHttpsForced(),
                ForceHttp = DefaultOpenApiConfigurationOptions.IsHttpForced(),
            };

            return options;
        });
    })
    .ConfigureFunctionsWorkerDefaults(w => 
        w
            .UseMiddleware<ErrorExposingMiddleware>()
            .UseMiddleware<PrintEnvVarsMiddleware>())
    .Build();

await host.RunAsync();

但是,当我在本地构建并运行代码时,控制台中没有出现 OpenApi 端点,如果我尝试访问 /api/swagger/ui,我会得到 404。可能是因为我的代码布局有点不-标准?

| - Program.cs
| - local.settings.json
| | - Functions
| | | - Registration
| | | | - RegistrationFunction.cs

或者也许是因为我正在运行

<TargetFramework>net8.0</TargetFramework>
并且此处的所有示例都使用 v7 max:https://github.com/Azure/azure-functions-openapi-extension/blob/main/samples/Microsoft.Azure。 Functions.Worker.Extensions.OpenApi.FunctionApp.OutOfProc/Microsoft.Azure.Functions.Worker.Extensions.OpenApi.FunctionApp.OutOfProc.csproj ?

c# azure azure-functions openapi
1个回答
0
投票

通过使用下面的代码,我也能够获取 OpenAPI 端点和响应。

我在上述文件中有以下代码。

函数.cs -

using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Azure.Functions.Worker;
using Microsoft.Azure.WebJobs.Extensions.OpenApi.Core.Attributes;
using Microsoft.Azure.WebJobs.Extensions.OpenApi.Core.Enums;
using Microsoft.Extensions.Logging;
using Microsoft.OpenApi.Models;
using System.Net;

namespace FunctionApp62
{
    public class Function1
    {
        private readonly ILogger<Function1> _logger;

        public Function1(ILogger<Function1> logger)
        {
            _logger = logger;
        }

        [OpenApiOperation(operationId: "greeting", tags: new[] { "greeting" }, Summary = "Greetings", Description = "This shows a welcome message.", Visibility = OpenApiVisibilityType.Important)]
        [OpenApiSecurity("function_key", SecuritySchemeType.ApiKey, Name = "code", In = OpenApiSecurityLocationType.Query)]
        [OpenApiResponseWithBody(statusCode: HttpStatusCode.OK, contentType: "text/plain", bodyType: typeof(string), Summary = "The response", Description = "This returns the response")]
        [Function("Function1")]
        public IActionResult Run([HttpTrigger(AuthorizationLevel.Anonymous, "get", "post")] HttpRequest req)
        {
            _logger.LogInformation("C# HTTP trigger function processed a request.");
            return new OkObjectResult("Welcome to Azure Functions!");
        }
    }
}

Program.cs -

using Microsoft.Azure.Functions.Worker.Extensions.OpenApi.Extensions;
using Microsoft.Extensions.Hosting;

var host = new HostBuilder()
    .ConfigureFunctionsWorkerDefaults(worker => worker.UseNewtonsoftJson())
    .ConfigureOpenApi()
    .Build();

host.Run();

.csproj -

<Project Sdk="Microsoft.NET.Sdk">
  <PropertyGroup>
    <TargetFramework>net8.0</TargetFramework>
    <AzureFunctionsVersion>v4</AzureFunctionsVersion>
    <OutputType>Exe</OutputType>
    <ImplicitUsings>enable</ImplicitUsings>
    <Nullable>enable</Nullable>
  </PropertyGroup>
  <ItemGroup>
    <PackageReference Include="Microsoft.Azure.Functions.Worker" Version="1.22.0" />
    <PackageReference Include="Microsoft.Azure.Functions.Worker.Extensions.OpenApi" Version="2.0.0-preview2" />
    <PackageReference Include="Microsoft.Azure.Functions.Worker.Sdk" Version="1.17.3-preview1" />
  </ItemGroup>
  <ItemGroup>
    <None Update="host.json">
      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
    </None>
    <None Update="local.settings.json">
      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
      <CopyToPublishDirectory>Never</CopyToPublishDirectory>
    </None>
  </ItemGroup>
  <ItemGroup>
    <Using Include="System.Threading.ExecutionContext" Alias="ExecutionContext" />
  </ItemGroup>
</Project>

我能够获得如下所示的端点-

Azure Functions Core Tools
Core Tools Version:       4.0.5611 Commit hash: N/A +591b8ae*****fe0655 (64-bit)
Function Runtime Version: 4.31.1.22191

[2024-04-29T06:15:29.663Z] Found C:\Users\******\FunctionApp62\FunctionApp62\FunctionApp62.csproj. Using for user secrets file configuration.
[2024-04-29T06:15:32.569Z] Azure Functions .NET Worker (PID: 12100) initialized in debug mode. Waiting for debugger to attach...
[2024-04-29T06:15:32.620Z] Worker process started and initialized.

Functions:

        Function1: [GET,POST] http://localhost:7296/api/Function1

        RenderOAuth2Redirect: [GET] http://localhost:7296/api/oauth2-redirect.html

        RenderOpenApiDocument: [GET] http://localhost:7296/api/openapi/{version}.{extension}

        RenderSwaggerDocument: [GET] http://localhost:7296/api/swagger.{extension}

        RenderSwaggerUI: [GET] http://localhost:7296/api/swagger/ui

For detailed output, run func with --verbose flag.
[2024-04-29T06:15:37.684Z] Host lock lease acquired by instance ID '000000000000000000000000BF6D1ED5'.
[2024-04-29T06:16:04.141Z] Executing 'Functions.RenderSwaggerUI' (Reason='This function was programmatically called via the host APIs.', Id=8f370a16-bd07-4fae-b900-2ea3b65dc81f)
[2024-04-29T06:16:04.447Z] SwaggerUI page was requested.
[2024-04-29T06:16:05.120Z] Executed 'Functions.RenderSwaggerUI' (Succeeded, Id=8f370a16-bd07-4fae-b900-2ea3b65dc81f, Duration=996ms)
[2024-04-29T06:16:05.246Z] Executing 'Functions.RenderSwaggerDocument' (Reason='This function was programmatically called via the host APIs.', Id=bfb3de02-493d-496c-bd0e-2b2bcf78fdf3)
[2024-04-29T06:16:05.257Z] swagger.json was requested.
[2024-04-29T06:16:05.931Z] Executed 'Functions.RenderSwaggerDocument' (Succeeded, Id=bfb3de02-493d-496c-bd0e-2b2bcf78fdf3, Duration=686ms)
[2024-04-29T06:17:20.115Z] Executing 'Functions.Function1' (Reason='This function was programmatically called via the host APIs.', Id=14303a95-f684-48a9-9475-1836ad752a5d)
[2024-04-29T06:17:20.140Z] C# HTTP trigger function processed a request.
[2024-04-29T06:17:20.211Z] Executed 'Functions.Function1' (Succeeded, Id=14303a95-f684-48a9-9475-1836ad752a5d, Duration=96ms)

enter image description here

enter image description here

© www.soinside.com 2019 - 2024. All rights reserved.