Skip to content

Dapr bits #929

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 8 commits into from
May 17, 2024
Merged
Show file tree
Hide file tree
Changes from 2 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
75 changes: 74 additions & 1 deletion docs/frameworks/dapr.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,12 @@

## Prerequisites

- TODO: Add prerequisites
- .NET 8.0 SDK or later
- .NET Aspire workload
- Docker
- Dapr version 1.13 or later

Dapr installation instructions can be found [here](https://docs.dapr.io/getting-started/install-dapr-cli/). After installing the Dapr CLI, remember to run dapr init as described [here](https://docs.dapr.io/getting-started/install-dapr-selfhost/).

For more information, see [.NET Aspire setup and tooling](../fundamentals/setup-tooling.md).

Expand All @@ -37,3 +42,71 @@
---

For more information, see [dotnet add package](/dotnet/core/tools/dotnet-add-package) or [Manage package dependencies in .NET applications](/dotnet/core/tools/dependencies).

The Dapr resource is added to the .NET Aspire distributed application builder using the `AddDapr()` method.
An overload of the `AddDapr()` method that accepts Dapr options is available. For most applications, the default options will suffice.

:::code language="csharp" source="snippets/Dapr/Dapr.AppHost/Program.cs" range="4":::

Dapr uses the Sidecar pattern to run alongside your application. The Dapr sidecar is a lightweight, portable, and stateless HTTP server that listens for incoming HTTP requests from your application. The sidecar is responsible for managing the lifecycle of your application, including service discovery, configuration, and secrets management. To add a sidecar to a .NET Aspire resource by using the `WithDaprSidecar(string appId)` method. The `appId` parameter is the unique identifier for the Dapr application.

:::code language="csharp" source="snippets/Dapr/Dapr.AppHost/Program.cs" range="18-21" highlight="21":::

The WithDaprSidecar method offers overloads to configure your Dapr sidecar options like app ID and ports. In the following example the Dapr sidecar is configured with specific ports for GRPC, HTTP, Metrics and a specific App ID.

:::code language="csharp" source="snippets/Dapr/Dapr.AppHost/Program.cs" range="6-16" highlight="6-12,16":::

Putting everything together, here is an example of an Aspire AppHost project which includes:
- A backend that declares a Dapr sidecar with specific ports and app ID.

Check failure on line 60 in docs/frameworks/dapr.md

View workflow job for this annotation

GitHub Actions / lint

Lists should be surrounded by blank lines [Context: "- A backend that declares a Da..."]
- A frontend that declares a Dapr sidecar with a specific app ID and default ports.

:::code language="csharp" source="snippets/Dapr/Dapr.AppHost/Program.cs":::

The .NET Aspire dashboard will shows the Dapr sidecar as a resource, with its status and logs.

:::image type="content" source="media/aspire-dashboard-dapr-sidecar-resources.png" lightbox="media/aspire-dashboard-dapr-sidecar-resources.png" alt-text=".NET Aspire dashboard showing Dapr sidecar resources":::

## Adding the Dapr SDK

To use Dapr APIs from .NET Aspire resources you can use the [Dapr SDK for ASP.Net Core](https://www.nuget.org/packages/Dapr.AspNetCore/). The Dapr SDK provides a set of APIs to interact with Dapr sidecars.

Check failure on line 71 in docs/frameworks/dapr.md

View workflow job for this annotation

GitHub Actions / lint

Proper names should have the correct capitalization [Expected: ASP.NET; Actual: ASP.Net]

### [.NET CLI](#tab/dotnet-cli)

```dotnetcli
dotnet add package Dapr.AspNetCore
```

### [PackageReference](#tab/package-reference)

```xml
<PackageReference Include="Dapr.AspNetCore"
Version="[SelectVersion]" />
```

Once installed into an ASP.Net Core project, the SDK can be added to the service builder.

Check failure on line 86 in docs/frameworks/dapr.md

View workflow job for this annotation

GitHub Actions / lint

Proper names should have the correct capitalization [Expected: ASP.NET; Actual: ASP.Net]

:::code language="csharp" source="snippets/Dapr/Dapr.Web/Program.cs" range="15":::

An instance of `DaprClient` can now be injected into your services to interact with the Dapr sidecar through the Dapr SDK.

:::code language="csharp" source="snippets/Dapr/Dapr.Web/WeatherApiClient.cs" highlight="9-10":::

`InvokeMethodAsync` is a method that sends an HTTP request to the Dapr sidecar. It is a generic method that takes an HTTP verb, the Dapr app ID of the service to call, the method name and a cancellation token. Depending on the HTTP verb it can also take a request body and headers. The generic type parameter is the type of the response body.

The full `Program.cs` file for the frontend project shows the Dapr Client being added to the service builder and the `WeatherApiClient` class that uses the Dapr Client to call the backend service.

:::code language="csharp" source="snippets/Dapr/Dapr.Web/Program.cs" highlight="15,17":::

In, for example, a Blazor project the `WeatherApiClient` class can be injected into a component and used to call the backend service.

:::code language="csharp" source="snippets/Dapr/Dapr.Web/Components/Pages/Weather.razor" highlight="5,47":::

What actually happens when the Dapr SDK is used is that the Dapr sidecar is called over HTTP. The Dapr sidecar then forwards the request to the target service. The target service can be running in the same process as the Dapr sidecar or in a different process. The Dapr sidecar is responsible for service discovery and routing the request to the target service.

## Dapr and .NET Aspire

At first sight Dapr and .NET Aspire may look like they have overlapping functionality, and they do. However, they both take a different approach. .NET Aspire is an opiniated approach on how to build distributed applications on a cloud platform. Dapr is a runtime that abstracts away the common complexities of the underlying cloud platform. It relies on sidecars to provide abstractions for things like configuration, secret management and messaging. The underlying technology can be easily switched out through configuration files, while your code does not need to change.

.NET Aspire makes setting up and debugging Dapr applications easier by providing a straightforward API to configure Dapr sidecars, and by exposing the sidecars as resources in the dashboard.

[.NET Aspire Dapr sample app] (https://learn.microsoft.com/en-us/samples/dotnet/aspire-samples/aspire-dapr/)

Check failure on line 112 in docs/frameworks/dapr.md

View workflow job for this annotation

GitHub Actions / lint

Bare URL used [Context: "https://learn.microsoft.com/en..."]

Check failure on line 112 in docs/frameworks/dapr.md

View workflow job for this annotation

GitHub Actions / lint

Files should end with a single newline character
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<Project Sdk="Microsoft.NET.Sdk.Web">

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

<ItemGroup>
<ProjectReference Include="..\Dapr.ServiceDefaults\Dapr.ServiceDefaults.csproj" />
</ItemGroup>

</Project>
39 changes: 39 additions & 0 deletions docs/frameworks/snippets/Dapr/Dapr.ApiService/Program.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
var builder = WebApplication.CreateBuilder(args);

// Add service defaults & Aspire components.
builder.AddServiceDefaults();

// Add services to the container.
builder.Services.AddProblemDetails();

var app = builder.Build();

// Configure the HTTP request pipeline.
app.UseExceptionHandler();

var summaries = new[]
{
"Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching"
};

app.MapGet("/weatherforecast", () =>
{
var forecast = Enumerable.Range(1, 5).Select(index =>
new WeatherForecast
(
DateOnly.FromDateTime(DateTime.Now.AddDays(index)),
Random.Shared.Next(-20, 55),
summaries[Random.Shared.Next(summaries.Length)]
))
.ToArray();
return forecast;
});

app.MapDefaultEndpoints();

app.Run();

record WeatherForecast(DateOnly Date, int TemperatureC, string? Summary)
{
public int TemperatureF => 32 + (int)(TemperatureC / 0.5556);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
{
"$schema": "https://json.schemastore.org/launchsettings.json",
"profiles": {
"http": {
"commandName": "Project",
"dotnetRunMessages": true,
"launchBrowser": true,
"launchUrl": "weatherforecast",
"applicationUrl": "http://localhost:5463",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
},
"https": {
"commandName": "Project",
"dotnetRunMessages": true,
"launchBrowser": true,
"launchUrl": "weatherforecast",
"applicationUrl": "https://localhost:7487;http://localhost:5463",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
},
"AllowedHosts": "*"
}
22 changes: 22 additions & 0 deletions docs/frameworks/snippets/Dapr/Dapr.AppHost/Dapr.AppHost.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<IsAspireHost>true</IsAspireHost>
<UserSecretsId>0bd3d839-67a8-422d-aee2-bd9f1c0556a1</UserSecretsId>
</PropertyGroup>

<ItemGroup>
<ProjectReference Include="..\Dapr.ApiService\Dapr.ApiService.csproj" />
<ProjectReference Include="..\Dapr.Web\Dapr.Web.csproj" />
</ItemGroup>

<ItemGroup>
<PackageReference Include="Aspire.Hosting.AppHost" Version="8.0.0-preview.7.24251.11" />
<PackageReference Include="Aspire.Hosting.Dapr" Version="8.0.0-preview.7.24251.11" />
</ItemGroup>

</Project>
23 changes: 23 additions & 0 deletions docs/frameworks/snippets/Dapr/Dapr.AppHost/Program.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
using Aspire.Hosting.Dapr;

var builder = DistributedApplication.CreateBuilder(args);
builder.AddDapr();

DaprSidecarOptions sidecarOptions = new ()
{
AppId = "apiservice-dapr",
DaprGrpcPort = 50001,
DaprHttpPort = 3500,
MetricsPort = 9090
};

var apiService = builder
.AddProject<Projects.Dapr_ApiService>("apiservice")
.WithDaprSidecar(sidecarOptions);

builder.AddProject<Projects.Dapr_Web>("webfrontend")
.WithExternalHttpEndpoints()
.WithReference(apiService)
.WithDaprSidecar("webfrontend-dapr");

builder.Build().Run();
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
{
"$schema": "https://json.schemastore.org/launchsettings.json",
"profiles": {
"https": {
"commandName": "Project",
"dotnetRunMessages": true,
"launchBrowser": true,
"applicationUrl": "https://localhost:17181;http://localhost:15032",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development",
"DOTNET_ENVIRONMENT": "Development",
"DOTNET_DASHBOARD_OTLP_ENDPOINT_URL": "https://localhost:21181",
"DOTNET_RESOURCE_SERVICE_ENDPOINT_URL": "https://localhost:22225"
}
},
"http": {
"commandName": "Project",
"dotnetRunMessages": true,
"launchBrowser": true,
"applicationUrl": "http://localhost:15032",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development",
"DOTNET_ENVIRONMENT": "Development",
"DOTNET_DASHBOARD_OTLP_ENDPOINT_URL": "http://localhost:19169",
"DOTNET_RESOURCE_SERVICE_ENDPOINT_URL": "http://localhost:20292"
}
}
}
}
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 docs/frameworks/snippets/Dapr/Dapr.AppHost/appsettings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning",
"Aspire.Hosting.Dcp": "Warning"
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<IsAspireSharedProject>true</IsAspireSharedProject>
</PropertyGroup>

<ItemGroup>
<FrameworkReference Include="Microsoft.AspNetCore.App" />

<PackageReference Include="Microsoft.Extensions.Http.Resilience" Version="8.3.0" />
<PackageReference Include="Microsoft.Extensions.ServiceDiscovery" Version="8.0.0-preview.7.24251.11" />
<PackageReference Include="OpenTelemetry.Exporter.OpenTelemetryProtocol" Version="1.8.1" />
<PackageReference Include="OpenTelemetry.Extensions.Hosting" Version="1.8.1" />
<PackageReference Include="OpenTelemetry.Instrumentation.AspNetCore" Version="1.8.1" />
<PackageReference Include="OpenTelemetry.Instrumentation.Http" Version="1.8.1" />
<PackageReference Include="OpenTelemetry.Instrumentation.Runtime" Version="1.8.0" />
</ItemGroup>

</Project>
Loading
Loading