I'm getting the above error message when publishing my .NET 6 API project to Azure API Management Service.
On analysis, I understood the reason for the issue is, while configuring services (for DI) in 'Program.cs', we are trying to fetch an Environment variable, which returns null and an exception is thrown. Somehow, this prevents creating the swagger.json file.
Two things that I'm trying to understand are,
Fetching the environment variable using "Environment.GetEnvironmentVariable()" is not fetching the value in 'Program.cs', but the same works in controller action method.
If I comment out everything related to swagger, this issue is not occurring.
In the Publish Window, under 'Service Dependencies', I have configured my APIM resource details to deploy/update the APIs in the APIM directly.
Below is a sample code screeshot which replicates the issue.
Please share your thoughts.
Thanks!
Initially even I got the same error with the given code.
The issue is at getting the Environment Variable.
To get the Key Value(Environment Variable) from Azure App settings, use the below line of code.
var key1 = app.Configuration.GetValue<String>("KEY");
My Azure App Setting:
Change app.UseSwaggerUI to
app.UseSwaggerUI(options =>
{
options.SwaggerEndpoint("/swagger/v1/swagger.json", "v1");
options.RoutePrefix = string.Empty;
});
My Program.cs
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddControllers();
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();
var app = builder.Build();
if (string.IsNullOrEmpty(app.Configuration.GetValue<String>("KEY")))
throw new Exception("Error");
app.UseSwagger();
app.UseSwaggerUI(options =>
{
options.SwaggerEndpoint("/swagger/v1/swagger.json", "v1");
options.RoutePrefix = string.Empty;
});
app.UseHttpsRedirection();
app.UseAuthorization();
app.MapControllers();
app.Run();
My appsettings.json
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
},
"AllowedHosts": "*",
"KEY": "Your Connection String"
}
Make sure you have installed the Swashbuckle.AspNetCore latest package.
.csproj file
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.2.3" />
Output:
I was creating documentation for Nest.js API using Swagger. The problem is what I removed documentation from this DTO or model, in swagger UI docs I can see it as empty object.
For example:
import { IsNotEmpty } from 'class-validator';
export class PostDto {
#IsNotEmpty()
readonly title: string;
#IsNotEmpty()
readonly content: string;
#IsNotEmpty()
readonly description: string;
}
Also I was trying to change name of this entity, using incognito mode, reinstall node_modules, but it didn't work. If I change name of this entity, it also changes there. What's wrong?
What I want to do, is by removing this documentation decorators, not to see those empty objects.
There is a CLI plugin provided with the #nestjs/swagger which will automatically add the annotations using reflection.
This means you NO LONGER need to individually annotate each property using #ApiProperty() etc.
The plugin is opt-in and not active by default.
In your nest-cli.json add:
{
"collection": "#nestjs/schematics",
"sourceRoot": "src",
"compilerOptions": {
"plugins": ["#nestjs/swagger"]
}
}
You can also change the default options:
"plugins": [
{
"name": "#nestjs/swagger",
"options": {
"classValidatorShim": false,
"introspectComments": true
}
}
]
See https://docs.nestjs.com/openapi/cli-plugin
Troubleshooting: if you are running in dev mode, may need to stop/start.
Trigger-happy duplicate closers kindly read the question thoroughly and refrain from incorrectly marking it as a duplicate.
This question is not a general question about getting the environment name. I am aware of many ways. The question is how to get a value that is guaranteed to be consistent with the value that will eventually be made available from HostingEnvironment.EnvironmentName
This question is about console apps. It is not about web apps, not even if you just figured out how to do this with web apps and you want to tell everyone. There is no Startup.cs involved. Answers that depend on the default web host fail to address the question.
The host builder setup looks like this.
var hostBuilder = Host.CreateDefaultBuilder(args);
hostBuilder
.ConfigureHostConfiguration(configurationBuilder =>
{
configurationBuilder.AddJsonFile("hostsettings.json", optional: true);
configurationBuilder.AddEnvironmentVariables(prefix: "AED_COORDINATOR_");
configurationBuilder.AddCommandLine(args);
})
.ConfigureAppConfiguration(configurationBuilder =>
{
var env = Environment.GetEnvironmentVariable($"{ENV_PREFIX}ENVIRONMENT");
configurationBuilder
.AddJsonFile("appSettings.json", false, true)
.AddJsonFile($"appSettings.{env}.json", true, true);
})
...
With this in launch.json
{
"version": "0.2.0",
"configurations": [
{
"name": ".NET Core Launch (console)",
"type": "coreclr",
"request": "launch",
"preLaunchTask": "build",
"program": "${workspaceFolder}/bin/Debug/netcoreapp3.1/aed.coordinator.dll",
"args": [
"--environment=Production"
],
"cwd": "${workspaceFolder}",
"console": "integratedTerminal",
"stopAtEntry": false,
"env": {
"AED_COORDINATOR_ENVIRONMENT": "Development"
}
},
running it produces this.
The problem is that appSettings.Development.json is loaded because Environment.GetEnvironmentVariable($"{ENV_PREFIX}ENVIRONMENT") does not take into account the command line arguments.
I am aware that can extend this code to explicitly consider the command line arguments, but reliable parsing of command line arguments is non-trivial and anyway what's the point of having a builder if you have to in-line everything? Worse, they can disagree.
So, is there some way to use the builder (which is already configured in this respect) to resolve the environment?
You can't invoke .Build() more than once so it's not possible to partly configured the builder, construct an intermediate host, pull the resolved environment out of it and then finish configuring.
It is possible to do this.
var ENV_PREFIX = "AED_COORDINATOR_";
string env;
using (var envHost = Host.CreateDefaultBuilder(args).ConfigureHostConfiguration(configurationBuilder =>
{
configurationBuilder.AddJsonFile("hostsettings.json", optional: true);
configurationBuilder.AddEnvironmentVariables(prefix: ENV_PREFIX);
configurationBuilder.AddCommandLine(args);
}).Build())
env = envHost.Services.GetService<IHostEnvironment>().EnvironmentName;
This resolves env in advance and properly disposes builder and intermediate host, and the rest of the code is more or less unchanged.
However, it is not necessary to do it.
In the lambda supplied to hostBuilder.ConfigureServices() I was inspecting the services and found that appSettings.{env}.json is magically added anyway — while the above code is successful, both appSettings.json and appSettings.{env}.json appeared twice as providers — and the host builder used the correct environment, so the entirety of
.ConfigureAppConfiguration(configurationBuilder =>
{
configurationBuilder
.AddJsonFile("appSettings.json", false, true)
.AddJsonFile($"appSettings.{env}.json", true, true);
})
is unnecessary.
Which means that provided you get this part right
.CreateDefaultBuilder(args).ConfigureHostConfiguration(configurationBuilder =>
{
configurationBuilder.AddJsonFile("hostsettings.json", optional: true);
configurationBuilder.AddEnvironmentVariables(prefix: ENV_PREFIX);
configurationBuilder.AddCommandLine(args);
})
you don't need the rest.
Later code can even use the config:
.ConfigureServices((hostContext, services) =>
{
services.AddConfig(hostContext.Configuration);
services.AddHostedService<Worker>();
});
The AddConfig method is an extension method that prepares the options classes for use by dependency injection.
public static IServiceCollection AddConfig(this IServiceCollection services, IConfiguration config)
{
var section = config.GetSection(MosquittoOptions.SectionName);
services.Configure<MosquittoOptions>(section);
section = config.GetSection(ServicesLayerOptions.SectionName);
services.Configure<ServicesLayerOptions>(section);
return services;
}
I added the following section in project.json.
"commands": {
"run": "run server.urls=http://localhost:8082",
"web": "Microsoft.AspNet.Hosting --server Microsoft.AspNet.Server.Kestrel --server.urls http://localhost:8082",
"weblistener": "Microsoft.AspNet.Hosting --server WebListener --server.urls http://localhost:8082"
},
However, it still shows "Now listening on: http://localhost:5000" when run it using dotnet myapp.dll?
BTW, will clients from other machine be able to access the service?
Yes this will be accesible from other machines if you bind on any external IP address. For example binding to http://*:80 . Note that binding to http://localhost:80 will only bind on 127.0.0.1 interface and therefore will not be accesible from other machines.
Visual Studio is overriding your port. You can change VS port editing this file Properties\launchSettings.json or else set it by code:
var host = new WebHostBuilder()
.UseKestrel()
.UseContentRoot(Directory.GetCurrentDirectory())
.UseIISIntegration()
.UseStartup<Startup>()
.UseUrls("http://localhost:80") // <-----
.Build();
host.Run();
A step by step guide using an external config file is available here.
It's working to me.
I use Asp.net core 2.2 (this way supported in asp.net core 2.1 and upper version).
add Kestrel section in appsettings.json file.
like this:
{
"Kestrel": {
"EndPoints": {
"Http": {
"Url": "http://localhost:4300"
}
}
},
"Logging": {
"LogLevel": {
"Default": "Warning"
}
},
"AllowedHosts": "*"
}
and in Startup.cs:
public Startup(IConfiguration configuration, IHostingEnvironment env)
{
var builder = new ConfigurationBuilder()
.SetBasePath(env.ContentRootPath)
.AddJsonFile("appsettings.json", optional: false, reloadOnChange: true)
.AddEnvironmentVariables();
Configuration = builder.Build();
}
Use simply dotnet YouApp.dll --urls http://0.0.0.0:80.
P.S. I don't know why I need to google this everytime and everytime it doesn't show up. So here it is.
In Asp.net core 2.0 WebApp, if you are using visual studio search LaunchSettings.json. I am adding my LaunchSettings.json, you can change port no as u can see.
In visual studio 2017 we can change the port number from LaunchSetting.json
In Properties-> LaunchSettings.json.
Open LaunchSettings.json and change the Port Number.
Change the port Number in json file
Use following one line of code .UseUrls("http://*:80") in Program.csThus changing .UseStartup<Startup>() to.UseStartup<Startup>()
.UseUrls("http://*:80")
3 files have to changed appsettings.json (see the last section - kestrel ), launchsettings.json - applicationurl commented out, and a 2 lines change in Startup.cs
Add below code in appsettings.json file and port to any as you wish.
},
"Kestrel": {
"Endpoints": {
"Http": {
"Url": "http://localhost:5003"
}
}
}
}
Modify Startup.cs with below lines.
using Microsoft.AspNetCore.Server.Kestrel.Core;
services.Configure<KestrelServerOptions>(Configuration.GetSection("Kestrel"));
Go to your program.cs file add UseUrs method to set your url, make sure you don't use a reserved url or port
public class Program
{
public static void Main(string[] args)
{
BuildWebHost(args).Run();
}
public static IWebHost BuildWebHost(string[] args) =>
WebHost.CreateDefaultBuilder(args)
.UseStartup<Startup>()
// params string[] urls
.UseUrls(urls: "http://localhost:10000")
.Build();
}
We can use this command to run our host project via Windows Powershell without IIS and visual studio on a separate port. Default of krestel web server is 5001
$env:ASPNETCORE_URLS="http://localhost:22742" ; dotnet run
will clients from other machine be able to access the service?
add to appsettings.json
"Urls": "http://0.0.0.0:8082",
All the other answer accounts only for http URLs. If the URL is https, then do as follows,
Open launchsettings.json under Properties of the API project.
Change the sslPort under iisSettings -> iisExpress
A sample launchsettings.json will look as follows
{
"iisSettings": {
"iisExpress": {
"applicationUrl": "http://localhost:12345",
"sslPort": 98765 <== Change_This
}
},
in appsetting.json
{
"DebugMode": false,
"Urls": "http://localhost:8082"
}
Building on #Abdus Salam Azad's answer...
In Visual Studio 2022 if you right click an ASP.NET Core Web API project for example, you have access to this UI where you can set up ASPNETCORE variables like this:
There you can enter a custom URL:port for ASPNETCORE_URLS like this:
The following works in ASP.Net Core 6.0. Inside Program.cs have this:
var builder = WebApplication.CreateBuilder(args);
if (!app.Environment.IsDevelopment())
{
builder.WebHost.UseUrls("http://*:80", "https://*.443");
}
I find it is useful to wrap it in a conditional statement when publishing to production, but this isn't necessary.
This works running from a Kestrel server on Mac OS 12.
you can also code like this
IConfiguration config = new ConfigurationBuilder()
.AddCommandLine(args)
.Build();
var host = new WebHostBuilder()
.UseConfiguration(config)
.UseKestrel()
.UseContentRoot(Directory.GetCurrentDirectory())
.UseStartup<Startup>()
.Build();
and set up your application by command line :dotnet run --server.urls http://*:5555
in your hosting.json
replace"Url": "http://localhost:80" by"Url": "http://*:80" and you will be able now access to your application by http://your_local_machine_ip:80 for example http://192.168.1.4:80
If you want to run on a specific port 60535 while developing locally but want to run app on port 80 in stage/prod environment servers, this does it.
Add to environmentVariables section in launchSettings.json
"ASPNETCORE_DEVELOPER_OVERRIDES": "Developer-Overrides",
and then modify Program.cs to
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseKestrel(options =>
{
var devOverride = Environment.GetEnvironmentVariable("ASPNETCORE_DEVELOPER_OVERRIDES");
if (!string.IsNullOrWhiteSpace(devOverride))
{
options.ListenLocalhost(60535);
}
else
{
options.ListenAnyIP(80);
}
})
.UseStartup<Startup>()
.UseNLog();
});
Maybe it's because I am not using Core yet. My project didn't have a LaunchSettings.json file but that did prompt me to look in the project properties. I found it under the Web tab and simply changed the project url:
I had a similar issue with a Kubernetes deployment after upgrading to .NET 6. The solution was simply to add the following environment variable to the deployment:
- name: Kestrel__Endpoints__Http__Url
value: http://0.0.0.0:80
This will work anywhere else where you can use an environment variable
Core 6.0 -->
Without any JSON setting changes we do some thing like this..
I also commented some code bcoz I don't have certificate. we can run it any port.
builder.WebHost.ConfigureKestrel((context, serverOptions) =>
{
// serverOptions.Listen(System.Net.IPAddress.Loopback, 5003);
serverOptions.Listen(System.Net.IPAddress.Loopback, 8086, listenOptions =>
{
listenOptions.UseHttps();
//listenOptions.UseHttps("testCert.pfx", "testPassword");
});
});
I created my project using Visual Studio 2022, so in Project/Properties/launchSettings.json there are two parts for this topic:
1- for lunching in IISExpress :
"iisSettings": {
..
"iisExpress": {
"applicationUrl": "http://localhost:31520",
"sslPort": 44346
}
},
2- for lunching through IDE:
"profiles": {
"MaxTemplate.API": {
...
"applicationUrl": "https://localhost:7141;http://localhost:5141",
...
}
},
For example you can change the port 7141 to 5050 and run the project again.
In asp.net core 6
app.Run("https://*:25565");
or in my case for deploying on heroku
app.Run("https://*:"+Environment.GetEnvironmentVariable("PORT"));
Don't have enough rep to add this as a comment, but I want to add that the WebHost.UseUrls() in .net core 6 can be set using a combination of IPAddress and IPEndPoint in file Program.cs
if (!builder.Environment.IsDevelopment()) // app in release
{
// listen to any ip on port 80 for http
IPEndPoint ipEndPointHttp = new IPEndPoint(IPAddress.Any, 80),
// listen to any ip on port 443 for https
ipEndPointHttps = new IPEndPoint(IPAddress.Any, 443);
builder.WebHost.UseUrls($"http://{ipEndPointHttp}",
$"https://{ipEndPointHttps}");
// enforce ssl when in release
builder.Services.AddHsts(options =>
{
options.Preload = true;
options.IncludeSubDomains = true;
options.MaxAge = TimeSpan.FromDays(3); // a commonly used value is one year.
});
// redirect to specific https port
builder.Services.AddHttpsRedirection(options =>
{
options.RedirectStatusCode = (int)HttpStatusCode.PermanentRedirect;
options.HttpsPort = ipEndPointHttps.Port;
});
}
else // app in debug
{
// listen to localhost on port 8081 for http
IPEndPoint ipEndPointHttp = new IPEndPoint(IPAddress.Loopback, 8081),
// listen to localhost on port 5001 for https
ipEndPointHttps = new IPEndPoint(IPAddress.Loopback, 5001);
builder.WebHost.UseUrls($"http://{ipEndPointHttp}",
$"https://{ipEndPointHttps}");
// redirect to specific https port
builder.Services.AddHttpsRedirection(options =>
{
options.RedirectStatusCode = (int)HttpStatusCode.TemporaryRedirect;
options.HttpsPort = ipEndPointHttps.Port;
});
}
... // rest of configuration
app.UseHttpsRedirection(); // set redirection to https if url is in http
....
Also note that using these values new IPEndPoint(IPAddress.Any, 80), *:80, ::80 are all equivalent, but I prefer IPEndPoint since it is more verbose
If a custom ip address (ex: 192.168.1.200) is needed other than IPAddress.Any or IPAddress.Loopback, a new address can be set using IPAddress.Parse("192.168.1.200")
"ConnectionStrings": {
"DefaultConnection": "Server=(localdb)\\mssqllocaldb; Database=ABC; Trusted_Connection=True; MultipleActiveResultSets=true"}
I am working with ASP.NET Core MVC. I have this connection string in my appsettings.json file but it doesn't seem to work. While running "dotnet ef database update" from cmd, I am getting this error keyword not supported: 'server.'. What's wrong with it?
Apologies! In my ConfigureServices method in Startup.cs, I was using SQLite database provider
services.AddDbContext<ApplicationDbContext>(options => options.UseSqlite(Configuration.GetConnectionString("DefaultConnection")))
I changed it to the following, and it worked with my connection string.
services.AddDbContext<ApplicationDbContext>(options => options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")))
The connection string should start of with Data Source=.
In Visual Studio if you open the SQL Server Object Explorer and click on the database you are wanting to connect to. The connection string will be displayed in the Properties window. The connections string should look something like this for localDb
Data Source=(localdb)\MSSQLLocalDB;Initial Catalog=DbName;Integrated Security=True;Connect Timeout=30;Encrypt=False;TrustServerCertificate=True;ApplicationIntent=ReadWrite;MultiSubnetFailover=Fals