- Blog
#Azure
How to plan your Azure budget for 2025-2026 with FinOps
- 11/12/2024
Reading time 5 minutes
The goal is to automatically publish each ASP.NET Core Controller as individual API in Azure API Management from Azure DevOps pipelines.
Swashbuckle can be used to generate OpenAPI Specification (OAS) of ASP.NET Core application. There is also dotnet tool called swagger that can be used to generate OAS from command line.
dotnet swagger tofile --output swagger.V1.json My.ApibinReleasenetcoreapp3.1My.Api.dll V1
Generated OAS can be used to import API to Azure API Management.
Here is how APIs are shown in Azure API management before doing any changes.
All this is cool, but it would be even better to have each API inside OAS as separate API in Azure API Management.
The generated OAS contains all APIs in single file.
"paths": { "/api/Users": {...}, "/api/Users/search": {...}, "/api/Roles": {...} }
Server address is also included in OpenAPI specification file.
"servers": [ { "url": "http://localhost:10586/" } ]
I built simple command line application called SwaggerCli that
In Users -endpoint example, Users API -specific OAS contains
"paths": { "/": {...}, "/search": {...}, }, "servers": [ { "url": "http://localhost:10586/api/Users" } ]
All Roles -API specific data has been removed, and server url contains /api/Users path.
The API specific OAS files are generated in build pipeline, and published as build results.
Following changes were required in build pipeline:
dotnet tool install Swashbuckle.AspNetCore.Cli --version 5.6.2
Steps 5-7 as YAML:
- task: CmdLine@2 displayName: Create specs directory inputs: script: 'mkdir $(Pipeline.Workspace)specs' - task: DotNetCoreCLI@2 displayName: 'Generate OpenAPI spec document' inputs: command: custom custom: swagger arguments: 'tofile --output $(Pipeline.Workspace)specs${{parameters.projectName}}.V1.json ${{ parameters.projectName }}.ApibinReleasenetcoreapp3.1${{parameters.projectName}}.Api.dll V1' - task: DotNetCoreCLI@2 displayName: "Divide OpenAPI spec document to API specific documents" inputs: command: custom custom: SwaggerClibinReleasenetcoreapp3.1SwaggerCli.dll arguments: '--inputFilename $(Pipeline.Workspace)specs${{parameters.projectName}}.V1.json --outputPath $(Pipeline.Workspace)specs' - task: CmdLine@2 displayName: Delete original OpenAPI spec file inputs: script: 'del $(Pipeline.Workspace)specs${{parameters.projectName}}.V1.json' - task: PublishPipelineArtifact@1 displayName: "Publish Artifact: OpenAPI specs" inputs: targetPath: '$(Pipeline.Workspace)specs' artifactName: 'OpenAPI'
For each API specific OAS, new task in Release pipeline was added:
- task: AzurePowerShell@4 displayName: Update API Management for Users API inputs: azureSubscription: '${{ parameters.azureSubscriptionName }}' scriptType: 'FilePath' scriptPath: '$(Pipeline.Workspace)/Deployment/Scripts/Update-ApimOpenAPISpec.ps1' scriptArguments: '-ResourceGroupName "${{ parameters.resourceGroupName }}" -ServiceName "${{ parameters.apiManagementName }}" -ServiceUrl "${{ parameters.apiManagementServiceUrl }}api/users" -ApiPath "api/users" -ApiName "Users" -SpecificationFilePath $(Pipeline.Workspace)OpenAPIUsers.${{ parameters.environment }}.json' errorActionPreference: 'stop' azurePowerShellVersion: 'latestVersion'
Task is calling PowerShell script to import OpenAPI specification into Azure API Management:
[CmdletBinding()] Param( [string] [Parameter(Mandatory=$true)] $ResourceGroupName, [string] [Parameter(Mandatory=$true)] $ServiceName, [string] [Parameter(Mandatory=$true)] $ServiceUrl, [string] [Parameter(Mandatory=$true)] $ApiPath, [string] [Parameter(Mandatory=$true)] $ApiName, [string] [Parameter(Mandatory=$true)] $SpecificationFilePath ) $apiMgmtContext = New-AzApiManagementContext -ResourceGroupName $ResourceGroupName -ServiceName $ServiceName $api = Get-AzApiManagementApi -Context $apiMgmtContext -Name $ApiName if ($null -eq $api) { $api = New-AzApiManagementApi -Context $apiMgmtContext -Name $ApiName -ServiceUrl $ServiceUrl -Path $ApiPath -Protocols @("https") } Import-AzApiManagementApi -Context $apiMgmtContext ` -SpecificationPath $SpecificationFilePath ` -SpecificationFormat 'OpenApi' ` -Path $api.Path ` -ApiId $api.ApiId
Here is how APIs are shown in Azure API management after changes were made.
Now I can define multiple API Management Products and include selected APIs for each Product. This was not possible without importing each ASP.NET Core Controller into own API Management API.
Thanks Twitter user @domze for great article below, it helped a lot to accomplish the goal!
Automating your OpenAPI updates to API Management through your CI/CD pipeline
Our newsletters contain stuff our crew is interested in: the articles we read, Azure news, Zure job opportunities, and so forth.
Please let us know what kind of content you are most interested about. Thank you!