Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions visual-studio/VisualStudioVsVsCode/Directory.Build.props
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
<Project>
<PropertyGroup Condition="'$(OS)' == 'Windows_NT'">
<ProjectDrive>$(MSBuildProjectDirectory.Substring(0, 2))</ProjectDrive>
<PathMap Condition="$(ProjectDrive.EndsWith(':'))">$(ProjectDrive.ToLowerInvariant())=$(ProjectDrive.ToUpperInvariant())</PathMap>
</PropertyGroup>
</Project>
38 changes: 38 additions & 0 deletions visual-studio/VisualStudioVsVsCode/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
# Visual Studio vs VS Code for .NET Developers

The sample for the Code Maze article "Visual Studio vs VS Code for .NET Developers". It holds one
minimal ASP.NET Core API, `ReportApi`, with a slow endpoint (`/report/slow`, string concatenation in
a loop) and a fast one (`/report/fast`, `StringBuilder`), and an xUnit test project,
`ReportApi.Tests`, with two tests.

## Open in Visual Studio

1. Open `VisualStudioVsVsCode.sln`.
2. Run `ReportApi`.
3. Browse to `http://localhost:5234/report/slow` and `http://localhost:5234/report/fast`.

## Open in VS Code

1. Install the C# Dev Kit extension.
2. To use Hot Reload while debugging, run "Preferences: Open User Settings (JSON)" from the Command
Palette and add this entry. The setting is machine-scoped, so a workspace
`.vscode/settings.json` would ignore it:

```json
"csharp.experimental.debug.hotReload": true
```

