---
title: .NET 8+
description: In .NET applications using Microsoft.Extensions.Hosting, the agent can be registered on the IServiceCollection. This applies to ASP.NET Core and to other...
url: https://www.elastic.co/elastic/docs-builder/docs/2395/reference/apm/agents/dotnet/setup-dotnet-net-core
---

# .NET 8+
## Quick start

In .NET applications using `Microsoft.Extensions.Hosting`, the agent can be registered on the `IServiceCollection`. This applies to ASP.NET Core and to other .NET applications that depend on the hosting APIs, such as those created using the [worker services](https://learn.microsoft.com/en-us/dotnet/core/extensions/workers) template.
The simplest way to enable the agent and its instrumentations requires a reference to the [`Elastic.Apm.NetCoreAll`](https://www.nuget.org/packages/Elastic.Apm.NetCoreAll) package.
```xml
<PackageReference Include="Elastic.Apm.NetCoreAll" Version="<LATEST>" /> <1>
```

1. Replace the `<LATEST>` placeholder with the latest version of the agent available on NuGet.

<note>
  The following code sample assumes the instrumentation of a .NET 8 worker service, using [top-level statements](https://learn.microsoft.com/en-us/dotnet/csharp/tutorials/top-level-statements).
</note>

**Program.cs**
```csharp
using WorkerServiceSample;

var builder = Host.CreateApplicationBuilder(args);

builder.Services.AddHttpClient();
builder.Services.AddAllElasticApm(); 
builder.Services.AddHostedService<Worker>();

var host = builder.Build();
host.Run();
```

When registering services with `AddAllElasticApm()`, an APM agent with all instrumentations is enabled. On ASP.NET Core, it’ll automatically capture incoming requests, database calls through supported technologies, outgoing HTTP requests, etc.
For other application templates, such as worker services, you must manually instrument your `BackgroundService` to identify one or more units of work that should be captured.

## Manual instrumentation using `ITracer`

`AddAllElasticApm` adds an `ITracer` to the Dependency Injection system, which can be used in your code to manually instrument your application, using the [*Public API*](https://www.elastic.co/elastic/docs-builder/docs/2395/reference/apm/agents/dotnet/public-api)
**Worker.cs**
```csharp
using Elastic.Apm.Api;

namespace WorkerServiceSample
{
  public class Worker : BackgroundService
  {
    private readonly IHttpClientFactory _httpClientFactory;
    private readonly ITracer _tracer;

    public Worker(IHttpClientFactory httpClientFactory, ITracer tracer)
    {
      _httpClientFactory = httpClientFactory;
      _tracer = tracer;
    }

    protected override async Task ExecuteAsync(CancellationToken stoppingToken)
    {
      while (!stoppingToken.IsCancellationRequested)
      {
        await _tracer.CaptureTransaction("UnitOfWork", ApiConstants.TypeApp, async () => 
        {
          var client = _httpClientFactory.CreateClient();
          await client.GetAsync("https://www.elastic.co", stoppingToken);
          await Task.Delay(5000, stoppingToken);
        });
      }
    }
  }
}
```

When this application runs, a new transaction will be captured and sent for each while loop iteration. A span named *HTTP GET* within the transaction will be created for the HTTP request to `https://www.elastic.co`. The HTTP span is captured because the `NetCoreAll` package enables this instrumentation automatically.

## Manual instrumentation using OpenTelemetry

As an alternative to using the Elastic APM API by injecting an `ITracer`, you can use the OpenTelemetry API to manually instrument your application. The Elastic APM agent automatically bridges instrumentations created using the OpenTelemetry API, so you can use it to create spans and transactions. In .NET, the [`Activity` API](https://learn.microsoft.com/en-us/dotnet/core/diagnostics/distributed-tracing-instrumentation-walkthroughs) can be used to instrument applications.
In the case of this sample worker service, we can update the code to prefer the OpenTelemetry API.
**Worker.cs**
```csharp
using System.Diagnostics;

namespace WorkerServiceSample
{
  public class Worker : BackgroundService
  {
    private readonly IHttpClientFactory _httpClientFactory;
    private static readonly ActivitySource ActivitySource = new("MyActivitySource"); 

    public Worker(IHttpClientFactory httpClientFactory)
    {
      _httpClientFactory = httpClientFactory;
    }

    protected override async Task ExecuteAsync(CancellationToken stoppingToken)
    {
      while (!stoppingToken.IsCancellationRequested)
      {
        using var activity = ActivitySource.StartActivity("UnitOfWork"); 
        var client = _httpClientFactory.CreateClient();
        await client.GetAsync("https://www.elastic.co", stoppingToken);
        await Task.Delay(5000, stoppingToken);
      }
    }
  }
}
```


## Instrumentation modules

The `Elastic.Apm.NetCoreAll` package references every agent component that can be automatically configured. This is usually not a problem, but if you want to keep dependencies minimal, you can instead reference the `Elastic.Apm.Extensions.Hosting` package and register services with `AddElasticApm` method, instead of `AddAllElasticApm`. With this setup you can explicitly control what the agent will listen for.
The following example only turns on outgoing HTTP monitoring (so, for instance, database and Elasticsearch calls won’t be automatically captured):
```csharp
using Elastic.Apm.DiagnosticSource;
using WorkerServiceSample;

var builder = Host.CreateApplicationBuilder(args);

builder.Services.AddHttpClient();
builder.Services.AddElasticApm(new HttpDiagnosticsSubscriber()); 
builder.Services.AddHostedService<Worker>();

var host = builder.Build();
host.Run();
```


## Zero code change setup on .NET 8+ ([1.7])

If you can’t or don’t want to reference NuGet packages in your application, you can use the startup hook feature to inject the agent during startup, if your application runs on .NET 8 or newer.
To configure startup hooks
1. Download the `ElasticApmAgent_<version>.zip` file from the [Releases](https://github.com/elastic/apm-agent-dotnet/releases) page of the .NET APM Agent GitHub repository. You can find the file under Assets.
2. Unzip the zip file into a folder.
3. Set the `DOTNET_STARTUP_HOOKS` environment variable to point to the `ElasticApmAgentStartupHook.dll` file in the unzipped folder
   ```sh
   set DOTNET_STARTUP_HOOKS=<path-to-agent>\ElasticApmAgentStartupHook.dll 
   ```
4. Start your .NET application in a context where the `DOTNET_STARTUP_HOOKS` environment variable is visible.

With this setup, the agent will be injected into the application during startup, enabling every instrumentation feature. Incoming requests will be automatically captured on ASP.NET Core (including gRPC).
<note>
  Agent configuration can be controlled through environment variables when using the startup hook feature.
</note>