I don't understand why my Minimal API doesn't bring up swagger

Falanga, Rod, DOH 400 Reputation points
2025-10-20T16:36:58.91+00:00

I have a Blazor Web Application I've been working on (Visual Studio 2022 and .NET 9). This application had 4 VS projects in the solutions, one of them was a Minimal API app. Due to problems I encountered with that configuration, I have decided to migrate the Minimal API project out of that VS solution, into a new VS solution that has only one VS project, which is the Minimal API from the other VS solution.

However, I've found that when debugging the new VS solution it does not bring up Swagger. I've tried using GitHub Copilot, but that just resulted in following Copilot running along a rabbit trail. So, I'm posting the Program.cs file from the new VS solution. Please review and tell me what I'm doing wrong.

using AutoMapper;
using Azure.Identity;
using Azure.Extensions.AspNetCore.Configuration.Secrets;
using FPTimetrackCore.DataActionsAPI;
using FPTimetrackCore.DataActionsAPI.DTO;
using FPTimetrackCore.DataActionsAPI.Model;
using Microsoft.EntityFrameworkCore;
using System.Linq;
using System.Net;
using System;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Configuration;
using Microsoft.OpenApi.Models;

var builder = WebApplication.CreateBuilder(args);

// -- Key Vault Configuration --
var isDev = builder.Environment.IsDevelopment();
var vaultUri = Environment.GetEnvironmentVariable("VaultUri");

if(!isDev && !string.IsNullOrWhiteSpace(vaultUri))
{
    builder.Configuration.AddAzureKeyVault(new Uri(vaultUri), new DefaultAzureCredential());
}

builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen(c =>
{
    c.SwaggerDoc("v1", new OpenApiInfo
    {
        Title = "FPTimetrackCore.DataActionsAPI",
        Version = "v1"
    });
});
builder.Services.AddAutoMapper(typeof(MappingConfig));


builder.Configuration.AddAzureKeyVault(
    new Uri($"https://this.is.not.real/"),
    new DefaultAzureCredential());

var app = builder.Build();

// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
{
    app.UseSwagger();
    app.UseSwaggerUI(c =>
    {
        c.SwaggerEndpoint("/swagger/v1/swagger.json", "FPTimetrackCore.DataActionsAPI v1");
    });
}

app.UseHttpsRedirection();

static SaveData GetConnectionObject(bool prodConn)
{
    IConfiguration configuration = null;
    if (prodConn)   // Is this really the best way to do this?
    {
        configuration = new ConfigurationBuilder()
            .AddJsonFile("appsettings.json")
            .AddEnvironmentVariables()
            .Build();
    }
    else
    {
        configuration = new ConfigurationBuilder()
            .AddJsonFile("appsettings.Development.json")
            .AddEnvironmentVariables()
            .Build();
    }
    var lib = new SaveData(configuration);
    return lib;
}

// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
{
    app.UseSwagger();
    app.UseSwaggerUI(c =>
    {
        c.SwaggerEndpoint("/swagger/v1/swagger.json", "FPTimetrackCore.API v1");
    });
}

const int MAX_MONTHS = -3; // This is the number of months to go back from today, from the original Family Planning Timetrack application.

app.MapGet("/api/getphdusers/{prodConn}/{Active}", (IConfiguration _config, IMapper _mapper, bool prodConn = true, bool Active = true) =>
{
    TimetrackContext ctx = GetDbContext(_config, prodConn);
    IQueryable<PhdUser> phdUsers = null;
    if (Active)
    {
        phdUsers = ctx.PhdUsers.Where(a => a.PhdUserStatus == "Active");
    }
    else
    {
        phdUsers = ctx.PhdUsers;
    }
    IOrderedQueryable<PhdUser> users = phdUsers.OrderBy(o => o.PhdUserName);
    var phdUserArray = users.ToArray();
    var PhdUsersDTOArray = _mapper.Map<PhdUserDTO[]>(phdUserArray);
    APIResponse response = new()
    {
        IsSuccess = true,
        Result = PhdUsersDTOArray,
        StatusCode = System.Net.HttpStatusCode.OK
    };
    return Results.Ok(response);
})
    .WithName("GetPhdUsers")
    .WithOpenApi()
    .Produces<APIResponse>(StatusCodes.Status200OK);

// Other endpoints go here, but omitted for brevity.

app.Run();

Developer technologies | ASP.NET | ASP.NET API
{count} votes

2 answers

Sort by: Most helpful
  1. Jack Dang (WICLOUD CORPORATION) 2,400 Reputation points Microsoft External Staff
    2025-10-21T03:00:43.65+00:00

    Hi @Falanga, Rod, DOH ,

    Thanks for sharing your code and detailed explanation. Based on your Program.cs, the issue is that Swagger is only configured to run in the Development environment, so if your environment isn’t detected as Development, Swagger won’t appear when you debug the API.

    Let’s go through a few points to check:

    1. Confirm your environment setting

    In Visual Studio, Swagger only appears when

    if (app.Environment.IsDevelopment())
    

    is true. Check your launch profile under: Properties → launchSettings.json

    Make sure it contains:

    "environmentVariables": {
      "ASPNETCORE_ENVIRONMENT": "Development"
    }
    

    If it’s set to "Production" or missing, Swagger will not load.

    1. Remove duplicate Swagger configuration blocks

    You have two identical blocks for:

    if (app.Environment.IsDevelopment())
    {
        app.UseSwagger();
        app.UseSwaggerUI(...);
    }
    

    Remove one of them - only one is needed. Having it twice won’t break Swagger, but it’s redundant and can cause confusion.

    1. Test Swagger endpoint directly

    After launching your Minimal API, try navigating manually to:

    https://localhost:<port>/swagger
    

    If you still don’t see the UI, check the console output to confirm the app is running in Development mode.

    1. Reference documentation

    You can review this step-by-step guide on enabling Swagger in Minimal APIs: Add OpenAPI support to a minimal API

    Your Swagger setup is correct - it’s just not being triggered because your environment likely isn’t set to Development after moving the project to a new solution. Once you fix that in launchSettings.json, Swagger should appear when you debug.

    Hope this helps! If my answer was helpful - kindly follow the instructions here so others with the same problem can benefit as well.

    1 person found this answer helpful.

  2. Bruce (SqlWork.com) 81,191 Reputation points Volunteer Moderator
    2025-10-20T18:46:11.45+00:00
    0 comments No comments

Your answer

Answers can be marked as 'Accepted' by the question author and 'Recommended' by moderators, which helps users know the answer solved the author's problem.