I've created a very basic .net CORE WEB API, following a youtube guide.
Everything works fine when I debug from visual studio. it opens my browser and directs me to the swagger ui site.
But when I run outside visual studio, starting the exe from the build/bin folder I can't get to that swagger site.
in a command propt the exe file says it is listening on http on port 5000.
so while this is running go to this url http://localhost:5000/swagger/index.html
anyone have a hit on what I'm missing here ?
appsettings.json
{
"ConnectionStrings": {
"DefaultConnection": "server=myServerXXXX;database=myDataBaseXXXX;User ID=mydbUserXXXXX;Password=myPasswordXXX"
},
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
},
"AllowedHosts": "*"
}
program.cs
global using ShoppingList.API.Data;
global using Microsoft.EntityFrameworkCore;
var builder = WebApplication.CreateBuilder(args);
// Add services to the container.
builder.Services.AddControllers();
builder.Services.AddDbContext<ShoppingItemDataContext>(options =>
{
options.UseSqlServer(builder.Configuration.GetConnectionString("DefaultConnection"));
});
// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();
var app = builder.Build();
// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
{
app.UseSwagger();
app.UseSwaggerUI();
}
app.UseAuthorization();
app.MapControllers();
app.Run();
By default dotnet runs applications with the production environment and you have swagger enabled for the dev environment only. change the condition or pass the "--environment production" argument (or configure host environment: e.g. https://enlabsoftware.com/development/dotnet-core-environment-how-config-examples.html)
Related
Please help me launch the web service. I run the .exe file from the folder "\bin\Debug\net 5.0". When prompted https://localhost:5001/ gives an error.
I specified it in the spa.Options.sourcepath, but it didn't help.
the ERROR that I received is the following:
fail: Microsoft.AspNetCore.Server.Kestrel[13]
Connection id "0HMD866NK2DDC", Request id "0HMD866NK2DDC:00000011": An unhandled exception was thrown by the application.
System.InvalidOperationException: The SPA default page middleware could not return the default page '/index.html' because it was not found, and no other middleware handled the request.
Your application is running in Production mode, so make sure it has been published, or that you have built your SPA manually. Alternatively you may wish to switch to the Development environment.
This is the folder structure ClientApp Paths
My config code:
public void ConfigureServices(IServiceCollection services)
{
// получаем строку подключения из файла конфигурации
string connection = Configuration.GetConnectionString("DefaultConnection");
// добавляем контекст ApplicationContext в качестве сервиса в приложение
services.AddDbContext<ApplicationContext>(options =>
options.UseSqlServer(connection));
//чтобы кирилица нормально отображалась
services.AddWebEncoders(o =>
{
o.TextEncoderSettings = new TextEncoderSettings(UnicodeRanges.BasicLatin, UnicodeRanges.Cyrillic, UnicodeRanges.CyrillicExtendedA, UnicodeRanges.CyrillicExtendedB);
});
services.AddControllersWithViews();
// In production, the React files will be served from this directory
services.AddSpaStaticFiles(configuration =>
{
configuration.RootPath = "ClientApp/build";
});
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseExceptionHandler("/Error");
// The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseSpaStaticFiles();
app.UseRouting();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllerRoute(
name: "default",
pattern: "{controller}");
});
app.UseSpa(spa =>
{
spa.Options.SourcePath = "ClientApp";
if (env.IsDevelopment())
{
spa.UseReactDevelopmentServer(npmScript: "start");
}
});
}
React assets are not built by dotnet build or dotnet run not even with -c Release.
To also build the React assets you need dotnet publish.
This requirement may be masked by the presence of assets due to earlier use of dotnet publish. In that case they are potentially stale. Therefore, for any environment other than dev, you must use dotnet publish.
Why don't dotnet build and dotnet run build the React assets? In development you don't need them because you're using the dev server for hot swap. In production you're almost certainly using assets prepared by dotnet publish.
AspNetCore React can only find spa files in dev mode
I have an asp.net core app with a React front-end that uses IdentityServer. It was created using the scaffold templates in Visual Studio 2019. The app works great locally, but fails when I deploy to an AWS beanstalk. The line of code it fails on is in the Configure method of my Startup.cs. app.UseIdentityServer().
Somewhere within UseIdentityServer() there is a null reference exception that is not visible to me, and I cannot reproduce when testing locally on my development machine.
Here is my Configure() method in Startup.cs:
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
//app.UseDatabaseErrorPage();
}
else
{
app.UseExceptionHandler("/Error");
// The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
app.UseHsts();
}
//app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseSpaStaticFiles();
app.UseRouting();
app.UseAuthentication();
app.UseIdentityServer();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllerRoute(
name: "default",
pattern: "{controller}/{action=Index}/{id?}");
endpoints.MapRazorPages();
});
app.UseSpa(spa =>
{
spa.Options.SourcePath = "ClientApp";
if (env.IsDevelopment())
{
//spa.UseReactDevelopmentServer(npmScript: "start"); // Starts CRA automatically
spa.UseProxyToSpaDevelopmentServer("http://localhost:3000"); // Must manually start CRA (yarn start)
}
});
}
}
There error I get when checking the AWS beanstalk logs looks like this:
Jan 1 00:36:57 ip-172-30-2-135 web: #033[41m#033[30mfail#033[39m#033[22m#033[49m: Microsoft.AspNetCore.Diagnostics.ExceptionHandlerMiddleware[1]
Jan 1 00:36:57 ip-172-30-2-135 web: An unhandled exception has occurred while executing the request.
Jan 1 00:36:57 ip-172-30-2-135 web: System.NullReferenceException: Object reference not set to an instance of an object.
Jan 1 00:36:57 ip-172-30-2-135 web: at Microsoft.Extensions.DependencyInjection.IdentityServerBuilderConfigurationExtensions.<>c.b__10_2(IServiceProvider sp)
Jan 1 00:36:57 ip-172-30-2-135 web: at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitFactory(FactoryCallSite factoryCallSite, RuntimeResolverContext context)
Jan 1 00:36:57 ip-172-30-2-135 web: at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor`2.VisitCallSiteMain(ServiceCallSite callSite, TArgument argument)
Has anybody run into this before? This is something that is specific to deploying to an AWS beanstalk. If I remove the UseIdentityServer() call, the app publishes and runs fine in AWS Beanstalk. I am publishing to a Linux beanstalk if that makes a difference. There must be something that needs to be configured differently with IdentityServer when deployed to Linux, or maybe something specific with AWS Beanstalk.
When running locally on my development machine, it is on Windows 10 in case that helps.
Edit: Adding ConfigureServices() method
public void ConfigureServices(IServiceCollection services)
{
services.AddDbContext<BarristerContext>(options =>
options.UseNpgsql(
Configuration["Data:DefaultConnection:ConnectionString"]));
services.AddIdentity<ApplicationUser, IdentityRole>()
.AddEntityFrameworkStores<BarristerContext>()
.AddDefaultTokenProviders();
services.Configure<IdentityOptions>();
services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Latest)
.AddRazorPagesOptions(options =>
{
options.Conventions.AuthorizeAreaFolder("Identity", "/Account/Manage");
options.Conventions.AuthorizeAreaPage("Identity", "/Account/Logout");
});
services.ConfigureApplicationCookie(options =>
{
// Cookie settings
options.Cookie.HttpOnly = true;
options.ExpireTimeSpan = TimeSpan.FromMinutes(5);
options.LoginPath = $"/Identity/Account/Login";
options.LogoutPath = $"/Identity/Account/Logout";
options.AccessDeniedPath = $"/Identity/Account/AccessDenied";
});
// using Microsoft.AspNetCore.Identity.UI.Services;
services.AddSingleton<IEmailSender, EmailSender>();
services.AddIdentityServer(options =>
{
options.UserInteraction = new UserInteractionOptions()
{
LogoutUrl = "/Identity/account/logout",
LoginUrl = "/Identity/account/login",
LoginReturnUrlParameter = "returnUrl"
};
}).AddApiAuthorization<ApplicationUser, BarristerContext>();
services.AddAuthentication().AddIdentityServerJwt();
services.AddControllersWithViews();
services.AddRazorPages();
// In production, the React files will be served from this directory
services.AddSpaStaticFiles(configuration =>
{
configuration.RootPath = "ClientApp/build";
});
//services.AddDatabaseDeveloperPageExceptionFilter();
}
I will also note, I am targeting .Net 5 on this deployment, which according to AWS, should work fine as long as I select "Build self contained deployment bundle" when I publish via the AWS Toolkit for Visual Studio.
https://aws.amazon.com/blogs/developer/aws-elastic-beanstalk-adds-net-core-on-linux-platform/
The difference between my local host and the AWS Beanstalk that was causing the error on the Beanstalk, was the Nginx proxy. I had to account for this by adding the following middleware in my ConfigureServices() method of my Startup.cs.
services.Configure<ForwardedHeadersOptions>(options =>
{
options.ForwardedHeaders =
ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto;
});
This is due to:
When HTTPS requests are proxied over HTTP, the original scheme (HTTPS) is lost and must be forwarded in a header.
Because an app receives a request from the proxy and not its true source on the Internet or corporate network, the originating client IP address must also be forwarded in a header.
The following article gives more details: https://learn.microsoft.com/en-us/aspnet/core/host-and-deploy/proxy-load-balancer?view=aspnetcore-5.0
I am currently working on an .Net Core WebAPI Project (netcore 2.0) and I want to define the URL my application runs on in my appsettings.json file. I then use the following code in my Program.cs file:
var config = new ConfigurationBuilder()
.SetBasePath(Directory.GetCurrentDirectory())
.AddJsonFile("appsettings.json").Build();
var url = config.GetSection("WebAppSettings").GetValue<string>("Url");
var host = new WebHostBuilder()
.UseUrls(url)
.UseIISIntegration()
.UseKestrel()
.UseContentRoot(Directory.GetCurrentDirectory())
.ConfigureAppConfiguration((context, configBuilder) =>
{
configBuilder
.AddJsonFile("appsettings.json", optional: false, reloadOnChange: true)
.AddEnvironmentVariables();
})
.ConfigureLogging(logging =>
{
logging.ClearProviders();
logging.SetMinimumLevel(LogLevel.Trace);
})
.UseStartup<Startup>()
.UseNLog()
.Build();
host.Run();
My appsettings.json file:
{
"WebAppSettings": {
"Url": "http://localhost:5023"
}
}
However, when I run my application, it is only accessible on port 5022 (I previously set it to this but changed it to 5023 afterwards). When I look into my project properties and go to the "Debug" submenu, it states 5022 as the port. I tried erasing this property but it's an required field.
So how can I force Visual Studio to use the port I set in my appsettings.json file without it screwing up my settings?
IIS Express uses launchSettings.json, which itself is set via the project properties settings you mentioned. UseUrls only applies outside of Visual Studio/IIS Express.
From what I understand the correct way of setting listen ports for ASP Dotnet Core 2 preview 1/2 is by creating a Kestrel section in the appsettings.json in the following format:
"Kestrel": {
"EndPoints": { //Could also be Endpoints, it's a bit unclear
"Http": {
"Address": "127.0.0.1",
"Port": 9001 //the port you want Kestrel to run on
},
I have tried to set up the sample webapp on a Debian machine, but when I start the app, it writes out that the app is listing on port 5000, the default port..
I know that the appsettings.json is read, because when I change the logging level to Trace, I get more info upon startup, including that no Endpoints are found and the app will use the standard 5000 port.
I have tried to search the aspnet source code on Github, and I can find a area where the Kestrel section is read from configuration (https://github.com/aspnet/Identity/blob/e38759b8a2de1b7a4a1c19462e40214b43c1cf3b/samples/IdentityOIDCWebApplicationSample/MetaPackage/KestrelServerOptionsSetup.cs), but as you can see it looks like a sample project.
What am I missing, isn't this the standard way to configure Kestrel in ASP Dotnet core 2?
As mentioned in a comment on the accepted answer, 2.1 has support for appsettings.json, see https://blogs.msdn.microsoft.com/webdev/2018/02/02/asp-net-core-2-1-roadmap/#security
A working appsettings.json:
"Kestrel": {
"EndPoints": {
"Http": {
"Url": "http://localhost:5555"
}
}
}
This is for a Program.cs using (created by "dotnet new webapi"):
WebHost.CreateDefaultBuilder(args)
Relevant source code in GitHub
https://github.com/aspnet/MetaPackages/blob/master/src/Microsoft.AspNetCore/WebHost.cs#L163
options.Configure(builderContext.Configuration.GetSection("Kestrel"));
and https://github.com/aspnet/MetaPackages/blob/master/src/Microsoft.AspNetCore/WebHost.cs#L169
config.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
Support for Kestrel configuration via appsettings.json has been dropped in 2.0.
See this issue comment:
kestrel config file support was cut from 2.0.0. Config values need to be read manually in your initialization code.
To get around this, you can do something like this in program.cs:
public static IWebHost BuildWebHost(string[] args) =>
WebHost.CreateDefaultBuilder(args)
.UseStartup < Startup > ()
.UseKestrel((hostingContext, options) =>
{
if (hostingContext.HostingEnvironment.IsDevelopment) {
options.Listen(IPAddress.Loopback, 9001);
options.Listen(IPAddress.Loopback, 9002, listenOptions => {
listenOptions.UseHttps("certificate.pfx", "password");
});
}
})
.Build();
I am using Program.cs and hosting.json file to configure Kestrel. Example:
var config = new ConfigurationBuilder()
.SetBasePath(Directory.GetCurrentDirectory())
.AddJsonFile("hosting.json", optional: true, reloadOnChange: true)
.Build();
var host = new WebHostBuilder()
.UseConfiguration(config)
.UseKestrel()
.UseContentRoot(Directory.GetCurrentDirectory())
.UseStartup<Startup>();
hosting.json:
{
"urls": "http://localhost:4444;http://localhost:4445;"
}
This above is an example for the latest version dotnet core.
For earlier versions:
hosting.json:
{
"server.urls": "http://localhost:4444;http://localhost:4445;"
}
To run Visual Studio with Kestrel, just edit appsettings.json and add the config like this (tested with NetCore 2.0 and 2.1):
"profiles" : {
"Kestrel": {
"commandName": "Project",
"launchBrowser": true,
"applicationUrl": "http://localhost:6969/"
}
}
I had the same issue whereby my Kestrel configuration in appsettings.json is not being picked up. From this article about migrating from asp.net core 2.0 to 2.1, I updated the bootstraping code to become like the below, and it worked for me.
public static void Main(string[] args)
{
CreateWebHostBuilder(args).Build().Run();
}
public static IWebHostBuilder CreateWebHostBuilder(string[] args)
{
return WebHost.CreateDefaultBuilder(args)
.UseStartup<Startup>();
}
After hosting my asp.net core 1.2 application, I am getting an error as:
swagger is unable to find the swagger.json file.
I have tried to solve the problem by giving a virtual path name app.UseSwaggerUI() but it's not working.
Edit to clarify question based on comments:
After hosting Asp.net core application in IIS, the swagger.json file is generating on localhost:<random_port>/swagger/v1/swagger.json path.
How do I serve the swagger.json file on a custom route like:
localhost:<random_port>/virtualpathname/swagger/v1/swagger.json
I have tried to set a virtual path in app.UseSwaggerUI() like {virtualpathname}/swagger/v2/swagger.json but still it is not working
Could be a few reasons for this - one being that .Net Core doesnt serve static files by default (although looking at online examples this doesnt seem to be an issue).
If you havent already, try installing the package Microsoft.AspNetCore.StaticFiles and adding UseStaticFiles() in your Configure() method in Startup.cs with the following configuration. I dont think that the order is important, but this is the order I have mine running in a working app.
public void Configure(...)
{
// Enable middleware to serve static files (like .json)
app.UseStaticFiles();
//Enable middleware for your API
app.UseMvc();
// Enable middleware to serve generated Swagger as a JSON endpoint
app.UseSwagger();
// Enable middleware to serve swagger-ui assets (HTML, JS, CSS etc.)
app.UseSwaggerUI(c =>
{
c.SwaggerEndpoint("/swagger/v1/swagger.json", "YourApp API V1");
});
}
You will also need SwaggerGen middleware configured in your ConfigureServices() method.
services.AddSwaggerGen(c =>
{
c.SwaggerDoc("v1", new Info { Title = "api_name", Version = "1.0"});
});
Edit Based on comment - to serve swagger json on a custom route:
// Enable middleware to serve generated Swagger as a JSON endpoint on a custom endpoint
app.UseSwagger(c => c.RouteTemplate = "custom/swagger/{documentName}/swagger.json");
// Enable middleware to serve swagger-ui assets (HTML, JS, CSS etc.)
// Using custom endpoint defined above
app.UseSwaggerUI(c =>
{
c.SwaggerEndpoint("/custom/swagger/v1/swagger.json", "YourApp API V1");
});
If you need to serve SwaggerUI on a custom route as well, then:
// Enable middleware to serve swagger-ui assets (HTML, JS, CSS etc.)
// Using custom endpoint defined above
// And serving UI on a custom route
app.UseSwaggerUI(c =>
{
c.SwaggerEndpoint("/custom/swagger/v1/swagger.json", "YourApp API V1");
c.RoutePrefix = "custom"; // serves UI on http://{domain}:{port}/custom/
});
I suggest you to perform the two next steps.
First, open your project web.config and enable stdoutLogEnabled. (Remember to create the folder logs on your application folder and give it proper permissions)
Second, make sure you're doing the right configuration. (https://learn.microsoft.com/en-us/aspnet/core/tutorials/web-api-help-pages-using-swagger)
Note: The first step is going to give you more details about the error you're facing.
In my case the issue was the virtual directory which I fixed by adding a relative path(../). In any case make sure you setup ConfigureServices first, then when Configure make sure everything is in order, UseSwagger should be before UseMvc and at the end UseSwaggerUI
public void ConfigureServices(IServiceCollection services)
{
// Add framework services.
services.AddMvc();
services.AddSwaggerGen(c => {
c.SwaggerDoc("v1", new Swashbuckle.AspNetCore.Swagger.Info { Title = "Utility", Version = "v1" });
});
// initialize configuration
var conf = new ConfigurationHelper(Microsoft.DotNet.PlatformAbstractions.ApplicationEnvironment.ApplicationBasePath);
Configuration = conf.Configuration; // just in case
// inject the RestApiWrapperService as singleton into the services configuration
var restService = new RestApiWrapperService(conf);
services.AddSingleton<IRestApiWrapperService>(restService);
}
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
loggerFactory.AddConsole(Configuration.GetSection("Logging"));
loggerFactory.AddDebug();
app.UseSwagger();
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
app.UseBrowserLink();
}
else
{
app.UseExceptionHandler("/Home/Error");
}
app.UseStaticFiles();
// app.UseMvc();
app.UseMvc(routes =>
{
routes.MapRoute(
name: "default",
template: "{controller=Home}/{action=Index}/{id?}");
});
app.UseSwaggerUI(s => {
s.RoutePrefix = "help";
s.SwaggerEndpoint("../swagger/v1/swagger.json", "Utility");
s.InjectStylesheet("../css/swagger.min.css");
});
Change the following on your startup.cs class:
app.UseSwaggerUI(c =>
{
c.SwaggerEndpoint("/swagger/v1/swagger.json", "MyService.API v1");
});
To
app.UseSwaggerUI(c =>
{
c.SwaggerEndpoint("/MyWebsiteName/swagger/v1/swagger.json",
"MyService.API v1");
});
[MyWebsiteName] being the name of application configured in IIS.
I happened to have a simple copy paste mistake!
see the first line in below code, the if statement env.IsDevelopment() is causing this section to not run when deployed to IIS. One option is to comment it out!
//if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
app.UseSwagger(c =>
{
c.RouteTemplate = "swagger/{documentName}/swagger.json";
});
app.UseSwaggerUI(c => {
c.RoutePrefix = "swagger";
c.SwaggerEndpoint("/swagger/v1/swagger.json", "StockOps.WebAPI v1");
});
}