From 4c219753e330a0533d7b6360bd69b20f00a3ec63 Mon Sep 17 00:00:00 2001 From: Rick Anderson <3605364+Rick-Anderson@users.noreply.github.com> Date: Fri, 2 May 2025 12:27:21 -0600 Subject: [PATCH 1/3] Update debug remove startup /2 --- aspnetcore/test/troubleshoot.md | 6 + .../troubleshoot/includes/troubleshoot5.md | 160 ++++++++++++++++++ 2 files changed, 166 insertions(+) create mode 100644 aspnetcore/test/troubleshoot/includes/troubleshoot5.md diff --git a/aspnetcore/test/troubleshoot.md b/aspnetcore/test/troubleshoot.md index 8a1d324c83e9..bb1320050e67 100644 --- a/aspnetcore/test/troubleshoot.md +++ b/aspnetcore/test/troubleshoot.md @@ -9,6 +9,8 @@ uid: test/troubleshoot --- # Troubleshoot and debug ASP.NET Core projects +:::moniker range=">= aspnetcore-6.0" + By [Rick Anderson](https://twitter.com/RickAndMSFT) The following links provide troubleshooting guidance: @@ -165,3 +167,7 @@ The following links provide information on debugging ASP.NET Core apps. * [Debugging .NET Core on Unix over SSH](https://devblogs.microsoft.com/devops/debugging-net-core-on-unix-over-ssh/) * [Quickstart: Debug ASP.NET with the Visual Studio debugger](/visualstudio/debugger/quickstart-debug-aspnet) * See [this GitHub issue](https://github.com/dotnet/AspNetCore.Docs/issues/2960) for more debugging information. + +:::moniker-end + +[!INCLUDE[](~/test/troubleshoot/includes/troubleshoot5.md)] diff --git a/aspnetcore/test/troubleshoot/includes/troubleshoot5.md b/aspnetcore/test/troubleshoot/includes/troubleshoot5.md new file mode 100644 index 000000000000..624a34e3b1db --- /dev/null +++ b/aspnetcore/test/troubleshoot/includes/troubleshoot5.md @@ -0,0 +1,160 @@ +:::moniker range="< aspnetcore-6.0" + +By [Rick Anderson](https://twitter.com/RickAndMSFT) + +The following links provide troubleshooting guidance: + +* +* +* [NDC Conference (London, 2018): Diagnosing issues in ASP.NET Core Applications](https://www.youtube.com/watch?v=RYI0DHoIVaA) +* [ASP.NET Blog: Troubleshooting ASP.NET Core Performance Problems](https://blogs.msdn.microsoft.com/webdev/2018/05/23/asp-net-core-performance-improvements/) + +## .NET Core SDK warnings + +### Both the 32-bit and 64-bit versions of the .NET Core SDK are installed + +In the **New Project** dialog for ASP.NET Core, you may see the following warning: + +> Both 32-bit and 64-bit versions of the .NET Core SDK are installed. Only templates from the 64-bit versions installed at 'C:\\Program Files\\dotnet\\sdk\\' are displayed. + +This warning appears when both 32-bit (x86) and 64-bit (x64) versions of the [.NET Core SDK](https://dotnet.microsoft.com/download/dotnet-core) are installed. Common reasons both versions may be installed include: + +* You originally downloaded the .NET Core SDK installer using a 32-bit machine but then copied it across and installed it on a 64-bit machine. +* The 32-bit .NET Core SDK was installed by another application. +* The wrong version was downloaded and installed. + +Uninstall the 32-bit .NET Core SDK to prevent this warning. Uninstall from **Control Panel** > **Programs and Features** > **Uninstall or change a program**. If you understand why the warning occurs and its implications, you can ignore the warning. + +### The .NET Core SDK is installed in multiple locations + +In the **New Project** dialog for ASP.NET Core, you may see the following warning: + +> The .NET Core SDK is installed in multiple locations. Only templates from the SDKs installed at 'C:\\Program Files\\dotnet\\sdk\\' are displayed. + +You see this message when you have at least one installation of the .NET Core SDK in a directory outside of *C:\\Program Files\\dotnet\\sdk\\*. Usually this happens when the .NET Core SDK has been deployed on a machine using copy/paste instead of the MSI installer. + +Uninstall all 32-bit .NET Core SDKs and runtimes to prevent this warning. Uninstall from **Control Panel** > **Programs and Features** > **Uninstall or change a program**. If you understand why the warning occurs and its implications, you can ignore the warning. + +### No .NET Core SDKs were detected + +* In the Visual Studio **New Project** dialog for ASP.NET Core, you may see the following warning: + + > No .NET Core SDKs were detected, ensure they are included in the environment variable `PATH`. + +* When executing a `dotnet` command, the warning appears as: + + > It was not possible to find any installed dotnet SDKs. + +These warnings appear when the environment variable `PATH` doesn't point to any .NET Core SDKs on the machine. To resolve this problem: + +* Install the .NET Core SDK. Obtain the latest installer from [.NET Downloads](https://dotnet.microsoft.com/download). +* Verify that the `PATH` environment variable points to the location where the SDK is installed (`C:\Program Files\dotnet\` for 64-bit/x64 or `C:\Program Files (x86)\dotnet\` for 32-bit/x86). The SDK installer normally sets the `PATH`. Always install the same bitness SDKs and runtimes on the same machine. + +### Missing SDK after installing the .NET Core Hosting Bundle + +Installing the [.NET Core Hosting Bundle](xref:host-and-deploy/iis/index#install-the-net-core-hosting-bundle) modifies the `PATH` when it installs the .NET Core runtime to point to the 32-bit (x86) version of .NET Core (`C:\Program Files (x86)\dotnet\`). This can result in missing SDKs when the 32-bit (x86) .NET Core `dotnet` command is used ([No .NET Core SDKs were detected](#no-net-core-sdks-were-detected)). To resolve this problem, move `C:\Program Files\dotnet\` to a position before `C:\Program Files (x86)\dotnet\` on the `PATH`. + +## Obtain data from an app + +If an app is capable of responding to requests, you can obtain the following data from the app using middleware: + +* Request: Method, scheme, host, pathbase, path, query string, headers +* Connection: Remote IP address, remote port, local IP address, local port, client certificate +* Identity: Name, display name +* Configuration settings +* Environment variables + +Place the following [middleware](xref:fundamentals/middleware/index#create-a-middleware-pipeline-with-iapplicationbuilder) code at the beginning of the `Startup.Configure` method's request processing pipeline. The environment is checked before the middleware is run to ensure that the code is only executed in the Development environment. + +To obtain the environment, use either of the following approaches: + +* Inject the `IHostingEnvironment` into the `Startup.Configure` method and check the environment with the local variable. The following sample code demonstrates this approach. + +* Assign the environment to a property in the `Startup` class. Check the environment using the property (for example, `if (Environment.IsDevelopment())`). + +```csharp +public void Configure(IApplicationBuilder app, IHostingEnvironment env, + IConfiguration config) +{ + if (env.IsDevelopment()) + { + app.Run(async (context) => + { + var sb = new StringBuilder(); + var nl = System.Environment.NewLine; + var rule = string.Concat(nl, new string('-', 40), nl); + var authSchemeProvider = app.ApplicationServices + .GetRequiredService(); + + sb.Append($"Request{rule}"); + sb.Append($"{DateTimeOffset.Now}{nl}"); + sb.Append($"{context.Request.Method} {context.Request.Path}{nl}"); + sb.Append($"Scheme: {context.Request.Scheme}{nl}"); + sb.Append($"Host: {context.Request.Headers["Host"]}{nl}"); + sb.Append($"PathBase: {context.Request.PathBase.Value}{nl}"); + sb.Append($"Path: {context.Request.Path.Value}{nl}"); + sb.Append($"Query: {context.Request.QueryString.Value}{nl}{nl}"); + + sb.Append($"Connection{rule}"); + sb.Append($"RemoteIp: {context.Connection.RemoteIpAddress}{nl}"); + sb.Append($"RemotePort: {context.Connection.RemotePort}{nl}"); + sb.Append($"LocalIp: {context.Connection.LocalIpAddress}{nl}"); + sb.Append($"LocalPort: {context.Connection.LocalPort}{nl}"); + sb.Append($"ClientCert: {context.Connection.ClientCertificate}{nl}{nl}"); + + sb.Append($"Identity{rule}"); + sb.Append($"User: {context.User.Identity.Name}{nl}"); + var scheme = await authSchemeProvider + .GetSchemeAsync(IISDefaults.AuthenticationScheme); + sb.Append($"DisplayName: {scheme?.DisplayName}{nl}{nl}"); + + sb.Append($"Headers{rule}"); + foreach (var header in context.Request.Headers) + { + sb.Append($"{header.Key}: {header.Value}{nl}"); + } + sb.Append(nl); + + sb.Append($"WebSockets{rule}"); + if (context.Features.Get() != null) + { + sb.Append($"Status: Enabled{nl}{nl}"); + } + else + { + sb.Append($"Status: Disabled{nl}{nl}"); + } + + sb.Append($"Configuration{rule}"); + foreach (var pair in config.AsEnumerable()) + { + sb.Append($"{pair.Path}: {pair.Value}{nl}"); + } + sb.Append(nl); + + sb.Append($"Environment Variables{rule}"); + var vars = System.Environment.GetEnvironmentVariables(); + foreach (var key in vars.Keys.Cast().OrderBy(key => key, + StringComparer.OrdinalIgnoreCase)) + { + var value = vars[key]; + sb.Append($"{key}: {value}{nl}"); + } + + context.Response.ContentType = "text/plain"; + await context.Response.WriteAsync(sb.ToString()); + }); + } +} +``` + +## Debug ASP.NET Core apps + +The following links provide information on debugging ASP.NET Core apps. + +* [Debugging ASP Core on Linux](https://devblogs.microsoft.com/premier-developer/debugging-asp-core-on-linux-with-visual-studio-2017/) +* [Debugging .NET Core on Unix over SSH](https://devblogs.microsoft.com/devops/debugging-net-core-on-unix-over-ssh/) +* [Quickstart: Debug ASP.NET with the Visual Studio debugger](/visualstudio/debugger/quickstart-debug-aspnet) +* See [this GitHub issue](https://github.com/dotnet/AspNetCore.Docs/issues/2960) for more debugging information. + +:::moniker-end From 1ee9927958c564687bebc7647938a17022c37721 Mon Sep 17 00:00:00 2001 From: Rick Anderson <3605364+Rick-Anderson@users.noreply.github.com> Date: Fri, 2 May 2025 12:37:53 -0600 Subject: [PATCH 2/3] Update debug remove startup /2 --- .../test/troubleshoot/code/5.x/Program.cs | 73 +++++++++++++++++++ 1 file changed, 73 insertions(+) create mode 100644 aspnetcore/test/troubleshoot/code/5.x/Program.cs diff --git a/aspnetcore/test/troubleshoot/code/5.x/Program.cs b/aspnetcore/test/troubleshoot/code/5.x/Program.cs new file mode 100644 index 000000000000..3b808441bbb1 --- /dev/null +++ b/aspnetcore/test/troubleshoot/code/5.x/Program.cs @@ -0,0 +1,73 @@ +public void Configure(IApplicationBuilder app, IHostingEnvironment env, + IConfiguration config) +{ + if (env.IsDevelopment()) + { + app.Run(async (context) => + { + var sb = new StringBuilder(); + var nl = System.Environment.NewLine; + var rule = string.Concat(nl, new string('-', 40), nl); + var authSchemeProvider = app.ApplicationServices + .GetRequiredService(); + + sb.Append($"Request{rule}"); + sb.Append($"{DateTimeOffset.Now}{nl}"); + sb.Append($"{context.Request.Method} {context.Request.Path}{nl}"); + sb.Append($"Scheme: {context.Request.Scheme}{nl}"); + sb.Append($"Host: {context.Request.Headers["Host"]}{nl}"); + sb.Append($"PathBase: {context.Request.PathBase.Value}{nl}"); + sb.Append($"Path: {context.Request.Path.Value}{nl}"); + sb.Append($"Query: {context.Request.QueryString.Value}{nl}{nl}"); + + sb.Append($"Connection{rule}"); + sb.Append($"RemoteIp: {context.Connection.RemoteIpAddress}{nl}"); + sb.Append($"RemotePort: {context.Connection.RemotePort}{nl}"); + sb.Append($"LocalIp: {context.Connection.LocalIpAddress}{nl}"); + sb.Append($"LocalPort: {context.Connection.LocalPort}{nl}"); + sb.Append($"ClientCert: {context.Connection.ClientCertificate}{nl}{nl}"); + + sb.Append($"Identity{rule}"); + sb.Append($"User: {context.User.Identity.Name}{nl}"); + var scheme = await authSchemeProvider + .GetSchemeAsync(IISDefaults.AuthenticationScheme); + sb.Append($"DisplayName: {scheme?.DisplayName}{nl}{nl}"); + + sb.Append($"Headers{rule}"); + foreach (var header in context.Request.Headers) + { + sb.Append($"{header.Key}: {header.Value}{nl}"); + } + sb.Append(nl); + + sb.Append($"WebSockets{rule}"); + if (context.Features.Get() != null) + { + sb.Append($"Status: Enabled{nl}{nl}"); + } + else + { + sb.Append($"Status: Disabled{nl}{nl}"); + } + + sb.Append($"Configuration{rule}"); + foreach (var pair in config.AsEnumerable()) + { + sb.Append($"{pair.Path}: {pair.Value}{nl}"); + } + sb.Append(nl); + + sb.Append($"Environment Variables{rule}"); + var vars = System.Environment.GetEnvironmentVariables(); + foreach (var key in vars.Keys.Cast().OrderBy(key => key, + StringComparer.OrdinalIgnoreCase)) + { + var value = vars[key]; + sb.Append($"{key}: {value}{nl}"); + } + + context.Response.ContentType = "text/plain"; + await context.Response.WriteAsync(sb.ToString()); + }); + } +} From a12f934b6b5ab3363863426fe3e04a29ff7a3ba2 Mon Sep 17 00:00:00 2001 From: Rick Anderson <3605364+Rick-Anderson@users.noreply.github.com> Date: Fri, 2 May 2025 12:40:18 -0600 Subject: [PATCH 3/3] Update debug remove startup /2 --- aspnetcore/test/troubleshoot/code/5.x/Program.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/aspnetcore/test/troubleshoot/code/5.x/Program.cs b/aspnetcore/test/troubleshoot/code/5.x/Program.cs index 3b808441bbb1..9e11088e14b2 100644 --- a/aspnetcore/test/troubleshoot/code/5.x/Program.cs +++ b/aspnetcore/test/troubleshoot/code/5.x/Program.cs @@ -1,3 +1,5 @@ +// This is a copy/paste from the previous version embedded in the MD file, used only for productive +// GitHub diff public void Configure(IApplicationBuilder app, IHostingEnvironment env, IConfiguration config) {