Tooling and Ecosystem
The .NET ecosystem provides a rich set of tools and libraries to help you develop, test, and deploy C# applications. This section covers the essential tools and components of the .NET ecosystem.
.NET CLI
The .NET Command Line Interface (CLI) is a cross-platform tool for developing, building, running, and publishing .NET applications.
Basic Commands
# Create a new console application
dotnet new console -n MyApp
# Create a new web API project
dotnet new webapi -n MyApi
# Create a new class library
dotnet new classlib -n MyLibrary
# Build a project or solution
dotnet build
# Run a project
dotnet run
# Run with specific configuration
dotnet run --configuration Release
# Run with specific framework
dotnet run --framework net8.0
# Publish the application
dotnet publish -c Release
Project Management
# Add a reference to another project
dotnet add reference ../MyLibrary/MyLibrary.csproj
# Add a NuGet package
dotnet add package Newtonsoft.Json
# Add a specific version of a package
dotnet add package Microsoft.EntityFrameworkCore --version 8.0.0
# Remove a package
dotnet remove package Newtonsoft.Json
# List project references
dotnet list reference
# List NuGet packages
dotnet list package
Solution Management
# Create a new solution
dotnet new sln -n MySolution
# Add projects to a solution
dotnet sln add MyApp/MyApp.csproj MyLibrary/MyLibrary.csproj
# Remove a project from a solution
dotnet sln remove MyApp/MyApp.csproj
# List projects in a solution
dotnet sln list
Testing
# Run tests
dotnet test
# Run tests with filter
dotnet test --filter "Category=Unit"
# Run tests with test results output
dotnet test --logger "trx;LogFileName=results.trx"
# Run tests with code coverage
dotnet test /p:CollectCoverage=true /p:CoverletOutputFormat=cobertura
Tools
# Install a global tool
dotnet tool install -g dotnet-ef
# Update a global tool
dotnet tool update -g dotnet-ef
# Uninstall a global tool
dotnet tool uninstall -g dotnet-ef
# List installed global tools
dotnet tool list -g
# Install a local tool
dotnet tool install dotnet-reportgenerator-globaltool
NuGet Package Management
NuGet is the package manager for .NET, allowing you to share and consume code packages.
Package Management with CLI
# Restore packages
dotnet restore
# Add a package
dotnet add package Serilog
# Add a package with specific version
dotnet add package Microsoft.Extensions.Logging --version 8.0.0
# Add a package from a specific source
dotnet add package MyPackage --source https://mypackagesource/v3/index.json
# Remove a package
dotnet remove package Serilog
Package Management with NuGet.Config
Create a NuGet.Config file to configure package sources:
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<packageSources>
<clear />
<add key="nuget.org" value="https://api.nuget.org/v3/index.json" />
<add key="MyCompany" value="https://packages.mycompany.com/nuget/v3/index.json" />
</packageSources>
<packageSourceCredentials>
<MyCompany>
<add key="Username" value="username" />
<add key="ClearTextPassword" value="password" />
</MyCompany>
</packageSourceCredentials>
</configuration>
Creating NuGet Packages
# Create a NuGet package
dotnet pack -c Release
# Create a NuGet package with specific version
dotnet pack -c Release /p:Version=1.0.1
# Push a package to NuGet.org
dotnet nuget push bin/Release/MyPackage.1.0.0.nupkg --api-key YOUR_API_KEY --source https://api.nuget.org/v3/index.json
# Push a package to a private feed
dotnet nuget push bin/Release/MyPackage.1.0.0.nupkg --source https://packages.mycompany.com/nuget/v3/index.json
Testing Frameworks
.NET provides several testing frameworks to help you write and run tests.
xUnit
xUnit is a popular testing framework for .NET:
using Xunit;
public class CalculatorTests
{
[Fact]
public void Add_TwoNumbers_ReturnsSum()
{
// Arrange
var calculator = new Calculator();
// Act
int result = calculator.Add(2, 3);
// Assert
Assert.Equal(5, result);
}
[Theory]
[InlineData(1, 1, 2)]
[InlineData(5, 3, 8)]
[InlineData(-1, 1, 0)]
public void Add_MultipleTestCases_ReturnsSum(int a, int b, int expected)
{
var calculator = new Calculator();
int result = calculator.Add(a, b);
Assert.Equal(expected, result);
}
}
NUnit
NUnit is another popular testing framework:
using NUnit.Framework;
[TestFixture]
public class CalculatorTests
{
[Test]
public void Add_TwoNumbers_ReturnsSum()
{
// Arrange
var calculator = new Calculator();
// Act
int result = calculator.Add(2, 3);
// Assert
Assert.AreEqual(5, result);
}
[TestCase(1, 1, 2)]
[TestCase(5, 3, 8)]
[TestCase(-1, 1, 0)]
public void Add_MultipleTestCases_ReturnsSum(int a, int b, int expected)
{
var calculator = new Calculator();
int result = calculator.Add(a, b);
Assert.AreEqual(expected, result);
}
}
MSTest
MSTest is Microsoft's testing framework:
using Microsoft.VisualStudio.TestTools.UnitTesting;
[TestClass]
public class CalculatorTests
{
[TestMethod]
public void Add_TwoNumbers_ReturnsSum()
{
// Arrange
var calculator = new Calculator();
// Act
int result = calculator.Add(2, 3);
// Assert
Assert.AreEqual(5, result);
}
[DataTestMethod]
[DataRow(1, 1, 2)]
[DataRow(5, 3, 8)]
[DataRow(-1, 1, 0)]
public void Add_MultipleTestCases_ReturnsSum(int a, int b, int expected)
{
var calculator = new Calculator();
int result = calculator.Add(a, b);
Assert.AreEqual(expected, result);
}
}
Mocking Frameworks
Mocking frameworks help you create mock objects for testing:
Moq
using Moq;
using Xunit;
public class OrderServiceTests
{
[Fact]
public void PlaceOrder_ValidOrder_ReturnsOrderId()
{
// Arrange
var mockRepository = new Mock<IOrderRepository>();
mockRepository.Setup(repo => repo.Save(It.IsAny<Order>()))
.Returns(42);
var service = new OrderService(mockRepository.Object);
var order = new Order { /* ... */ };
// Act
int orderId = service.PlaceOrder(order);
// Assert
Assert.Equal(42, orderId);
mockRepository.Verify(repo => repo.Save(order), Times.Once);
}
}
NSubstitute
using NSubstitute;
using Xunit;
public class OrderServiceTests
{
[Fact]
public void PlaceOrder_ValidOrder_ReturnsOrderId()
{
// Arrange
var repository = Substitute.For<IOrderRepository>();
repository.Save(Arg.Any<Order>()).Returns(42);
var service = new OrderService(repository);
var order = new Order { /* ... */ };
// Act
int orderId = service.PlaceOrder(order);
// Assert
Assert.Equal(42, orderId);
repository.Received(1).Save(order);
}
}
Common Libraries
The .NET ecosystem includes many popular libraries for various tasks.
Web Development
- ASP.NET Core: Framework for building web apps and APIs
- Blazor: Framework for building interactive web UIs using C#
- Minimal APIs: Lightweight approach to building HTTP APIs
- SignalR: Real-time web functionality for apps
- Swagger/OpenAPI: API documentation and testing
Data Access
- Entity Framework Core: ORM for database access
- Dapper: Lightweight ORM for high performance
- MongoDB.Driver: MongoDB client library
- StackExchange.Redis: Redis client library
- Npgsql: PostgreSQL client library
Logging and Monitoring
- Serilog: Structured logging library
- NLog: Flexible logging platform
- Microsoft.Extensions.Logging: Logging abstractions
- OpenTelemetry: Observability framework
- Application Insights: Azure monitoring service
Serialization
- System.Text.Json: Built-in JSON serialization
- Newtonsoft.Json: Popular JSON framework
- MessagePack: Binary serialization format
- Protobuf-net: Protocol Buffers serialization
Dependency Injection
- Microsoft.Extensions.DependencyInjection: Built-in DI container
- Autofac: IoC container
- Lamar: Fast IoC container
- SimpleInjector: DI container focused on simplicity
Authentication and Authorization
- Microsoft.AspNetCore.Authentication: Authentication middleware
- IdentityServer: OpenID Connect and OAuth 2.0 framework
- Auth0.NET: Auth0 integration
- Microsoft.Identity.Web: Microsoft identity platform integration
Testing
- xUnit: Testing framework
- NUnit: Testing framework
- MSTest: Microsoft's testing framework
- Moq: Mocking framework
- NSubstitute: Mocking framework
- FluentAssertions: Fluent assertions library
- Bogus: Fake data generator
Utility Libraries
- Polly: Resilience and transient-fault-handling library
- Humanizer: String manipulation and human-friendly text
- AutoMapper: Object-to-object mapping
- FluentValidation: Validation library
- MediatR: Mediator pattern implementation
- Scrutor: Assembly scanning and decoration extensions for DI
Build Systems
Build systems automate the process of compiling, testing, and packaging your code.
MSBuild
MSBuild is the build system used by Visual Studio and the .NET CLI:
<!-- Directory.Build.props -->
<Project>
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
<LangVersion>latest</LangVersion>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.8.0" />
<PackageReference Include="xunit" Version="2.6.1" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.5.3" />
</ItemGroup>
</Project>
CAKE (C# Make)
CAKE is a cross-platform build automation system with a C# DSL:
// build.cake
var target = Argument("target", "Default");
var configuration = Argument("configuration", "Release");
Task("Clean")
.Does(() =>
{
CleanDirectories("./src/**/bin");
CleanDirectories("./src/**/obj");
});
Task("Restore")
.IsDependentOn("Clean")
.Does(() =>
{
DotNetRestore("./MySolution.sln");
});
Task("Build")
.IsDependentOn("Restore")
.Does(() =>
{
DotNetBuild("./MySolution.sln", new DotNetBuildSettings
{
Configuration = configuration,
NoRestore = true
});
});
Task("Test")
.IsDependentOn("Build")
.Does(() =>
{
DotNetTest("./MySolution.sln", new DotNetTestSettings
{
Configuration = configuration,
NoRestore = true,
NoBuild = true
});
});
Task("Default")
.IsDependentOn("Test");
RunTarget(target);
GitHub Actions
GitHub Actions allows you to automate your build, test, and deployment pipeline:
# .github/workflows/build.yml
name: Build and Test
on:
push:
branches: [ main ]
pull_request:
branches: [ main ]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Setup .NET
uses: actions/setup-dotnet@v3
with:
dotnet-version: 8.0.x
- name: Restore dependencies
run: dotnet restore
- name: Build
run: dotnet build --no-restore --configuration Release
- name: Test
run: dotnet test --no-build --configuration Release --verbosity normal
Azure DevOps Pipelines
Azure DevOps Pipelines provides CI/CD capabilities:
# azure-pipelines.yml
trigger:
- main
pool:
vmImage: 'ubuntu-latest'
variables:
buildConfiguration: 'Release'
steps:
- task: UseDotNet@2
inputs:
packageType: 'sdk'
version: '8.0.x'
- task: DotNetCoreCLI@2
displayName: 'Restore'
inputs:
command: 'restore'
projects: '**/*.csproj'
- task: DotNetCoreCLI@2
displayName: 'Build'
inputs:
command: 'build'
projects: '**/*.csproj'
arguments: '--configuration $(buildConfiguration) --no-restore'
- task: DotNetCoreCLI@2
displayName: 'Test'
inputs:
command: 'test'
projects: '**/*Tests.csproj'
arguments: '--configuration $(buildConfiguration) --no-build'
Deployment Options
.NET applications can be deployed in various ways.
Self-Contained Deployment
Package your application with the .NET runtime:
# Create a self-contained deployment for Windows
dotnet publish -c Release -r win-x64 --self-contained
# Create a self-contained deployment for Linux
dotnet publish -c Release -r linux-x64 --self-contained
# Create a self-contained deployment for macOS
dotnet publish -c Release -r osx-x64 --self-contained
Framework-Dependent Deployment
Package your application without the .NET runtime:
# Create a framework-dependent deployment
dotnet publish -c Release
Docker Containers
Deploy your application as a Docker container:
# Dockerfile
FROM mcr.microsoft.com/dotnet/sdk:8.0 AS build
WORKDIR /src
COPY ["MyApp.csproj", "./"]
RUN dotnet restore "MyApp.csproj"
COPY . .
RUN dotnet build "MyApp.csproj" -c Release -o /app/build
FROM build AS publish
RUN dotnet publish "MyApp.csproj" -c Release -o /app/publish
FROM mcr.microsoft.com/dotnet/aspnet:8.0 AS final
WORKDIR /app
COPY --from=publish /app/publish .
ENTRYPOINT ["dotnet", "MyApp.dll"]
Build and run the Docker container:
# Build the Docker image
docker build -t myapp .
# Run the Docker container
docker run -p 8080:80 myapp
Cloud Deployment
Deploy your application to cloud platforms:
Azure App Service
# Deploy to Azure App Service
az webapp up --name MyWebApp --resource-group MyResourceGroup --sku F1
AWS Elastic Beanstalk
# Deploy to AWS Elastic Beanstalk
eb init -p .NET -r us-east-1 MyApp
eb create MyApp-env
Kubernetes
# kubernetes-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: myapp
spec:
replicas: 3
selector:
matchLabels:
app: myapp
template:
metadata:
labels:
app: myapp
spec:
containers:
- name: myapp
image: myapp:latest
ports:
- containerPort: 80
Deploy to Kubernetes:
# Apply the Kubernetes deployment
kubectl apply -f kubernetes-deployment.yaml