On Windows, `Directory.Build.props` in this folder sets the compiler's `PathMap` so the debug
symbols store the source paths with an upper-case drive letter. In our test, the C# Dev Kit's
build wrote a lower-case one (`d:\`), and Hot Reload then reported "No code changes were found."
for every edit. The file does nothing on Linux and macOS.

3. Open this folder, then run and debug `ReportApi`.
4. With the API running, use the .NET diagnostic tools from the terminal while you call
`/report/slow`:

```
dnx dotnet-counters monitor -n ReportApi
dnx dotnet-trace collect -n ReportApi --duration 00:00:00:15 -o slow.nettrace
dnx dotnet-trace report slow.nettrace topN -n 10
```
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>net10.0</TargetFramework>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
<IsPackable>false</IsPackable>
<IsTestProject>true</IsTestProject>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="18.10.1" />
<PackageReference Include="xunit.v3.mtp-off" Version="4.0.1" />
<PackageReference Include="xunit.runner.visualstudio" Version="4.0.0" />
</ItemGroup>

<ItemGroup>
<Using Include="Xunit" />
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\ReportApi\ReportApi.csproj" />
</ItemGroup>

</Project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
namespace ReportApi.Tests;

public class ReportBuilderTests
{
[Fact]
public void WhenBuiltBothWays_ThenReportsAreEqual()
{
var concatenated = ReportBuilder.BuildWithConcatenation(100);
var built = ReportBuilder.BuildWithStringBuilder(100);

Assert.Equal(concatenated, built);
}

[Fact]
public void WhenBuilt_ThenReportHasOneLinePerOrder()
{
var report = ReportBuilder.BuildWithStringBuilder(100);

var lines = report.Split(Environment.NewLine, StringSplitOptions.RemoveEmptyEntries);

Assert.Equal(100, lines.Length);
Assert.Equal("Order 1: 2 items", lines[0]);
}
}
9 changes: 9 additions & 0 deletions visual-studio/VisualStudioVsVsCode/ReportApi/Program.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
using ReportApi;

var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();

app.MapGet("/report/slow", (int orders = 10_000) => ReportBuilder.BuildWithConcatenation(orders));
app.MapGet("/report/fast", (int orders = 10_000) => ReportBuilder.BuildWithStringBuilder(orders));

app.Run();
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
{
"$schema": "https://json.schemastore.org/launchsettings.json",
"profiles": {
"http": {
"commandName": "Project",
"dotnetRunMessages": true,
"launchBrowser": true,
"applicationUrl": "http://localhost:5234",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
},
"https": {
"commandName": "Project",
"dotnetRunMessages": true,
"launchBrowser": true,
"applicationUrl": "https://localhost:7032;http://localhost:5234",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
}
}
}
9 changes: 9 additions & 0 deletions visual-studio/VisualStudioVsVsCode/ReportApi/ReportApi.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<Project Sdk="Microsoft.NET.Sdk.Web">

<PropertyGroup>
<TargetFramework>net10.0</TargetFramework>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
</PropertyGroup>

</Project>
28 changes: 28 additions & 0 deletions visual-studio/VisualStudioVsVsCode/ReportApi/ReportBuilder.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
using System.Text;

namespace ReportApi;

public static class ReportBuilder
{
public static string BuildWithConcatenation(int orders)
{
var report = "";
for (var i = 1; i <= orders; i++)
{
report += $"Order {i}: {i % 7 + 1} items{Environment.NewLine}";
}

return report;
}

public static string BuildWithStringBuilder(int orders)
{
var report = new StringBuilder();
for (var i = 1; i <= orders; i++)
{
report.AppendLine($"Order {i}: {i % 7 + 1} items");
}

return report.ToString();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
}
}
9 changes: 9 additions & 0 deletions visual-studio/VisualStudioVsVsCode/ReportApi/appsettings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
},
"AllowedHosts": "*"
}
48 changes: 48 additions & 0 deletions visual-studio/VisualStudioVsVsCode/VisualStudioVsVsCode.sln
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
VisualStudioVersion = 17.0.31903.59
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ReportApi", "ReportApi\ReportApi.csproj", "{D330E484-5658-4636-A24B-EF6E0BC35EC6}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ReportApi.Tests", "ReportApi.Tests\ReportApi.Tests.csproj", "{9B6B5296-581D-491A-95ED-398AA80CE457}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Debug|x64 = Debug|x64
Debug|x86 = Debug|x86
Release|Any CPU = Release|Any CPU
Release|x64 = Release|x64
Release|x86 = Release|x86
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{D330E484-5658-4636-A24B-EF6E0BC35EC6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{D330E484-5658-4636-A24B-EF6E0BC35EC6}.Debug|Any CPU.Build.0 = Debug|Any CPU
{D330E484-5658-4636-A24B-EF6E0BC35EC6}.Debug|x64.ActiveCfg = Debug|Any CPU
{D330E484-5658-4636-A24B-EF6E0BC35EC6}.Debug|x64.Build.0 = Debug|Any CPU
{D330E484-5658-4636-A24B-EF6E0BC35EC6}.Debug|x86.ActiveCfg = Debug|Any CPU
{D330E484-5658-4636-A24B-EF6E0BC35EC6}.Debug|x86.Build.0 = Debug|Any CPU
{D330E484-5658-4636-A24B-EF6E0BC35EC6}.Release|Any CPU.ActiveCfg = Release|Any CPU
{D330E484-5658-4636-A24B-EF6E0BC35EC6}.Release|Any CPU.Build.0 = Release|Any CPU
{D330E484-5658-4636-A24B-EF6E0BC35EC6}.Release|x64.ActiveCfg = Release|Any CPU
{D330E484-5658-4636-A24B-EF6E0BC35EC6}.Release|x64.Build.0 = Release|Any CPU
{D330E484-5658-4636-A24B-EF6E0BC35EC6}.Release|x86.ActiveCfg = Release|Any CPU
{D330E484-5658-4636-A24B-EF6E0BC35EC6}.Release|x86.Build.0 = Release|Any CPU
{9B6B5296-581D-491A-95ED-398AA80CE457}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{9B6B5296-581D-491A-95ED-398AA80CE457}.Debug|Any CPU.Build.0 = Debug|Any CPU
{9B6B5296-581D-491A-95ED-398AA80CE457}.Debug|x64.ActiveCfg = Debug|Any CPU
{9B6B5296-581D-491A-95ED-398AA80CE457}.Debug|x64.Build.0 = Debug|Any CPU
{9B6B5296-581D-491A-95ED-398AA80CE457}.Debug|x86.ActiveCfg = Debug|Any CPU
{9B6B5296-581D-491A-95ED-398AA80CE457}.Debug|x86.Build.0 = Debug|Any CPU
{9B6B5296-581D-491A-95ED-398AA80CE457}.Release|Any CPU.ActiveCfg = Release|Any CPU
{9B6B5296-581D-491A-95ED-398AA80CE457}.Release|Any CPU.Build.0 = Release|Any CPU
{9B6B5296-581D-491A-95ED-398AA80CE457}.Release|x64.ActiveCfg = Release|Any CPU
{9B6B5296-581D-491A-95ED-398AA80CE457}.Release|x64.Build.0 = Release|Any CPU
{9B6B5296-581D-491A-95ED-398AA80CE457}.Release|x86.ActiveCfg = Release|Any CPU
{9B6B5296-581D-491A-95ED-398AA80CE457}.Release|x86.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
EndGlobal
Loading