I have a .net core web api application that I have recently tried to debug (in VS2017) on a new computer (after a long hiatus from working on the app). I also upgraded the .net core from 1.1 to 2.2. However, it no longer seems to route at all, even to the ValuesController which I left in for testing purposes, nor with just using localhost (I had been testing it with my local ip address). I've created another web api project (which routes fine) in the same solution and have compared code, config files etc; I've simplified my own code to extreme matching the working web api code:
public class Program {
public static void Main(string[] args) {
BuildWebHost(args).Run();
}
public static IWebHost BuildWebHost(string[] args) =>
WebHost.CreateDefaultBuilder(args)
.UseStartup<Startup>()
.Build();
}
And I've stripped out all but the bare bones of Startup.cs
public partial class Startup {
public IConfiguration Configuration { get; }
public Startup(IConfiguration configuration) {
Configuration = configuration;
}
public void ConfigureServices(IServiceCollection services) {
services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
}
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory) {
if (env.IsDevelopment()) {
app.UseDeveloperExceptionPage();
} else {
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseMvc();
}
}
[Route("api/[controller]")]
[ApiController]
public class ValuesController : ControllerBase
{
// GET api/values
[HttpGet]
public ActionResult<IEnumerable<string>> Get()
{
return new string[] { "value1", "value2" };
}
...
And made sure my my launchSettings.json also matched my test web api (have tried launching with both the service directly, or via IISExpress). Relevent bit for direct launch:
"profiles": {
"MyWebApiService": {
"commandName": "Project",
"launchBrowser": true,
"launchUrl": "api/values",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
},
"applicationUrl": "http://localhost:8080;https://localhost:44385"
}
}
But when it launches, although it first calls http://localhost:8080/api/values, and the redirect to https://localhost:44385/api/values works fine, the call to https://localhost:44385/api/values returns http code 404.
Is there any way to see what is going on in the routing? What it's looking for and where?
In your code supplied I don't see AddHttpsRedirection in ConfigureServices. Please add:
services.AddHttpsRedirection(options =>
{
options.HttpsPort = 443;
});
Please refer to: Enforce HTTPS in ASP.NET Core
Similar problem to WebApi giving 404 whilst debugging; works when published but I hadn't checked the published version. Also, my Sdk as set in the <Project> node in the .csproj file was:
Microsoft.NET.Sdk.Web
as it should be. However, I did have the <PreserveCompilationContext> there and explicitly set to false, which appears to have worked fine prior to v. 2.1. Setting this to true was the solution here:
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFramework>netcoreapp2.2</TargetFramework>
<PreserveCompilationContext>true</PreserveCompilationContext>
...
"MVC 2.1.0 requires compilation context to be available. Compilation context tells it if a library references MVC which is used as a filter to skip assemblies that are deemed unlikely to have controllers." See ASP.NET Core 2.1.0 breaks attribute-routed endpoints in applications targeting Microsoft.NET.Sdk #8388
Note this issue is in all of Microsoft.AspNetCore.App and Microsoft.AspNetCore.All versions 2.1.0, 2.1.1, 2.1.2 and 2.1.3.
Related
I recently upgraded a relatively large web API from .NET Core 3.1 to .NET 6 and am getting a no Access-Control-Allow-Origin header CORS error. I have not moved to the minimal hosting model, but I understand from the docs that this is not necessary and the old model should continue to work. I include code from startup and program below and what I had to change to make the upgraded project work. Note that everything else works properly.
Startup.cs
public void ConfigureServices(IServiceCollection services)
{
services.Configure<ForwardedHeadersOptions>(options =>
{
options.ForwardedHeaders =
ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto;
});
services.AddCors(options => options.AddPolicy("CorsPolicy",
builder =>
{
builder.AllowAnyMethod()
.WithOrigins(Configuration.GetSection("AllowedOrigins").Get<string[]>())
.SetIsOriginAllowed(origin => true)
.AllowAnyHeader();
}));
}
public void Configure(IApplicationBuilder app, IWebHostEnvironment env, ILoggerFactory loggerFactory, IHostApplicationLifetime appLifetime)
{
app.UseCors("CorsPolicy");
}
Note that * is returned from "AllowedOrigins".
Program.cs
private static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.UseSerilog()
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder
.UseKestrel()
.UseContentRoot(Directory.GetCurrentDirectory())
.UseUrls(Configuration.GetValue<bool>("App:UsesHttps")
? $"{Configuration.GetValue<string>("App:HttpUrl")}, " +
$"{Configuration.GetValue<string>("App:HttpsUrl") }"
: $"{Configuration.GetValue<string>("App:HttpUrl")}")
.UseStartup<Startup>();
});
For the upgrade to .NET 6, nothing in Startup.cs has changed. In Program.cs, .UseUrls does not work anymore and instead I have it defined in appsettings and I have removed the call to .UseUrls.
Appsettings (.NET Core 3.1)
"App": {
"UsesHttps": false,
"HttpUrl": "http://0.0.0.0:5005",
"HttpsUrl": "https://0.0.0.0:5001"
},
Appsettings (.NET 6)
"Kestrel": {
"Endpoints": {
"Http": {
"Url": "http://localhost:5005"
}
}
},
Nothing else in the code has changed, and all I have done is update packages. I fail to see how they would influence a CORS error.
The app is running in a Docker container behind Nginx serving as a reverse proxy. I have not made any changed to the Nginx settings. The app is listening on HTTP only as Nginx handles the HTTPS connection. Again, this works when the app is built against .NET Core 3.1. I have read the documentation about upgrading to .NET 6 and I cannot find anything that would explain this kind of a change.
don't know if this will help you. We have the following in our API in the program.cs
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
// Other code left out here
app.UseAuthentication();
// Allow CORS for any origin, method or header
app.UseCors(policy =>
policy.AllowAnyOrigin()
.AllowAnyMethod()
.AllowAnyHeader());
app.UseAuthorization();
}
If I remember correctly the order of things is pretty important. I don't see Authentication and Authorization in your code. Don't know if you need that or not. There's a remark at this code as it might be allowing too much. We still have to investigate that.
I'm experiencing a strange behavior when launching an ASP.NET core 3.1 web application from Visual Studio 2019 using kestrel (I mean the launching profile which does not use IIS express).
I have created a minimal application to reproduce the issue.
OS: Windows 10 (build 19041.746)
Visual Studio version: Visual Studio 2019 version 16.8.4
This is the csproj file:
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFramework>netcoreapp3.1</TargetFramework>
</PropertyGroup>
</Project>
This is the launchSettings.json file:
{
"$schema": "http://json.schemastore.org/launchsettings.json",
"iisSettings": {
"windowsAuthentication": false,
"anonymousAuthentication": true,
"iisExpress": {
"applicationUrl": "http://localhost:52222",
"sslPort": 0
}
},
"profiles": {
"IIS Express": {
"commandName": "IISExpress",
"launchBrowser": true,
"launchUrl": "weatherforecast",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
},
"TestWebApplication": {
"commandName": "Project",
"launchBrowser": true,
"launchUrl": "weatherforecast",
"applicationUrl": "http://localhost:5002",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
}
}
}
This is the Program.cs file:
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Hosting;
namespace TestWebApplication
{
public class Program
{
public static void Main(string[] args)
{
CreateHostBuilder(args).Build().Run();
}
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>();
});
}
}
This is the Startup.cs file:
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
namespace TestWebApplication
{
public class Startup
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public IConfiguration Configuration { get; }
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
services.AddControllers();
}
// 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();
}
app.UseRouting();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
});
}
}
}
When I launch this web application by using the TestWebApplication profile from Visual Studio everything works fine: kestrel is launched at http://localhost:5002 and the web browser is launched at http://localhost:5002/weatherforecast.
This is exactly what I would expect from the provided launchSettings.json file.
Consider the following change to the Program.cs, made to customize the application configuration sources:
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Hosting;
namespace TestWebApplication
{
public class Program
{
public static void Main(string[] args)
{
CreateHostBuilder(args).Build().Run();
}
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureAppConfiguration(builder =>
{
builder.Sources.Clear();
builder.AddEnvironmentVariables();
})
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>();
});
}
}
This change breaks everything in terms of interaction with the launchSettings.json file. The following happens:
kester is launched on both http://localhost:5000 and https://localhost:5001
web browser is not launched on http://localhost:5002/weatherforecast
Basically it seems that the file launchSettings.json is ignored and some defaults are used instead.
I have also observed the following:
the root cause seems to be the line which clears the configuration sources: builder.Sources.Clear();
the IIS express profile is not affected by this issue: it works as expected even with the modified Program.cs file
Is this a bug ? Am I missing anything ?
SOME CLARIFICATIONS
I'm clearing the configuration sources in order to have full control over the configuration sources themselves. Put another way, I would like to remove all the existing configuration sources and start from scratch. According to this documentation this approach seems to be allowed.
Notice that the exact same code works as expected when using the WebHost class instead of the Host class. In that case the configuration sources can be fully customized and the ability to read the launchSettings.json file is maintained for Kestrel too. I'm trying to achieve the same effect with the generic Host class, which is the recommended class to be used instead of WebHost in ASP.NET core 3.1
I have finally managed this issue.
That's not an ASP.NET core 3.1 bug, insted this is the way the generic Host is designed to work.
Basically the configuration for the port number which is specified inside the lanchSettings.json file is passed to the ASP.NET core application by means of some environment variables prefixed by ASPNETCORE_. These environment variables are set automatically by Visual Studio. The one responsible for the kestrel port binding is called ASPNETCORE_URLS.
When doing builder.Sources.Clear(); the configuration source for the environment variables prefixed by ASPNETCORE_ is cleared away. So, in order to fix the issue, it is necessary to replace this configuration source:
.ConfigureAppConfiguration(builder =>
{
builder.Sources.Clear();
builder.AddEnvironmentVariables();
builder.AddEnvironmentVariables("ASPNETCORE_");
})
All the details are available here
Linqpad 6 supports .Net Core.
When I create a new empty .Net Core API solution in visual studio , I get a simple template with a simple demo controller.
When I run it in visual studio it uses a command-line server (kestrel) to run the project :
So I wanted to see if I can run this project in Linqpad 6.
So I've installed all nugets and copied the code to Linqpad :
https://i.stack.imgur.com/lwRyU.png
void Main()
{
CreateWebHostBuilder(new string[] { "" }).Build().Run();
}
public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
WebHost.CreateDefaultBuilder(args)
.UseStartup<Startup>();
[Route("api/[controller]")]
[ApiController]
public class ValuesController : ControllerBase
{
[HttpGet]
public ActionResult<IEnumerable<string>> Get()
{
return new string[] { "value1", "value2" };
}
}
public class Startup
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public IConfiguration Configuration { get; }
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
//if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.UseMvc();
}
}
I do see that it is now listening :
But calls to http://localhost:5000/api/values do get acked , but without the json value response from controller :
Question:
How can I get Linqpad to return the value from the controller? ( a simple json)
There's a difference in the way LINQPad executes code that could account for this not working.
Being a scripting tool, LINQPad wraps everything in a class (otherwise, the Main method would have nowhere to live). So ValuesController is actually ends up as a nested type, UserQuery.ValuesController, and this could potentially upset the routing API.
For such situations, LINQPad has the ability to extract all nested types and move them outside UserQuery (using the Roslyn API). To enable this, add the following to the start of your query:
#LINQPad nonest
Something else to consider is that a default MVC project includes an appsettings.json file. Should this be required for your code in LINQPad, you need to create such a file and add a reference to it (when you reference to a non-binary file, LINQPad copies it into the output folder, which is exactly where appsettings.json needs to be).
Edit: There's now a checkbox in the Query Properties dialog to add ASP.NET Core references to a query in LINQPad 6. This pulls the assemblies straight from the shared framework folder, and is easier than finding the right NuGet packages.
I'm starting a new project in VS 2015.
File -> New -> Project -> ASP.NET Web Application -> ASP.NET 5 Templates -> Web API
A project is initialized. I would assume that if I run the project with IIS Express a service would be available.
It runs through the startup methods.
public class Startup
{
public Startup(IHostingEnvironment env)
{
// Set up configuration sources.
var builder = new ConfigurationBuilder()
.AddJsonFile("appsettings.json")
.AddEnvironmentVariables();
Configuration = builder.Build();
}
public IConfigurationRoot Configuration { get; set; }
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
// Add framework services.
services.AddMvc();
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
loggerFactory.AddConsole(Configuration.GetSection("Logging"));
loggerFactory.AddDebug();
app.UseIISPlatformHandler();
app.UseStaticFiles();
app.UseMvc();
}
// Entry point for the application.
public static void Main(string[] args) =>
WebApplication.Run<Startup>(args);
}
}
But then it crashes. I don't know how to implement global error handling.
I looked at this example.
But when I try to use System.Net.Http or System.Web.Http.ExceptionHandling they can't be found.
I also noticed that through intellisense it says Core 5.0 is no available.
Here is my project.json as requested.
{
"version":"1.0.0-*",
"compilationOptions":{
"emitEntryPoint":true
},
"dependencies":{
"Microsoft.AspNet.IISPlatformHandler":"1.0.0-rc1-final",
"Microsoft.AspNet.Mvc":"6.0.0-rc1-final",
"Microsoft.AspNet.Server.Kestrel":"1.0.0-rc1-final",
"Microsoft.AspNet.StaticFiles":"1.0.0-rc1-final",
"Microsoft.Extensions.Configuration.FileProviderExtensions":"1.0.0-rc1-final",
"Microsoft.Extensions.Configuration.Json":"1.0.0-rc1-final",
"Microsoft.Extensions.Logging":"1.0.0-rc1-final",
"Microsoft.Extensions.Logging.Console":"1.0.0-rc1-final",
"Microsoft.Extensions.Logging.Debug":"1.0.0-rc1-final"
},
"commands":{
"web":"Microsoft.AspNet.Server.Kestrel"
},
"frameworks":{
"dnx451":{
"frameworkAssemblies":{
"System.Web":"4.0.0.0"
}
},
"dnxcore50":{
}
},
"exclude":[
"wwwroot",
"node_modules"
],
"publishExclude":[
"**.user",
"**.vspscc"
]
}
Try to open Visual Studio Administrator Mode
I guess it depends on what is crashing - it's not clear from your description what crashes, when it crashes and how it crashes.
You can use UseExceptionHandler and UseDeveloperExceptionPage extension methods to configure an error handling page. This article describes it in more details.
If the exception happens during startup you may need to use UseCaptureStartupErrors extension method (it was recently renamed to CaptureStartupErrors).
Also, you already have logging enabled - the logs may also have some useful information. If you can't see logs because you log to the console consider logging to a file.
If this is IIS/IISExpress crashing check event log.
What is your runtime version ?
Maybe you can try scaffolding your application with the AspNet Yeoman generator and compare the files.
Personally I prefer to use the scaffolder as it is often up to date.
Hope this helps !
I have an ASP.Net vNext project that uses Session. But I am getting this error while trying to get/set values in the session.
An exception of type 'System.InvalidOperationException' occurred in Microsoft.AspNet.Http.Core.dll but was not handled in user code
Additional information: Session has not been configured for this application or request.
Here's my controller method:
[AllowAnonymous]
[HttpGet("/admin")]
public IActionResult Index()
{
if (Context.Session.GetString("UserName") == null) // error thrown here
{
return RedirectToAction("Login");
}
return View();
}
I have added the KVM package "Microsoft.AspNet.Session": "1.0.0-beta3" in my project.json file as well and have configured my application to use session via my Startup.cs like so:
public void ConfigureServices(IServiceCollection services)
{
// code removed for brevity
services.AddCachingServices();
services.AddSessionServices();
}
public void Configure(IApplicationBuilder app)
{
app.UseMvc();
app.UseInMemorySession(configure: s => s.IdleTimeout = TimeSpan.FromMinutes(30));
}
I have looked at the vNext documentation on Github but it does not provide much information about ASP.Net sessions. What am I doing wrong?
So I figured this out. The fix was quite simple actually. Since ASP.Net adds the middlewares sequentially into the request pipeline, all I needed to do was use the session middleware before using MVC. More info here: https://stackoverflow.com/a/29569746/832546
Fixed code:
public void Configure(IApplicationBuilder app)
{
app.UseInMemorySession(configure: s => s.IdleTimeout = TimeSpan.FromMinutes(30));
app.UseMvc();
}
Thanks to #acrhistof the link helped.
So if you are using RC1:
add this these dependencies in project.json:
"Microsoft.AspNet.Session": "1.0.0-rc1-final",
"Microsoft.Extensions.Caching.Memory": "1.0.0",
in Startup.cs file:
public void ConfigureServices(IServiceCollection services)
{
services.AddCaching();
services.AddSession();
services.AddMvc();
}
and
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
app.UseSession(); //outside of dev if (env.IsDevelopment())
....
}
It seems like things changed once again and the well-known ASP.NET session has to be configured differently in the rc1. (no UseInMemorySession() or other AppBuilder methods are related to Session, now it is added as a service).
In general Session has to be installed, configured, and then used. All these steps are quite new and somewhat unusual. Moreover, it depends on Cache:
Session is built on top of IDistributedCache, so you must configure
this as well, otherwise you will receive an error.
The quotation above is from ASP.NET 5 docs. All you need to do is described here: https://docs.asp.net/en/latest/fundamentals/app-state.html#installing-and-configuring-session.