diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS
index d55f7ebf8..a35ece820 100644
--- a/.github/CODEOWNERS
+++ b/.github/CODEOWNERS
@@ -6,3 +6,7 @@
# The '*' pattern is global owners.
* @IEvangelist
+
+# Community Toolkit docs
+
+# /docs/community-toolkit/* @aaronpowell
diff --git a/.github/dependabot.yml b/.github/dependabot.yml
index d1906a080..ad34f895e 100644
--- a/.github/dependabot.yml
+++ b/.github/dependabot.yml
@@ -118,6 +118,17 @@ updates:
dotnet:
patterns:
- "*" # Prefer a single PR per solution update.
+ - package-ecosystem: "nuget"
+ directory: "/docs/fundamentals/dashboard/snippets/BrowserTelemetry" #BrowserTelemetry.sln
+ schedule:
+ interval: "weekly"
+ day: "wednesday"
+ open-pull-requests-limit: 5
+ groups:
+ # Group .NET updates together for solutions.
+ dotnet:
+ patterns:
+ - "*" # Prefer a single PR per solution update.
- package-ecosystem: "nuget"
directory: "/docs/fundamentals/snippets/healthz/Healthz.ServiceDefaults" #healthz.sln
schedule:
@@ -613,6 +624,28 @@ updates:
dotnet:
patterns:
- "*" # Prefer a single PR per project update.
+ - package-ecosystem: "nuget"
+ directory: "/docs/fundamentals/dashboard/snippets/BrowserTelemetry/BrowserTelemetry.AppHost" #BrowserTelemetry.AppHost.csproj
+ schedule:
+ interval: "weekly"
+ day: "wednesday"
+ open-pull-requests-limit: 5
+ groups:
+ # Group .NET updates together for projects.
+ dotnet:
+ patterns:
+ - "*" # Prefer a single PR per project update.
+ - package-ecosystem: "nuget"
+ directory: "/docs/fundamentals/dashboard/snippets/BrowserTelemetry/BrowserTelemetry.ServiceDefaults" #BrowserTelemetry.ServiceDefaults.csproj
+ schedule:
+ interval: "weekly"
+ day: "wednesday"
+ open-pull-requests-limit: 5
+ groups:
+ # Group .NET updates together for projects.
+ dotnet:
+ patterns:
+ - "*" # Prefer a single PR per project update.
- package-ecosystem: "nuget"
directory: "/docs/fundamentals/snippets/integrations/AspireApp/AspireApp.AppHost" #AspireApp.AppHost.csproj
schedule:
diff --git a/.github/policies/auto-merge.yml b/.github/policies/auto-merge.yml
index c77c910f7..b3d49e004 100644
--- a/.github/policies/auto-merge.yml
+++ b/.github/policies/auto-merge.yml
@@ -8,36 +8,41 @@ where:
configuration:
resourceManagementConfiguration:
eventResponderTasks:
- - description: Approve and auto-squash-merge PRs to main labeled with 'auto-merge'
- triggerOnOwnActions: true
- if:
- - payloadType: Pull_Request
- - labelAdded:
- label: ":octocat: auto-merge"
- - targetsBranch:
- branch: main
- then:
- - approvePullRequest:
- comment: "Approved; this PR will merge when all status checks pass."
- - enableAutoMerge:
- mergeMethod: Squash
+ - description: Approve and auto-squash-merge bot PRs to main labeled 'auto-merge'
+ triggerOnOwnActions: true
+ if:
+ - payloadType: Pull_Request
+ - labelAdded:
+ label: ':octocat: auto-merge'
+ - targetsBranch:
+ branch: main
+ - or:
+ - isActivitySender:
+ user: dotnet-policy-service[bot]
+ then:
+ - enableAutoMerge:
+ mergeMethod: Squash
+ - approvePullRequest:
+ comment: "Approved; this PR will merge when all status checks pass."
- - description: Auto-merge PRs to live labeled with 'auto-merge'
- triggerOnOwnActions: true
- if:
- - payloadType: Pull_Request
- - labelAdded:
- label: ":octocat: auto-merge"
- - targetsBranch:
- branch: live
- then:
- - enableAutoMerge:
- mergeMethod: Merge
+ - description: Auto-merge policy service bot PRs to live labeled 'auto-merge'
+ triggerOnOwnActions: true
+ if:
+ - payloadType: Pull_Request
+ - labelAdded:
+ label: ':octocat: auto-merge'
+ - targetsBranch:
+ branch: live
+ - isActivitySender:
+ user: dotnet-policy-service[bot]
+ then:
+ - enableAutoMerge:
+ mergeMethod: Merge
- - description: Don't auto-merge PRs with 'auto-merge' label removed
- if:
- - payloadType: Pull_Request
- - labelRemoved:
- label: ":octocat: auto-merge"
- then:
- - disableAutoMerge
+ - description: Don't auto-merge PRs with 'auto-merge' label removed
+ if:
+ - payloadType: Pull_Request
+ - labelRemoved:
+ label: ':octocat: auto-merge'
+ then:
+ - disableAutoMerge
diff --git a/.github/workflows/check-for-build-warnings.yml b/.github/workflows/check-for-build-warnings.yml
index fca5e5685..1a266c649 100644
--- a/.github/workflows/check-for-build-warnings.yml
+++ b/.github/workflows/check-for-build-warnings.yml
@@ -21,7 +21,7 @@ jobs:
with:
egress-policy: audit
- - uses: dotnet/docs-tools/actions/status-checker@cf581edfb9f8bbccc3f0476ce1b8369689fb0290 # main
+ - uses: dotnet/docs-tools/actions/status-checker@691b5550e4b848ac76bd61a3d135754b029884be # main
with:
repo_token: ${{ secrets.GITHUB_TOKEN }}
docs_path: "docs"
diff --git a/.github/workflows/clean-repo.yml b/.github/workflows/clean-repo.yml
index 022f805b7..d166b2671 100644
--- a/.github/workflows/clean-repo.yml
+++ b/.github/workflows/clean-repo.yml
@@ -22,7 +22,7 @@ jobs:
with:
egress-policy: audit
- - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
+ - uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4.2.1
# Call clean repo
- name: Clean repo
diff --git a/.github/workflows/dependabot-bot.yml b/.github/workflows/dependabot-bot.yml
index df3b8aa13..9f53a192d 100644
--- a/.github/workflows/dependabot-bot.yml
+++ b/.github/workflows/dependabot-bot.yml
@@ -30,7 +30,7 @@ jobs:
with:
egress-policy: audit
- - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
+ - uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4.2.1
# - name: Setup .NET
# uses: actions/setup-dotnet@4d4a70f4a5b2a5a5329f13be4ac933f2c9206ac0
# with:
diff --git a/.github/workflows/dependency-review.yml b/.github/workflows/dependency-review.yml
index c1209291a..7b0990bcf 100644
--- a/.github/workflows/dependency-review.yml
+++ b/.github/workflows/dependency-review.yml
@@ -22,6 +22,6 @@ jobs:
egress-policy: audit
- name: 'Checkout Repository'
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
+ uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4.2.1
- name: 'Dependency Review'
uses: actions/dependency-review-action@5a2ce3f5b92ee19cbb1541a4984c76d921601d7c # v4.3.4
diff --git a/.github/workflows/dispatch-merge-main-to-live.yml b/.github/workflows/dispatch-merge-main-to-live.yml
index ff1f13e79..698c7e84a 100644
--- a/.github/workflows/dispatch-merge-main-to-live.yml
+++ b/.github/workflows/dispatch-merge-main-to-live.yml
@@ -32,7 +32,7 @@ jobs:
echo 'Reason: ${{ github.event.inputs.reason }}'
- name: Check out code
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # main
+ uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # main
- name: Check for existing PR
id: exists
diff --git a/.github/workflows/markdownlint.yml b/.github/workflows/markdownlint.yml
index 260f56fdb..181206973 100644
--- a/.github/workflows/markdownlint.yml
+++ b/.github/workflows/markdownlint.yml
@@ -31,7 +31,7 @@ jobs:
with:
egress-policy: audit
- - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
+ - uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4.2.1
- uses: DavidAnson/markdownlint-cli2-action@db43aef879112c3119a410d69f66701e0d530809 # v17.0.0
with:
config: ".markdownlint-cli2.jsonc"
diff --git a/.github/workflows/scorecards.yml b/.github/workflows/scorecards.yml
index 7e34ce18d..ed7838077 100644
--- a/.github/workflows/scorecards.yml
+++ b/.github/workflows/scorecards.yml
@@ -36,7 +36,7 @@ jobs:
egress-policy: audit
- name: "Checkout code"
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
+ uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4.2.1
with:
persist-credentials: false
@@ -63,7 +63,7 @@ jobs:
# Upload the results as artifacts (optional). Commenting out will disable uploads of run results in SARIF
# format to the repository Actions tab.
- name: "Upload artifact"
- uses: actions/upload-artifact@50769540e7f4bd5e21e526ee35c689e35e0d6874 # v4.4.0
+ uses: actions/upload-artifact@b4b15b8c7c6ac21ea08fcf65892d2ee8f75cf882 # v4.4.3
with:
name: SARIF file
path: results.sarif
@@ -71,6 +71,6 @@ jobs:
# Upload the results to GitHub's code scanning dashboard.
- name: "Upload to code-scanning"
- uses: github/codeql-action/upload-sarif@461ef6c76dfe95d5c364de2f431ddbd31a417628 # v3.26.9
+ uses: github/codeql-action/upload-sarif@f779452ac5af1c261dce0346a8f964149f49322b # v3.26.13
with:
sarif_file: results.sarif
diff --git a/.github/workflows/snippets5000.yml b/.github/workflows/snippets5000.yml
index ba325427d..1fd6fda81 100644
--- a/.github/workflows/snippets5000.yml
+++ b/.github/workflows/snippets5000.yml
@@ -38,7 +38,7 @@ jobs:
with:
egress-policy: audit
- - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
+ - uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4.2.1
# Get the latest preview SDK (or sdk not installed by the runner)
- name: Setup .NET
@@ -70,7 +70,7 @@ jobs:
# Update build output json file
- name: Upload build results
- uses: actions/upload-artifact@50769540e7f4bd5e21e526ee35c689e35e0d6874 #@v4.4.0
+ uses: actions/upload-artifact@b4b15b8c7c6ac21ea08fcf65892d2ee8f75cf882 #@v4.4.3
with:
name: build
path: ./output.json
diff --git a/.github/workflows/whats-new-automation.yml b/.github/workflows/whats-new-automation.yml
index 470274af8..6292e0a30 100644
--- a/.github/workflows/whats-new-automation.yml
+++ b/.github/workflows/whats-new-automation.yml
@@ -27,7 +27,7 @@ jobs:
with:
egress-policy: audit
- - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
+ - uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4.2.1
- name: "Print manual run reason"
if: ${{ github.event_name == 'workflow_dispatch' }}
diff --git a/.gitignore b/.gitignore
index c70ca92e0..8a39666e8 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,3 +1,5 @@
+syntax: glob
+
# Python virtual environments
.venv
@@ -59,4 +61,6 @@ docs/core/extensions/snippets/workers/cloud-service/Properties/PublishProfiles/c
docs/csharp/language-reference/xmldoc/snippets/xmldoc/xmldoc.xml
BenchmarkDotNet.Artifacts
-*.pfx
\ No newline at end of file
+*.pfx
+
+node_modules/
\ No newline at end of file
diff --git a/.markdownlint-cli2.jsonc b/.markdownlint-cli2.jsonc
index e199cd007..689ad3824 100644
--- a/.markdownlint-cli2.jsonc
+++ b/.markdownlint-cli2.jsonc
@@ -25,6 +25,7 @@
"code",
"em",
"h4",
+ "img",
"kbd",
"li",
"ol",
diff --git a/.openpublishing.redirection.json b/.openpublishing.redirection.json
index 8930680fa..7bd76b7b6 100644
--- a/.openpublishing.redirection.json
+++ b/.openpublishing.redirection.json
@@ -263,6 +263,10 @@
{
"source_path_from_root": "/docs/extensibility/implement-auth-from-resource-to-integration.md",
"redirect_url": "/dotnet/aspire/extensibility/secure-communication-between-integrations"
+ },
+ {
+ "source_path_from_root": "/docs/messaging/rabbitmq-client-integration.md",
+ "redirect_url": "/dotnet/aspire/messaging/rabbitmq-integration"
}
]
}
\ No newline at end of file
diff --git a/docfx.json b/docfx.json
index bf71ecc36..d92bbb6f6 100644
--- a/docfx.json
+++ b/docfx.json
@@ -104,16 +104,16 @@
},
"author": {
"docs/**/*.*": "IEvangelist",
+ "docs/community-toolkit/**/*.*": "aaronpowell",
"docs/database/**/*.*": "CamSoper",
"docs/storage/**/*.*": "CamSoper",
- "docs/messaging/**/*.*": "CamSoper",
"docs/deployment/**/*.*": "CamSoper"
},
"ms.author": {
"docs/**/*.*": "dapine",
+ "docs/community-toolkit/**/*.*": "aapowell",
"docs/database/**/*.*": "casoper",
"docs/storage/**/*.*": "casoper",
- "docs/messaging/**/*.*": "casoper",
"docs/deployment/**/*.*": "casoper"
},
"ms.collection": {
diff --git a/docs/authentication/keycloak-integration.md b/docs/authentication/keycloak-integration.md
index 961625613..771002790 100644
--- a/docs/authentication/keycloak-integration.md
+++ b/docs/authentication/keycloak-integration.md
@@ -30,7 +30,7 @@ dotnet add package Aspire.Keycloak.Authentication
```xml
+ Version="*" />
```
---
@@ -84,7 +84,7 @@ dotnet add package Aspire.Hosting.Keycloak
```xml
+ Version="*" />
```
---
diff --git a/docs/azureai/azureai-openai-integration.md b/docs/azureai/azureai-openai-integration.md
index e9ccb59e9..1f2134e96 100644
--- a/docs/azureai/azureai-openai-integration.md
+++ b/docs/azureai/azureai-openai-integration.md
@@ -28,7 +28,7 @@ dotnet add package Aspire.Azure.AI.OpenAI
```xml
+ Version="*" />
```
---
@@ -66,7 +66,7 @@ dotnet add package Aspire.Hosting.Azure.CognitiveServices
```xml
+ Version="*" />
```
---
diff --git a/docs/azureai/azureai-search-document-integration.md b/docs/azureai/azureai-search-document-integration.md
index ab47f86c4..4ce9469de 100644
--- a/docs/azureai/azureai-search-document-integration.md
+++ b/docs/azureai/azureai-search-document-integration.md
@@ -28,7 +28,7 @@ dotnet add package Aspire.Azure.Search.Documents
```xml
+ Version="*" />
```
---
@@ -87,7 +87,7 @@ dotnet add package Aspire.Hosting.Azure.Search
```xml
+ Version="*" />
```
---
diff --git a/docs/caching/caching-integrations.md b/docs/caching/caching-integrations.md
index 51482986c..6fd186392 100644
--- a/docs/caching/caching-integrations.md
+++ b/docs/caching/caching-integrations.md
@@ -55,7 +55,7 @@ Visual Studio creates a new .NET Aspire solution that consists of the following
```xml
+ Version="*" />
```
---
diff --git a/docs/caching/includes/garnet-app-host.md b/docs/caching/includes/garnet-app-host.md
index 30cada3c6..a56231f60 100644
--- a/docs/caching/includes/garnet-app-host.md
+++ b/docs/caching/includes/garnet-app-host.md
@@ -1,4 +1,8 @@
-To model the Garnet resource (`GarnetResource`) in the app host, install the [Aspire.Hosting.Garnet](https://www.nuget.org/packages/Aspire.Hosting.Garnet) NuGet package in the [app host](xref:aspire/app-host) project.
+---
+ms.topic: include
+---
+
+The Garnet hosting integration models a Garnet resource as the type. To access this type and APIs that allow you to add it to your [app model](xref:aspire/app-host#define-the-app-model), install the [📦 Aspire.Hosting.Garnet](https://www.nuget.org/packages/Aspire.Hosting.Garnet) NuGet package in the [app host](xref:aspire/app-host) project.
### [.NET CLI](#tab/dotnet-cli)
@@ -10,12 +14,16 @@ dotnet add package Aspire.Hosting.Garnet
```xml
+ Version="*" />
```
---
-In your app host project, register .NET Aspire Garnet as a `GarnetResource` using the `AddGarnet` method and consume the service using the following methods:
+For more information, see [dotnet add package](/dotnet/core/tools/dotnet-add-package) or [Manage package dependencies in .NET applications](/dotnet/core/tools/dependencies).
+
+### Add Garnet resource
+
+In your app host project, call on the `builder` instance to add a Garnet resource:
```csharp
var builder = DistributedApplication.CreateBuilder(args);
@@ -23,11 +31,75 @@ var builder = DistributedApplication.CreateBuilder(args);
var cache = builder.AddGarnet("cache");
builder.AddProject()
- .WithReference(cache)
+ .WithReference(cache);
+
+// After adding all resources, run the app...
```
-The method configures a connection in the `ExampleProject` project named `cache`. In the _:::no-loc text="Program.cs":::_ file of `ExampleProject`, the Garnet connection can be consumed using:
+When .NET Aspire adds a container image to the app host, as shown in the preceding example with the `ghcr.io/microsoft/garnet` image, it creates a new Garnet instance on your local machine. A reference to your Garnet resource (the `cache` variable) is added to the `ExampleProject`.
+
+The method configures a connection in the `ExampleProject` named `"cache"`. For more information, see [Container resource lifecycle](../../fundamentals/app-host-overview.md#container-resource-lifecycle).
+
+> [!TIP]
+> If you'd rather connect to an existing Garnet instance, call instead. For more information, see [Reference existing resources](../../fundamentals/app-host-overview.md#reference-existing-resources).
+
+### Add Garnet resource with data volume
+
+To add a data volume to the Garnet resource, call the method on the Garnet resource:
```csharp
-builder.AddGarnet("cache");
+var builder = DistributedApplication.CreateBuilder(args);
+
+var cache = builder.AddGarnet("cache")
+ .WithDataVolume(isReadOnly: false);
+
+builder.AddProject()
+ .WithReference(cache);
+
+// After adding all resources, run the app...
```
+
+The data volume is used to persist the Garnet data outside the lifecycle of its container. The data volume is mounted at the `/data` path in the Garnet container and when a `name` parameter isn't provided, the name is generated at random. For more information on data volumes and details on why they're preferred over [bind mounts](#add-garnet-resource-with-data-bind-mount), see [Docker docs: Volumes](https://docs.docker.com/engine/storage/volumes).
+
+### Add Garnet resource with data bind mount
+
+To add a data bind mount to the Garnet resource, call the method:
+
+```csharp
+var builder = DistributedApplication.CreateBuilder(args);
+
+var cache = builder.AddGarnet("cache")
+ .WithDataBindMount(
+ source: @"C:\Garnet\Data",
+ isReadOnly: false);
+
+builder.AddProject()
+ .WithReference(cache);
+
+// After adding all resources, run the app...
+```
+
+[!INCLUDE [data-bind-mount-vs-volumes](../../includes/data-bind-mount-vs-volumes.md)]
+
+Data bind mounts rely on the host machine's filesystem to persist the Garnet data across container restarts. The data bind mount is mounted at the `C:\Garnet\Data` on Windows (or `/Garnet/Data` on Unix) path on the host machine in the Garnet container. For more information on data bind mounts, see [Docker docs: Bind mounts](https://docs.docker.com/engine/storage/bind-mounts).
+
+### Add Garnet resource with persistence
+
+To add persistence to the Garnet resource, call the method with either the data volume or data bind mount:
+
+```csharp
+var builder = DistributedApplication.CreateBuilder(args);
+
+var cache = builder.AddGarnet("cache")
+ .WithDataVolume()
+ .WithPersistence(
+ interval: TimeSpan.FromMinutes(5),
+ keysChangedThreshold: 100);
+
+builder.AddProject()
+ .WithReference(cache);
+
+// After adding all resources, run the app...
+```
+
+The preceding code adds persistence to the Redis resource by taking snapshots of the Garnet data at a specified interval and threshold. The `interval` is time between snapshot exports and the `keysChangedThreshold` is the number of key change operations required to trigger a snapshot. For more information on persistence, see [Redis docs: Persistence](https://redis.io/topics/persistence).
diff --git a/docs/caching/includes/redis-app-host.md b/docs/caching/includes/redis-app-host.md
index 6dbe7074a..9f5190b63 100644
--- a/docs/caching/includes/redis-app-host.md
+++ b/docs/caching/includes/redis-app-host.md
@@ -1,4 +1,8 @@
-To model the Redis resource (`RedisResource`) in the app host, install the [Aspire.Hosting.Redis](https://www.nuget.org/packages/Aspire.Hosting.Redis) NuGet package in the [app host](xref:aspire/app-host) project.
+---
+ms.topic: include
+---
+
+The Redis hosting integration models a Redis resource as the type. To access this type and APIs that allow you to add it to your [app model](xref:aspire/app-host#define-the-app-model), install the [📦 Aspire.Hosting.Redis](https://www.nuget.org/packages/Aspire.Hosting.Redis) NuGet package in the [app host](xref:aspire/app-host) project.
### [.NET CLI](#tab/dotnet-cli)
@@ -10,12 +14,16 @@ dotnet add package Aspire.Hosting.Redis
```xml
+ Version="*" />
```
---
-In your app host project, register the .NET Aspire Stack Exchange Redis as a resource using the method and consume the service using the following methods:
+For more information, see [dotnet add package](/dotnet/core/tools/dotnet-add-package) or [Manage package dependencies in .NET applications](/dotnet/core/tools/dependencies).
+
+### Add Redis resource
+
+In your app host project, call on the `builder` instance to add a Redis resource:
```csharp
var builder = DistributedApplication.CreateBuilder(args);
@@ -23,11 +31,117 @@ var builder = DistributedApplication.CreateBuilder(args);
var cache = builder.AddRedis("cache");
builder.AddProject()
- .WithReference(cache)
+ .WithReference(cache);
+
+// After adding all resources, run the app...
+```
+
+When .NET Aspire adds a container image to the app host, as shown in the preceding example with the `docker.io/Redis/Redis` image, it creates a new Redis instance on your local machine. A reference to your Redis resource (the `cache` variable) is added to the `ExampleProject`.
+
+The method configures a connection in the `ExampleProject` named `"cache"`. For more information, see [Container resource lifecycle](../../fundamentals/app-host-overview.md#container-resource-lifecycle).
+
+> [!TIP]
+> If you'd rather connect to an existing Redis instance, call instead. For more information, see [Reference existing resources](../../fundamentals/app-host-overview.md#reference-existing-resources).
+
+### Add Redis resource with Redis Insights
+
+To add the [Redis Insights](https://redis.io/insight/) to the Redis resource, call the `WithRedisInsights` method:
+
+```csharp
+var builder = DistributedApplication.CreateBuilder(args);
+
+var cache = builder.AddRedis("cache")
+ .WithRedisInsights();
+
+builder.AddProject()
+ .WithReference(cache);
+
+// After adding all resources, run the app...
```
-The method configures a connection in the `ExampleProject` project named `cache`. In the _:::no-loc text="Program.cs":::_ file of `ExampleProject`, the Redis connection can be consumed using:
+Redis Insights is a free graphical interface for analyzing Redis data across all operating systems and Redis deployments with the help of our AI assistant, Redis Copilot. .NET Aspire adds another container image [`docker.io/redis/redisinsight`](https://hub.docker.com/r/redis/redisinsight) to the app host that runs the commander app.
+
+> [!TIP]
+> To configure the host port for the `RedisInsightResource` call `WithHostPort` and provide the desired port number.
+
+### Add Redis resource with Redis Commander
+
+To add the [Redis Commander](https://joeferner.github.io/redis-commander/) to the Redis resource, call the method:
```csharp
-builder.AddRedis("cache");
+var builder = DistributedApplication.CreateBuilder(args);
+
+var cache = builder.AddRedis("cache")
+ .WithRedisCommander();
+
+builder.AddProject()
+ .WithReference(cache);
+
+// After adding all resources, run the app...
```
+
+Redis Commander is a Node.js web application used to view, edit, and manage a Redis Database. .NET Aspire adds another container image [`docker.io/rediscommander/redis-commander`](https://hub.docker.com/r/rediscommander/redis-commander) to the app host that runs the commander app.
+
+> [!TIP]
+> To configure the host port for the call and provide the desired port number.
+
+### Add Redis resource with data volume
+
+To add a data volume to the Redis resource, call the method on the Redis resource:
+
+```csharp
+var builder = DistributedApplication.CreateBuilder(args);
+
+var cache = builder.AddRedis("cache")
+ .WithDataVolume(isReadOnly: false);
+
+builder.AddProject()
+ .WithReference(cache);
+
+// After adding all resources, run the app...
+```
+
+The data volume is used to persist the Redis data outside the lifecycle of its container. The data volume is mounted at the `/data` path in the Redis container and when a `name` parameter isn't provided, the name is generated at random. For more information on data volumes and details on why they're preferred over [bind mounts](#add-redis-resource-with-data-bind-mount), see [Docker docs: Volumes](https://docs.docker.com/engine/storage/volumes).
+
+### Add Redis resource with data bind mount
+
+To add a data bind mount to the Redis resource, call the method:
+
+```csharp
+var builder = DistributedApplication.CreateBuilder(args);
+
+var cache = builder.AddRedis("cache")
+ .WithDataBindMount(
+ source: @"C:\Redis\Data",
+ isReadOnly: false);
+
+builder.AddProject()
+ .WithReference(cache);
+
+// After adding all resources, run the app...
+```
+
+[!INCLUDE [data-bind-mount-vs-volumes](../../includes/data-bind-mount-vs-volumes.md)]
+
+Data bind mounts rely on the host machine's filesystem to persist the Redis data across container restarts. The data bind mount is mounted at the `C:\Redis\Data` on Windows (or `/Redis/Data` on Unix) path on the host machine in the Redis container. For more information on data bind mounts, see [Docker docs: Bind mounts](https://docs.docker.com/engine/storage/bind-mounts).
+
+### Add Redis resource with persistence
+
+To add persistence to the Redis resource, call the method with either the data volume or data bind mount:
+
+```csharp
+var builder = DistributedApplication.CreateBuilder(args);
+
+var cache = builder.AddRedis("cache")
+ .WithDataVolume()
+ .WithPersistence(
+ interval: TimeSpan.FromMinutes(5),
+ keysChangedThreshold: 100);
+
+builder.AddProject()
+ .WithReference(cache);
+
+// After adding all resources, run the app...
+```
+
+The preceding code adds persistence to the Redis resource by taking snapshots of the Redis data at a specified interval and threshold. The `interval` is time between snapshot exports and the `keysChangedThreshold` is the number of key change operations required to trigger a snapshot. For more information on persistence, see [Redis docs: Persistence](https://redis.io/topics/persistence).
diff --git a/docs/caching/includes/redis-client-json-settings.md b/docs/caching/includes/redis-client-json-settings.md
new file mode 100644
index 000000000..a47512472
--- /dev/null
+++ b/docs/caching/includes/redis-client-json-settings.md
@@ -0,0 +1,21 @@
+---
+ms.topic: include
+---
+
+The .NET Aspire Stack Exchange Redis integration supports . It loads the from configuration by using the `Aspire:StackExchange:Redis` key. Example _:::no-loc text="appsettings.json":::_ that configures some of the options:
+
+```json
+{
+ "Aspire": {
+ "StackExchange": {
+ "Redis": {
+ "ConnectionString": "localhost:6379",
+ "DisableHealthChecks": true,
+ "DisableTracing": false
+ }
+ }
+ }
+}
+```
+
+For the complete Redis client integration JSON schema, see [Aspire.StackExchange.Redis/ConfigurationSchema.json](https://github.com/dotnet/aspire/blob/v8.2.1/src/Components/Aspire.StackExchange.Redis/ConfigurationSchema.json).
diff --git a/docs/caching/includes/redis-hosting-health-checks.md b/docs/caching/includes/redis-hosting-health-checks.md
new file mode 100644
index 000000000..956e4b511
--- /dev/null
+++ b/docs/caching/includes/redis-hosting-health-checks.md
@@ -0,0 +1,7 @@
+---
+ms.topic: include
+---
+
+The Redis hosting integration automatically adds a health check for the appropriate resource type. The health check verifies that the server is running and that a connection can be established to it.
+
+The hosting integration relies on the [📦 AspNetCore.HealthChecks.Redis](https://www.nuget.org/packages/AspNetCore.HealthChecks.Redis) NuGet package.
diff --git a/docs/caching/includes/redis-trademark.md b/docs/caching/includes/redis-trademark.md
new file mode 100644
index 000000000..d2a7b695f
--- /dev/null
+++ b/docs/caching/includes/redis-trademark.md
@@ -0,0 +1,5 @@
+---
+ms.topic: include
+---
+
+> *****: _Redis is a registered trademark of Redis Ltd. Any rights therein are reserved to Redis Ltd. Any use by Microsoft is for referential purposes only and does not indicate any sponsorship, endorsement or affiliation between Redis and Microsoft. [Return to top](#heading)?_
diff --git a/docs/caching/includes/valkey-app-host.md b/docs/caching/includes/valkey-app-host.md
index ca44e5b48..bf08b2644 100644
--- a/docs/caching/includes/valkey-app-host.md
+++ b/docs/caching/includes/valkey-app-host.md
@@ -1,4 +1,8 @@
-To model the Valkey resource (`ValkeyResource`) in the app host, install the [Aspire.Hosting.Valkey](https://www.nuget.org/packages/Aspire.Hosting.Valkey) NuGet package in the [app host](xref:aspire/app-host) project.
+---
+ms.topic: include
+---
+
+The Valkey hosting integration models a Valkey resource as the type. To access this type and APIs that allow you to add it to your [app model](xref:aspire/app-host#define-the-app-model), install the [📦 Aspire.Hosting.Valkey](https://www.nuget.org/packages/Aspire.Hosting.Valkey) NuGet package in the [app host](xref:aspire/app-host) project.
### [.NET CLI](#tab/dotnet-cli)
@@ -10,12 +14,16 @@ dotnet add package Aspire.Hosting.Valkey
```xml
+ Version="*" />
```
---
-In your app host project, register the .NET Aspire Valkey as a resource using the `AddValkey` method and consume the service using the following methods:
+For more information, see [dotnet add package](/dotnet/core/tools/dotnet-add-package) or [Manage package dependencies in .NET applications](/dotnet/core/tools/dependencies).
+
+### Add Valkey resource
+
+In your app host project, call on the `builder` instance to add a Valkey resource:
```csharp
var builder = DistributedApplication.CreateBuilder(args);
@@ -23,11 +31,76 @@ var builder = DistributedApplication.CreateBuilder(args);
var cache = builder.AddValkey("cache");
builder.AddProject()
- .WithReference(cache)
+ .WithReference(cache);
+
+// After adding all resources, run the app...
```
-The method configures a connection in the `ExampleProject` project named `cache`. In the _:::no-loc text="Program.cs":::_ file of `ExampleProject`, the Valkey connection can be consumed using:
+When .NET Aspire adds a container image to the app host, as shown in the preceding example with the `docker.io/valkey/valkey` image, it creates a new Valkey instance on your local machine. A reference to your Valkey resource (the `cache` variable) is added to the `ExampleProject`.
+
+The method configures a connection in the `ExampleProject` named `"cache"`. For more information, see [Container resource lifecycle](../../fundamentals/app-host-overview.md#container-resource-lifecycle).
+
+> [!TIP]
+> If you'd rather connect to an existing Valkey instance, call instead. For more information, see [Reference existing resources](../../fundamentals/app-host-overview.md#reference-existing-resources).
+
+### Add Valkey resource with data volume
+
+To add a data volume to the Valkey resource, call the method on the Valkey resource:
```csharp
-builder.AddValkey("cache");
+var builder = DistributedApplication.CreateBuilder(args);
+
+var cache = builder.AddValkey("cache")
+ .WithDataVolume(isReadOnly: false);
+
+builder.AddProject()
+ .WithReference(cache);
+
+// After adding all resources, run the app...
```
+
+The data volume is used to persist the Valkey data outside the lifecycle of its container. The data volume is mounted at the `/data` path in the Valkey container and when a `name` parameter isn't provided, the name is generated at random. For more information on data volumes and details on why they're preferred over [bind mounts](#add-valkey-resource-with-data-bind-mount), see [Docker docs: Volumes](https://docs.docker.com/engine/storage/volumes).
+
+### Add Valkey resource with data bind mount
+
+To add a data bind mount to the Valkey resource, call the method:
+
+```csharp
+var builder = DistributedApplication.CreateBuilder(args);
+
+var cache = builder.AddValkey("cache")
+ .WithDataBindMount(
+ source: @"C:\Valkey\Data",
+ isReadOnly: false);
+
+builder.AddProject()
+ .WithReference(cache);
+
+// After adding all resources, run the app...
+```
+
+[!INCLUDE [data-bind-mount-vs-volumes](../../includes/data-bind-mount-vs-volumes.md)]
+
+Data bind mounts rely on the host machine's filesystem to persist the Valkey data across container restarts. The data bind mount is mounted at the `C:\Valkey\Data` on Windows (or `/Valkey/Data` on Unix) path on the host machine in the Valkey container. For more information on data bind mounts, see [Docker docs: Bind mounts](https://docs.docker.com/engine/storage/bind-mounts).
+
+### Add Valkey resource with persistence
+
+To add persistence to the Valkey resource, call the
+method with either the data volume or data bind mount:
+
+```csharp
+var builder = DistributedApplication.CreateBuilder(args);
+
+var cache = builder.AddValkey("cache")
+ .WithDataVolume()
+ .WithPersistence(
+ interval: TimeSpan.FromMinutes(5),
+ keysChangedThreshold: 100);
+
+builder.AddProject()
+ .WithReference(cache);
+
+// After adding all resources, run the app...
+```
+
+The preceding code adds persistence to the Redis resource by taking snapshots of the Valkey data at a specified interval and threshold. The `interval` is time between snapshot exports and the `keysChangedThreshold` is the number of key change operations required to trigger a snapshot. For more information on persistence, see [Redis docs: Persistence](https://redis.io/topics/persistence).
diff --git a/docs/caching/stackexchange-redis-caching-overview.md b/docs/caching/stackexchange-redis-caching-overview.md
index 2bd29fd35..947681b25 100644
--- a/docs/caching/stackexchange-redis-caching-overview.md
+++ b/docs/caching/stackexchange-redis-caching-overview.md
@@ -1,10 +1,12 @@
---
title: Stack Exchange Redis caching overview
description: Learn about Stack Exchange Redis caching and how to use it in your applications.
-ms.date: 08/12/2024
+ms.date: 10/15/2024
---
-# Stack Exchange Redis caching overview
+# Stack Exchange Redis®**[*](#registered)** caching overview
+
+
With .NET Aspire, there are several ways to use caching in your applications. One popular option is to use [Stack Exchange Redis](https://stackexchange.github.io/StackExchange.Redis), which is a high-performance data store that can be used to store frequently accessed data. This article provides an overview of Stack Exchange Redis caching and links to resources that help you use it in your applications.
@@ -67,3 +69,5 @@ Output caching is a type of caching that stores the output of a web page or API
- [Distributed caching in .NET](/dotnet/core/extensions/caching#distributed-caching)
- [Distributed caching in ASP.NET Core](/aspnet/core/performance/caching/distributed)
- [Output caching middleware in ASP.NET Core](/aspnet/core/performance/caching/output)
+
+[!INCLUDE [redis-trademark](includes/redis-trademark.md)]
diff --git a/docs/caching/stackexchange-redis-distributed-caching-integration.md b/docs/caching/stackexchange-redis-distributed-caching-integration.md
index 0ad6499a7..5c980a474 100644
--- a/docs/caching/stackexchange-redis-distributed-caching-integration.md
+++ b/docs/caching/stackexchange-redis-distributed-caching-integration.md
@@ -1,18 +1,57 @@
---
-title: .NET Aspire Stack Exchange Redis distributed caching integration
-description: This article describes the .NET Aspire Stack Exchange Redis distributed caching integration features and capabilities
-ms.topic: how-to
-ms.date: 08/12/2024
+title: .NET Aspire Redis distributed caching integration
+description: Learn how to use the .NET Aspire Redis distributed caching integration, which includes both hosting and client integrations.
+ms.date: 10/15/2024
zone_pivot_groups: resp-host
---
-# .NET Aspire Stack Exchange Redis distributed caching integration
+# .NET Aspire Redis®**[*](#registered)** distributed caching integration
-In this article, you learn how to use the .NET Aspire Stack Exchange Redis distributed caching integration. The `Aspire.StackExchange.Redis.DistributedCaching` library is used to register an [IDistributedCache](https://stackexchange.github.io/StackExchange.Redis/Basics) provider for connecting to [Redis](https://redis.io/) server. It enables corresponding health checks, logging and telemetry.
+
-## Get started
+[!INCLUDE [includes-hosting-and-client](../includes/includes-hosting-and-client.md)]
-To get started with the .NET Aspire Stack Exchange Redis distributed caching integration, install the [Aspire.StackExchange.Redis.DistributedCaching](https://www.nuget.org/packages/Aspire.StackExchange.Redis.DistributedCaching) NuGet package in the client-consuming project, i.e., the project for the application that uses the Stack Exchange Redis distributed caching client.
+:::zone pivot="redis"
+
+Learn how to use the .NET Aspire Redis distributed caching integration. The `Aspire.StackExchange.Redis.DistributedCaching` library is used to register an [IDistributedCache](https://stackexchange.github.io/StackExchange.Redis/Basics) provider backed by a [Redis](https://redis.io/) server with the [`docker.io/library/redis` container image](https://hub.docker.com/_/redis/).
+
+:::zone-end
+:::zone pivot="garnet"
+
+Learn how to use the .NET Aspire Redis distributed caching integration. The `Aspire.StackExchange.Redis.DistributedCaching` library is used to register an [IDistributedCache](https://stackexchange.github.io/StackExchange.Redis/Basics) provider backed by a [Garnet](https://microsoft.github.io/garnet/) server with the [`ghcr.io/microsoft/garnet` container image](https://github.com/microsoft/garnet/pkgs/container/garnet).
+
+:::zone-end
+:::zone pivot="valkey"
+
+Learn how to use the .NET Aspire Redis distributed caching integration. The `Aspire.StackExchange.Redis.DistributedCaching` library is used to register an [IDistributedCache](https://stackexchange.github.io/StackExchange.Redis/Basics) provider backed by a [Valkey](https://valkey.io/) server with the [`docker.io/valkey/valkey` container image](https://hub.docker.com/r/valkey/valkey/).
+
+:::zone-end
+
+## Hosting integration
+
+:::zone pivot="redis"
+
+[!INCLUDE [redis-app-host](includes/redis-app-host.md)]
+
+:::zone-end
+:::zone pivot="garnet"
+
+[!INCLUDE [garnet-app-host](includes/garnet-app-host.md)]
+
+:::zone-end
+:::zone pivot="valkey"
+
+[!INCLUDE [valkey-app-host](includes/valkey-app-host.md)]
+
+:::zone-end
+
+### Hosting integration health checks
+
+[!INCLUDE [redis-hosting-health-checks](includes/redis-hosting-health-checks.md)]
+
+## Client integration
+
+To get started with the .NET Aspire Redis distributed caching integration, install the [📦 Aspire.StackExchange.Redis.DistributedCaching](https://www.nuget.org/packages/Aspire.StackExchange.Redis.DistributedCaching) NuGet package in the client-consuming project, i.e., the project for the application that uses the Redis distributed caching client.
### [.NET CLI](#tab/dotnet-cli)
@@ -24,21 +63,38 @@ dotnet add package Aspire.StackExchange.Redis.DistributedCaching
```xml
+ Version="*" />
```
---
-For more information, see [dotnet add package](/dotnet/core/tools/dotnet-add-package) or [Manage package dependencies in .NET applications](/dotnet/core/tools/dependencies).
-
-## Example usage
+### Add Redis client
In the _:::no-loc text="Program.cs":::_ file of your client-consuming project, call the extension to register the required services for distributed caching and add a for use via the dependency injection container.
```csharp
-builder.AddRedisDistributedCache("cache");
+builder.AddRedisDistributedCache(connectionName: "cache");
```
+:::zone pivot="redis"
+
+> [!TIP]
+> The `connectionName` parameter must match the name used when adding the Redis resource in the app host project. For more information, see [Add Redis resource](#add-redis-resource).
+
+:::zone-end
+:::zone pivot="garnet"
+
+> [!TIP]
+> The `connectionName` parameter must match the name used when adding the Garnet resource in the app host project. For more information, see [Add Garnet resource](#add-garnet-resource).
+
+:::zone-end
+:::zone pivot="valkey"
+
+> [!TIP]
+> The `connectionName` parameter must match the name used when adding the Valkey resource in the app host project. For more information, see [Add Valkey resource](#add-valkey-resource).
+
+:::zone-end
+
You can then retrieve the `IDistributedCache` instance using dependency injection. For example, to retrieve the cache from a service:
```csharp
@@ -48,34 +104,40 @@ public class ExampleService(IDistributedCache cache)
}
```
-## App host usage
+For more information on dependency injection, see [.NET dependency injection](/dotnet/core/extensions/dependency-injection).
-:::zone pivot="redis"
+### Add keyed Redis client
-[!INCLUDE [redis-app-host](includes/redis-app-host.md)]
+There might be situations where you want to register multiple `IDistributedCache` instances with different connection names. To register keyed Redis clients, call the method:
-:::zone-end
-:::zone pivot="garnet"
-
-[!INCLUDE [garnet-app-host](includes/garnet-app-host.md)]
+```csharp
+builder.AddKeyedRedisDistributedCache(name: "chat");
+builder.AddKeyedRedisDistributedCache(name: "product");
+```
-:::zone-end
-:::zone pivot="valkey"
+Then you can retrieve the `IDistributedCache` instances using dependency injection. For example, to retrieve the connection from an example service:
-[!INCLUDE [valkey-app-host](includes/valkey-app-host.md)]
+```csharp
+public class ExampleService(
+ [FromKeyedServices("chat")] IDistributedCache chatCache,
+ [FromKeyedServices("product")] IDistributedCache productCache)
+{
+ // Use caches...
+}
+```
-:::zone-end
+For more information on keyed services, see [.NET dependency injection: Keyed services](/dotnet/core/extensions/dependency-injection#keyed-services).
-## Configuration
+### Configuration
-The .NET Aspire Stack Exchange Redis distributed caching integration provides multiple options to configure the Redis connection based on the requirements and conventions of your project.
+The .NET Aspire Redis distributed caching integration provides multiple options to configure the Redis connection based on the requirements and conventions of your project.
-### Use a connection string
+#### Use a connection string
When using a connection string from the `ConnectionStrings` configuration section, you can provide the name of the connection string when calling `builder.AddRedisDistributedCache`:
```csharp
-builder.AddRedisDistributedCache("RedisConnection");
+builder.AddRedisDistributedCache("cache");
```
And then the connection string will be retrieved from the `ConnectionStrings` configuration section:
@@ -83,35 +145,18 @@ And then the connection string will be retrieved from the `ConnectionStrings` co
```json
{
"ConnectionStrings": {
- "RedisConnection": "localhost:6379"
+ "cache": "localhost:6379"
}
}
```
For more information on how to format this connection string, see the [Stack Exchange Redis configuration docs](https://stackexchange.github.io/StackExchange.Redis/Configuration.html#basic-configuration-strings).
-### Use configuration providers
+#### Use configuration providers
-The .NET Aspire Stack Exchange Redis distributed caching integration supports . It loads the from configuration by using the `Aspire:StackExchange:Redis` key. Example _:::no-loc text="appsettings.json":::_ that configures some of the options:
+[!INCLUDE [redis-client-json-settings](includes/redis-client-json-settings.md)]
-```json
-{
- "Aspire": {
- "StackExchange": {
- "Redis": {
- "ConfigurationOptions": {
- "ConnectTimeout": 3000,
- "ConnectRetry": 2
- },
- "DisableHealthChecks": true,
- "DisableTracing": false
- }
- }
- }
-}
-```
-
-### Use inline delegates
+#### Use inline delegates
You can also pass the `Action` delegate to set up some or all the options inline, for example to configure `DisableTracing`:
@@ -126,37 +171,39 @@ You can also set up the [ConfigurationOptions](https://stackexchange.github.io/S
```csharp
builder.AddRedisDistributedCache(
"cache",
- configureOptions: options => options.ConnectTimeout = 3000);
+ static settings => settings.ConnectTimeout = 3_000);
```
[!INCLUDE [integration-health-checks](../includes/integration-health-checks.md)]
-The .NET Aspire Stack Exchange Redis distributed caching integration handles the following:
+The .NET Aspire Redis distributed caching integration handles the following:
- Adds the `StackExchange.Redis` health check, tries to open the connection and throws when it fails.
- Integrates with the `/health` HTTP endpoint, which specifies all registered health checks must pass for app to be considered ready to accept traffic
[!INCLUDE [integration-observability-and-telemetry](../includes/integration-observability-and-telemetry.md)]
-### Logging
+#### Logging
-The .NET Aspire Stack Exchange Redis Distributed Caching integration uses the following Log categories:
+The .NET Aspire Redis Distributed Caching integration uses the following Log categories:
- `Aspire.StackExchange.Redis`
- `Microsoft.Extensions.Caching.StackExchangeRedis`
-### Tracing
+#### Tracing
-The .NET Aspire Stack Exchange Redis Distributed Caching integration will emit the following Tracing activities using OpenTelemetry:
+The .NET Aspire Redis Distributed Caching integration will emit the following Tracing activities using OpenTelemetry:
-- "OpenTelemetry.Instrumentation.StackExchangeRedis"
+- `OpenTelemetry.Instrumentation.StackExchangeRedis`
-### Metrics
+#### Metrics
-The .NET Aspire Stack Exchange Redis Distributed Caching integration currently doesn't support metrics by default due to limitations with the `StackExchange.Redis` library.
+The .NET Aspire Redis Distributed Caching integration currently doesn't support metrics by default due to limitations with the `StackExchange.Redis` library.
## See also
- [Stack Exchange Redis docs](https://stackexchange.github.io/StackExchange.Redis/)
- [.NET Aspire integrations](../fundamentals/integrations-overview.md)
- [.NET Aspire GitHub repo](https://github.com/dotnet/aspire)
+
+[!INCLUDE [redis-trademark](includes/redis-trademark.md)]
diff --git a/docs/caching/stackexchange-redis-integration.md b/docs/caching/stackexchange-redis-integration.md
index 6b6ef6e03..f198f9918 100644
--- a/docs/caching/stackexchange-redis-integration.md
+++ b/docs/caching/stackexchange-redis-integration.md
@@ -1,18 +1,57 @@
---
-title: .NET Aspire Stack Exchange Redis integration
-description: This article describes the .NET Aspire Stack Exchange Redis integration features and capabilities
-ms.topic: how-to
-ms.date: 08/12/2024
+title: .NET Aspire Redis integration
+description: Learn how to use the .NET Aspire Redis integration, which includes both hosting and client integrations.
+ms.date: 10/14/2024
zone_pivot_groups: resp-host
---
-# .NET Aspire Stack Exchange Redis integration
+# .NET Aspire Redis®**[*](#registered)** integration
-In this article, you learn how to use the .NET Aspire Stack Exchange Redis integration. The `Aspire.StackExchange.Redis` library is used to register an [IConnectionMultiplexer](https://stackexchange.github.io/StackExchange.Redis/Basics) in the DI container for connecting to a [Redis](https://redis.io/) server. It enables corresponding health checks, logging and telemetry.
+
-## Get started
+[!INCLUDE [includes-hosting-and-client](../includes/includes-hosting-and-client.md)]
-To get started with the .NET Aspire Stack Exchange Redis integration, install the [Aspire.StackExchange.Redis](https://www.nuget.org/packages/Aspire.StackExchange.Redis) NuGet package in the client-consuming project, i.e., the project for the application that uses the Stack Exchange Redis client.
+:::zone pivot="redis"
+
+[Redis](https://redis.io/) is the world's fastest data platform for caching, vector search, and NoSQL databases. The .NET Aspire Redis integration enables you to connect to existing Redis instances, or create new instances from .NET with the [`docker.io/library/redis` container image](https://hub.docker.com/_/redis/).
+
+:::zone-end
+:::zone pivot="garnet"
+
+[Garnet](https://microsoft.github.io/garnet/) is a a high-performance cache-store from Microsoft Research and complies with the [Redis serialization protocol](stackexchange-redis-caching-overview.md#redis-serialization-protocol-resp) (RESP). The .NET Aspire Redis integration enables you to connect to existing Garnet instances, or create new instances from .NET with the [`ghcr.io/microsoft/garnet` container image](https://github.com/microsoft/garnet/pkgs/container/garnet).
+
+:::zone-end
+:::zone pivot="valkey"
+
+[Valkey](https://valkey.io/) is a Redis fork and complies with the [Redis serialization protocol](stackexchange-redis-caching-overview.md#redis-serialization-protocol-resp) (RESP). It's a high-performance key/value datastore that supports a variety of workloads such as caching, message queues, and can act as a primary database. The .NET Aspire Redis integration enables you to connect to existing Valkey instances, or create new instances from .NET with the [`docker.io/valkey/valkey` container image](https://hub.docker.com/r/valkey/valkey/).
+
+:::zone-end
+
+## Hosting integration
+
+:::zone pivot="redis"
+
+[!INCLUDE [redis-app-host](includes/redis-app-host.md)]
+
+:::zone-end
+:::zone pivot="garnet"
+
+[!INCLUDE [garnet-app-host](includes/garnet-app-host.md)]
+
+:::zone-end
+:::zone pivot="valkey"
+
+[!INCLUDE [valkey-app-host](includes/valkey-app-host.md)]
+
+:::zone-end
+
+### Hosting integration health checks
+
+[!INCLUDE [redis-hosting-health-checks](includes/redis-hosting-health-checks.md)]
+
+## Client integration
+
+To get started with the .NET Aspire Stack Exchange Redis client integration, install the [📦 Aspire.StackExchange.Redis](https://www.nuget.org/packages/Aspire.StackExchange.Redis) NuGet package in the client-consuming project, that is, the project for the application that uses the Redis client. The Redis client integration registers an an [IConnectionMultiplexer](https://stackexchange.github.io/StackExchange.Redis/Basics) instance that you can use to interact with Redis.
### [.NET CLI](#tab/dotnet-cli)
@@ -24,57 +63,80 @@ dotnet add package Aspire.StackExchange.Redis
```xml
+ Version="*" />
```
---
-For more information, see [dotnet add package](/dotnet/core/tools/dotnet-add-package) or [Manage package dependencies in .NET applications](/dotnet/core/tools/dependencies).
-
-## Example usage
+### Add Redis client
-In the _:::no-loc text="Program.cs":::_ file of your client-consuming project, call the extension to register a `IConnectionMultiplexer` for use via the dependency injection container.
+In the _:::no-loc text="Program.cs":::_ file of your client-consuming project, call the extension method on any to register an `IConnectionMultiplexer` for use via the dependency injection container. The method takes a connection name parameter.
```csharp
-builder.AddRedisClient("cache");
+builder.AddRedisClient(connectionName: "cache");
```
-You can then retrieve the `IConnectionMultiplexer` instance using dependency injection. For example, to retrieve the connection multiplexer from a service:
+:::zone pivot="redis"
+
+> [!TIP]
+> The `connectionName` parameter must match the name used when adding the Redis resource in the app host project. For more information, see [Add Redis resource](#add-redis-resource).
+
+:::zone-end
+:::zone pivot="garnet"
+
+> [!TIP]
+> The `connectionName` parameter must match the name used when adding the Garnet resource in the app host project. For more information, see [Add Garnet resource](#add-garnet-resource).
+
+:::zone-end
+:::zone pivot="valkey"
+
+> [!TIP]
+> The `connectionName` parameter must match the name used when adding the Valkey resource in the app host project. For more information, see [Add Valkey resource](#add-valkey-resource).
+
+:::zone-end
+
+You can then retrieve the `IConnection` instance using dependency injection. For example, to retrieve the connection from an example service:
```csharp
-public class ExampleService(IConnectionMultiplexer connectionMultiplexer)
+public class ExampleService(IConnectionMultiplexer connectionMux)
{
// Use connection multiplexer...
}
```
-## App host usage
-
-:::zone pivot="redis"
+For more information on dependency injection, see [.NET dependency injection](/dotnet/core/extensions/dependency-injection).
-[!INCLUDE [redis-app-host](includes/redis-app-host.md)]
+### Add keyed Redis client
-:::zone-end
-:::zone pivot="garnet"
+There might be situations where you want to register multiple `IConnectionMultiplexer` instances with different connection names. To register keyed Redis clients, call the method:
-[!INCLUDE [garnet-app-host](includes/garnet-app-host.md)]
+```csharp
+builder.AddKeyedRedisClient(name: "chat");
+builder.AddKeyedRedisClient(name: "queue");
+```
-:::zone-end
-:::zone pivot="valkey"
+Then you can retrieve the `IConnectionMultiplexer` instances using dependency injection. For example, to retrieve the connection from an example service:
-[!INCLUDE [valkey-app-host](includes/valkey-app-host.md)]
+```csharp
+public class ExampleService(
+ [FromKeyedServices("chat")] IConnectionMultiplexer chatConnectionMux,
+ [FromKeyedServices("queue")] IConnectionMultiplexer queueConnectionMux)
+{
+ // Use connections...
+}
+```
-:::zone-end
+For more information on keyed services, see [.NET dependency injection: Keyed services](/dotnet/core/extensions/dependency-injection#keyed-services).
-## Configuration
+### Configuration
-The .NET Aspire Stack Exchange Redis integration provides multiple options to configure the Redis connection based on the requirements and conventions of your project.
+The .NET Aspire Stack Exchange Redis client integration provides multiple options to configure the Redis connection based on the requirements and conventions of your project.
-### Use a connection string
+#### Use a connection string
:::zone pivot="redis"
-When using a connection string from the `ConnectionStrings` configuration section, you can provide the name of the connection string when calling `builder.AddRedis`:
+When using a connection string from the `ConnectionStrings` configuration section, you can provide the name of the connection string when calling :
```csharp
builder.AddRedis("cache");
@@ -83,7 +145,7 @@ builder.AddRedis("cache");
:::zone-end
:::zone pivot="garnet"
-When using a connection string from the `ConnectionStrings` configuration section, you can provide the name of the connection string when calling `builder.AddGarnet`:
+When using a connection string from the `ConnectionStrings` configuration section, you can provide the name of the connection string when calling :
```csharp
builder.AddGarnet("cache");
@@ -92,9 +154,7 @@ builder.AddGarnet("cache");
:::zone-end
:::zone pivot="valkey"
-[!INCLUDE [valkey-app-host](includes/valkey-app-host.md)]
-
-When using a connection string from the `ConnectionStrings` configuration section, you can provide the name of the connection string when calling `builder.AddValkey`:
+When using a connection string from the `ConnectionStrings` configuration section, you can provide the name of the connection string when calling :
```csharp
builder.AddValkey("cache");
@@ -102,7 +162,7 @@ builder.AddValkey("cache");
:::zone-end
-And then the connection string will be retrieved from the `ConnectionStrings` configuration section:
+Then the connection string will be retrieved from the `ConnectionStrings` configuration section:
```json
{
@@ -114,83 +174,46 @@ And then the connection string will be retrieved from the `ConnectionStrings` co
For more information on how to format this connection string, see the [Stack Exchange Redis configuration docs](https://stackexchange.github.io/StackExchange.Redis/Configuration.html#basic-configuration-strings).
-### Use configuration providers
-
-The .NET Aspire Stack Exchange Redis integration supports . It loads the from configuration by using the `Aspire:StackExchange:Redis` key. Example _:::no-loc text="appsettings.json":::_ that configures some of the options:
+#### Use configuration providers
-```json
-{
- "Aspire": {
- "StackExchange": {
- "Redis": {
- "ConfigurationOptions": {
- "ConnectTimeout": 3000,
- "ConnectRetry": 2
- },
- "DisableHealthChecks": true,
- "DisableTracing": false
- }
- }
- }
-}
-```
+[!INCLUDE [redis-client-json-settings](includes/redis-client-json-settings.md)]
-### Use inline delegates
+#### Use inline delegates
You can also pass the `Action` delegate to set up some or all the options inline, for example to configure `DisableTracing`:
-:::zone pivot="redis"
-
```csharp
-builder.AddRedis(
+builder.AddRedisClient(
"cache",
- settings => settings.DisableTracing = true);
+ static settings => settings.DisableTracing = true);
```
-:::zone-end
-:::zone pivot="garnet"
-
-```csharp
-builder.AddGarnet(
- "cache",
- settings => settings.DisableTracing = true);
-```
+### Client integration health checks
-:::zone-end
-:::zone pivot="valkey"
-
-[!INCLUDE [valkey-app-host](includes/valkey-app-host.md)]
-
-```csharp
-builder.AddValkey(
- "cache",
- settings => settings.DisableTracing = true);
-```
-
-:::zone-end
-
-[!INCLUDE [integration-health-checks](../includes/integration-health-checks.md)]
+By default, .NET Aspire integrations enable [health checks](../fundamentals/health-checks.md) for all services. For more information, see [.NET Aspire integrations overview](../fundamentals/integrations-overview.md).
The .NET Aspire Stack Exchange Redis integration handles the following:
-- Adds the `StackExchange.Redis` health check, tries to open the connection and throws when it fails.
-- Integrates with the `/health` HTTP endpoint, which specifies all registered health checks must pass for app to be considered ready to accept traffic
+- Adds the health check when is `false`, which attempts to connect to the container instance.
+- Integrates with the `/health` HTTP endpoint, which specifies all registered health checks must pass for app to be considered ready to accept traffic.
-[!INCLUDE [integration-observability-and-telemetry](../includes/integration-observability-and-telemetry.md)]
+### Observability and telemetry
-### Logging
+.NET Aspire integrations automatically set up Logging, Tracing, and Metrics configurations, which are sometimes known as *the pillars of observability*. For more information about integration observability and telemetry, see [.NET Aspire integrations overview](../fundamentals/integrations-overview.md). Depending on the backing service, some integrations might only support some of these features. For example, some integrations support logging and tracing, but not metrics. Telemetry features can also be disabled using the techniques presented in the [Configuration](#configuration) section.
+
+#### Logging
The .NET Aspire Stack Exchange Redis integration uses the following log categories:
- `Aspire.StackExchange.Redis`
-### Tracing
+#### Tracing
The .NET Aspire Stack Exchange Redis integration will emit the following tracing activities using OpenTelemetry:
-- "OpenTelemetry.Instrumentation.StackExchangeRedis"
+- `OpenTelemetry.Instrumentation.StackExchangeRedis`
-### Metrics
+#### Metrics
The .NET Aspire Stack Exchange Redis integration currently doesn't support metrics by default due to limitations with the `StackExchange.Redis` library.
@@ -199,3 +222,5 @@ The .NET Aspire Stack Exchange Redis integration currently doesn't support metri
- [Stack Exchange Redis docs](https://stackexchange.github.io/StackExchange.Redis/)
- [.NET Aspire integrations](../fundamentals/integrations-overview.md)
- [.NET Aspire GitHub repo](https://github.com/dotnet/aspire)
+
+[!INCLUDE [redis-trademark](includes/redis-trademark.md)]
diff --git a/docs/caching/stackexchange-redis-output-caching-integration.md b/docs/caching/stackexchange-redis-output-caching-integration.md
index d3eb87a25..c294e2b2e 100644
--- a/docs/caching/stackexchange-redis-output-caching-integration.md
+++ b/docs/caching/stackexchange-redis-output-caching-integration.md
@@ -1,18 +1,57 @@
---
-title: .NET Aspire Stack Exchange Redis output caching Component
-description: This article describes the .NET Aspire Stack Exchange Redis output caching integration features and capabilities
-ms.topic: how-to
-ms.date: 08/12/2024
+title: .NET Aspire Redis output caching integration
+description: Learn how to use the .NET Aspire Redis output caching integration to register an ASP.NET Core Output Caching provider backed by a Redis server.
+ms.date: 10/15/2024
zone_pivot_groups: resp-host
---
-# .NET Aspire Stack Exchange Redis output caching integration
+# .NET Aspire Redis®**[*](#registered)** output caching integration
-In this article, you learn how to use the .NET Aspire Stack Exchange Redis output caching integration. The `Aspire.StackExchange.Redis.OutputCaching` library is used to register an [ASP.NET Core Output Caching](/aspnet/core/performance/caching/output) provider backed by a [Redis](https://redis.io/) server. It enables corresponding health check, logging, and telemetry..
+
-## Get started
+[!INCLUDE [includes-hosting-and-client](../includes/includes-hosting-and-client.md)]
-To get started with the .NET Aspire Stack Exchange Redis output caching integration, install the [Aspire.StackExchange.Redis.OutputCaching](https://www.nuget.org/packages/Aspire.StackExchange.Redis.OutputCaching) NuGet package in the client-consuming project, i.e., the project for the application that uses the Stack Exchange Redis output caching client.
+:::zone pivot="redis"
+
+Learn how to use the .NET Aspire Redis output caching integration. The `Aspire.StackExchange.Redis.OutputCaching` client integration is used to register an [ASP.NET Core Output Caching](/aspnet/core/performance/caching/output) provider backed by a [Redis](https://redis.io/) server with the [`docker.io/library/redis` container image](https://hub.docker.com/_/redis/).
+
+:::zone-end
+:::zone pivot="garnet"
+
+Learn how to use the .NET Aspire Redis output caching integration. The `Aspire.StackExchange.Redis.OutputCaching` client integration is used to register an [ASP.NET Core Output Caching](/aspnet/core/performance/caching/output) provider backed by a [Garnet](https://microsoft.github.io/garnet/) server with the [`ghcr.io/microsoft/garnet` container image](https://github.com/microsoft/garnet/pkgs/container/garnet).
+
+:::zone-end
+:::zone pivot="valkey"
+
+Learn how to use the .NET Aspire Redis output caching integration. The `Aspire.StackExchange.Redis.OutputCaching` client integration is used to register an [ASP.NET Core Output Caching](/aspnet/core/performance/caching/output) provider backed by a [Valkey](https://valkey.io/) server with the [`docker.io/valkey/valkey` container image](https://hub.docker.com/r/valkey/valkey/).
+
+:::zone-end
+
+## Hosting integration
+
+:::zone pivot="redis"
+
+[!INCLUDE [redis-app-host](includes/redis-app-host.md)]
+
+:::zone-end
+:::zone pivot="garnet"
+
+[!INCLUDE [garnet-app-host](includes/garnet-app-host.md)]
+
+:::zone-end
+:::zone pivot="valkey"
+
+[!INCLUDE [valkey-app-host](includes/valkey-app-host.md)]
+
+:::zone-end
+
+### Hosting integration health checks
+
+[!INCLUDE [redis-hosting-health-checks](includes/redis-hosting-health-checks.md)]
+
+## Client integration
+
+To get started with the .NET Aspire Stack Exchange Redis output caching client integration, install the [📦 Aspire.StackExchange.Redis.OutputCaching](https://www.nuget.org/packages/Aspire.StackExchange.Redis.OutputCaching) NuGet package in the client-consuming project, that is, the project for the application that uses the output caching client.
### [.NET CLI](#tab/dotnet-cli)
@@ -24,101 +63,88 @@ dotnet add package Aspire.StackExchange.Redis.OutputCaching
```xml
+ Version="*" />
```
---
-For more information, see [dotnet add package](/dotnet/core/tools/dotnet-add-package) or [Manage package dependencies in .NET applications](/dotnet/core/tools/dependencies).
-
-## Example usage
+### Add output caching
-In the _:::no-loc text="Program.cs":::_ file of your client-consuming project, call the extension to register the required services for output caching.
+In the _:::no-loc text="Program.cs":::_ file of your client-consuming project, call the extension method on any to register the required services for output caching.
```csharp
-builder.AddRedisOutputCache("cache");
+builder.AddRedisOutputCache(connectionName: "cache");
```
-Add the middleware to the request processing pipeline by calling [UseOutputCache](/dotnet/api/microsoft.aspnetcore.builder.outputcacheapplicationbuilderextensions.useoutputcache).
-
-```csharp
-var app = builder.Build();
-app.UseOutputCache();
-```
-
-For minimal API apps, configure an endpoint to do caching by calling , or by applying the , as shown in the following examples:
-
-```csharp
-app.MapGet("/cached", () => { return "Hello world!"; }).CacheOutput();
-app.MapGet("/attribute", [OutputCache] () => { return "Hello world!"; });
-```
-
-For apps with controllers, apply the `[OutputCache]` attribute to the action method. For Razor Pages apps, apply the attribute to the Razor page class.
-
-## App host usage
-
:::zone pivot="redis"
-[!INCLUDE [redis-app-host](includes/redis-app-host.md)]
+> [!TIP]
+> The `connectionName` parameter must match the name used when adding the Redis resource in the app host project. For more information, see [Add Redis resource](#add-redis-resource).
:::zone-end
:::zone pivot="garnet"
-[!INCLUDE [garnet-app-host](includes/garnet-app-host.md)]
+> [!TIP]
+> The `connectionName` parameter must match the name used when adding the Garnet resource in the app host project. For more information, see [Add Garnet resource](#add-garnet-resource).
:::zone-end
:::zone pivot="valkey"
-[!INCLUDE [valkey-app-host](includes/valkey-app-host.md)]
+> [!TIP]
+> The `connectionName` parameter must match the name used when adding the Valkey resource in the app host project. For more information, see [Add Valkey resource](#add-valkey-resource).
:::zone-end
-## Configuration
+Add the middleware to the request processing pipeline by calling :
+
+```csharp
+var app = builder.Build();
+
+app.UseOutputCache();
+```
+
+For [minimal API apps](/aspnet/core/fundamentals/minimal-apis/overview), configure an endpoint to do caching by calling , or by applying the , as shown in the following examples:
+
+```csharp
+app.MapGet("/cached", () => "Hello world!")
+ .CacheOutput();
+
+app.MapGet(
+ "/attribute",
+ [OutputCache] () => "Hello world!");
+```
+
+For apps with controllers, apply the `[OutputCache]` attribute to the action method. For Razor Pages apps, apply the attribute to the Razor page class.
+
+### Configuration
The .NET Aspire Stack Exchange Redis output caching integration provides multiple options to configure the Redis connection based on the requirements and conventions of your project.
-### Use a connection string
+#### Use a connection string
-When using a connection string from the `ConnectionStrings` configuration section, you can provide the name of the connection string when calling `builder.AddRedisOutputCache`:
+When using a connection string from the `ConnectionStrings` configuration section, you can provide the name of the connection string when calling :
```csharp
-builder.AddRedisOutputCache("RedisConnection");
+builder.AddRedisOutputCache(connectionName: "cache");
```
-And then the connection string will be retrieved from the `ConnectionStrings` configuration section:
+Then the connection string will be retrieved from the `ConnectionStrings` configuration section:
```json
{
"ConnectionStrings": {
- "RedisConnection": "localhost:6379"
+ "cache": "localhost:6379"
}
}
```
For more information on how to format this connection string, see the [Stack Exchange Redis configuration docs](https://stackexchange.github.io/StackExchange.Redis/Configuration.html#basic-configuration-strings).
-### Use configuration providers
-
-The .NET Aspire Stack Exchange Redis output caching integration supports . It loads the from configuration by using the `Aspire:StackExchange:Redis` key. Example _:::no-loc text="appsettings.json":::_ that configures some of the options:
+#### Use configuration providers
-```json
-{
- "Aspire": {
- "StackExchange": {
- "Redis": {
- "ConfigurationOptions": {
- "ConnectTimeout": 3000,
- "ConnectRetry": 2
- },
- "DisableHealthChecks": true,
- "DisableTracing": false
- }
- }
- }
-}
-```
+[!INCLUDE [redis-client-json-settings](includes/redis-client-json-settings.md)]
-### Use inline delegates
+#### Use inline delegates
You can also pass the `Action configurationSettings` delegate to set up some or all the options inline, for example to disable health checks from code:
@@ -133,7 +159,7 @@ You can also set up the [ConfigurationOptions](https://stackexchange.github.io/S
```csharp
builder.AddRedisOutputCache(
"cache",
- static configureOptions: options => options.ConnectTimeout = 3000);
+ static settings => settings.ConnectTimeout = 3_000);
```
[!INCLUDE [integration-health-checks](../includes/integration-health-checks.md)]
@@ -145,20 +171,20 @@ The .NET Aspire Stack Exchange Redis output caching integration handles the foll
[!INCLUDE [integration-observability-and-telemetry](../includes/integration-observability-and-telemetry.md)]
-### Logging
+#### Logging
The .NET Aspire Stack Exchange Redis output caching integration uses the following Log categories:
- `Aspire.StackExchange.Redis`
- `Microsoft.AspNetCore.OutputCaching.StackExchangeRedis`
-### Tracing
+#### Tracing
The .NET Aspire Stack Exchange Redis output caching integration will emit the following Tracing activities using OpenTelemetry:
-- "OpenTelemetry.Instrumentation.StackExchangeRedis"
+- `OpenTelemetry.Instrumentation.StackExchangeRedis`
-### Metrics
+#### Metrics
The .NET Aspire Stack Exchange Redis output caching integration currently doesn't support metrics by default due to limitations with the `StackExchange.Redis` library.
@@ -167,3 +193,5 @@ The .NET Aspire Stack Exchange Redis output caching integration currently doesn'
- [Stack Exchange Redis docs](https://stackexchange.github.io/StackExchange.Redis/)
- [.NET Aspire integrations](../fundamentals/integrations-overview.md)
- [.NET Aspire GitHub repo](https://github.com/dotnet/aspire)
+
+[!INCLUDE [redis-trademark](includes/redis-trademark.md)]
diff --git a/docs/community-toolkit/hosting-azure-static-web-apps.md b/docs/community-toolkit/hosting-azure-static-web-apps.md
new file mode 100644
index 000000000..d8b43beee
--- /dev/null
+++ b/docs/community-toolkit/hosting-azure-static-web-apps.md
@@ -0,0 +1,70 @@
+---
+title: Azure Static Web Apps emulator
+description: Learn how to use the .NET Aspire Azure Static Web Apps emulator integration to run Azure Static Web Apps locally using the emulator.
+ms.date: 10/11/2024
+---
+
+# .NET Aspire Azure Static Web Apps emulator integration
+
+[!INCLUDE [includes-hosting](../includes/includes-hosting.md)]
+
+[!INCLUDE [banner](includes/banner.md)]
+
+In this article, you learn how to use the .NET Aspire [Azure Static Web Apps emulator](/azure/static-web-apps/local-development) hosting integration to run Azure Static Web Apps locally using the emulator. The emulator provides support for proxying both the static frontend and the API backend using resources defined in the app host.
+
+This integration requires the [Azure Static Web Apps CLI](/azure/static-web-apps/local-development#get-started) to run, and only supports hosting the emulator for local development, not deploying to Azure Static Web Apps.
+
+## Hosting integration
+
+To get started with the .NET Aspire Azure Static Web Apps emulator hosting integration, install the [📦 Aspire.CommunityToolkit.Hosting.Azure.StaticWebApps](https://dev.azure.com/dotnet/CommunityToolkit/_artifacts/feed/CommunityToolkit-MainLatest/NuGet/Aspire.CommunityToolkit.Hosting.Azure.StaticWebApps) NuGet package in the AppHost project.
+
+### [.NET CLI](#tab/dotnet-cli)
+
+```dotnetcli
+dotnet add package Aspire.CommunityToolkit.Hosting.Azure.StaticWebApps
+```
+
+### [PackageReference](#tab/package-reference)
+
+```xml
+
+```
+
+---
+
+For more information, see [dotnet add package](/dotnet/core/tools/dotnet-add-package) or [Manage package dependencies in .NET applications](/dotnet/core/tools/dependencies).
+
+## Example usage
+
+In the _:::no-loc text="Program.cs":::_ file of your app host project, define the backend and frontend resources. Then, call the `AddSwaEmulator` method to create the emulator and pass the resources using the `WithAppResource` and `WithApiResource` methods.
+
+```csharp
+var builder = DistributedApplication.CreateBuilder(args);
+
+// Define the API resource
+var api = builder.AddProject("api");
+
+// Define the frontend resource
+var web = builder
+ .AddNpmApp("web", Path.Combine("..", "Aspire.CommunityToolkit.StaticWebApps.WebApp"), "dev")
+ .WithHttpEndpoint(env: "PORT")
+ .WithExternalHttpEndpoints();
+
+// Create a SWA emulator with the frontend and API resources
+_ = builder
+ .AddSwaEmulator("swa")
+ .WithAppResource(web)
+ .WithApiResource(api);
+
+builder.Build().Run();
+```
+
+The preceding code defines the API and frontend resources and creates an emulator with the resources. The emulator is then started using the `Run` method.
+
+## See also
+
+- [Azure Static Web Apps emulator](/azure/static-web-apps/local-development)
+- [Azure Static Web Apps](/azure/static-web-apps/)
+- [.NET Aspire Community Toolkit GitHub repo](https://github.com/CommunityToolkit/Aspire)
+- [Sample app source code](https://github.com/CommunityToolkit/Aspire/tree/main/examples/swa)
diff --git a/docs/community-toolkit/hosting-golang.md b/docs/community-toolkit/hosting-golang.md
new file mode 100644
index 000000000..193dd135a
--- /dev/null
+++ b/docs/community-toolkit/hosting-golang.md
@@ -0,0 +1,50 @@
+---
+title: Go hosting
+author: tommasodotNET
+description: Learn how to use the .NET Aspire Go hosting integration to host Go applications.
+ms.date: 10/11/2024
+---
+
+# .NET Aspire Go hosting
+
+[!INCLUDE [includes-hosting](../includes/includes-hosting.md)]
+
+[!INCLUDE [banner](includes/banner.md)]
+
+In this article, you learn how to use the .NET Aspire Go hosting integration to host Go applications.
+
+## Hosting integration
+
+To get started with the .NET Aspire Go hosting integration, install the [📦 Aspire.CommunityToolkit.Hosting.Go](https://dev.azure.com/dotnet/CommunityToolkit/_artifacts/feed/CommunityToolkit-MainLatest/NuGet/Aspire.CommunityToolkit.Hosting.Golang) NuGet package in the AppHost project.
+
+### [.NET CLI](#tab/dotnet-cli)
+
+```dotnetcli
+dotnet add package Aspire.CommunityToolkit.Hosting.Golang
+```
+
+### [PackageReference](#tab/package-reference)
+
+```xml
+
+```
+
+---
+
+For more information, see [dotnet add package](/dotnet/core/tools/dotnet-add-package) or [Manage package dependencies in .NET applications](/dotnet/core/tools/dependencies).
+
+## Example usage
+
+In the _:::no-loc text="Program.cs":::_ file of your app host project, call the `AddGolangApp` method to add a Go application to the builder.
+
+```csharp
+var golang = builder.AddGolangApp("golang", "../go-service");
+```
+
+The Go application can be added as a reference to other resources in the AppHost project.
+
+## See also
+
+- [.NET Aspire Community Toolkit GitHub repo](https://github.com/CommunityToolkit/Aspire)
+- [Sample Go app](https://github.com/CommunityToolkit/Aspire/tree/main/examples/golang)
diff --git a/docs/community-toolkit/hosting-java.md b/docs/community-toolkit/hosting-java.md
new file mode 100644
index 000000000..44b0edd29
--- /dev/null
+++ b/docs/community-toolkit/hosting-java.md
@@ -0,0 +1,99 @@
+---
+title: Java/Spring hosting
+author: justinyoo
+description: A .NET Aspire hosting integration for hosting Java/Spring applications using either the Java runtime or a container.
+ms.date: 10/11/2024
+---
+
+# .NET Aspire Java/Spring hosting integration
+
+[!INCLUDE [includes-hosting](../includes/includes-hosting.md)]
+
+[!INCLUDE [banner](includes/banner.md)]
+
+In this article, you learn how to use the .NET Aspire Java/Spring hosting integration to host Java/Spring applications using either the Java runtime or a container.
+
+## Prerequisites
+
+This integration requires the [OpenTelemetry Agent for Java](https://opentelemetry.io/docs/zero-code/java/agent/) to be downloaded and placed in the `agents` directory in the root of the project. Depending on your preferred shell, use either of the following commands to download the agent:
+
+# [Bash](#tab/bash)
+
+```bash
+# bash/zsh
+mkdir -p ./agents
+wget -P ./agents \
+ https://github.com/open-telemetry/opentelemetry-java-instrumentation/releases/latest/download/opentelemetry-javaagent.jar
+```
+
+# [PowerShell](#tab/powershell)
+
+```powershell
+# PowerShell
+New-item -type Directory -Path ./agents -Force
+Invoke-WebRequest `
+ -OutFile "./agents/opentelemetry-javaagent.jar" `
+ -Uri "https://github.com/open-telemetry/opentelemetry-java-instrumentation/releases/latest/download/opentelemetry-javaagent.jar"
+```
+
+---
+
+## Get started
+
+To get started with the .NET Aspire Azure Static Web Apps emulator integration, install the [📦 Aspire.CommunityToolkit.Hosting.Java](https://dev.azure.com/dotnet/CommunityToolkit/_artifacts/feed/CommunityToolkit-MainLatest/NuGet/Aspire.CommunityToolkit.Hosting.Java) NuGet package in the AppHost project.
+
+### [.NET CLI](#tab/dotnet-cli)
+
+```dotnetcli
+dotnet add package Aspire.CommunityToolkit.Hosting.Java
+```
+
+### [PackageReference](#tab/package-reference)
+
+```xml
+
+```
+
+---
+
+For more information, see [dotnet add package](/dotnet/core/tools/dotnet-add-package) or [Manage package dependencies in .NET applications](/dotnet/core/tools/dependencies).
+
+## Example Usage
+
+The following sections detail various example usage scenarios, from hosting a containerized Spring app to hosting an executable Spring app.
+
+### [Container hosting](#tab/container-hosting)
+
+In the _:::no-loc text="Program.cs":::_file of your app host project, call the `AddSpringApp` method to define the containerized Spring app. Use the `JavaAppContainerResourceOptions` to define the containerized Spring app.
+
+```csharp
+var containerapp = builder.AddSpringApp(
+ "containerapp",
+ new JavaAppContainerResourceOptions
+ {
+ ContainerImageName = "/",
+ OtelAgentPath = ""
+ });
+```
+
+### [Executable hosting](#tab/executable-hosting)
+
+In the _:::no-loc text="Program.cs":::_ file of your AppHost project, call the `AddSpringApp` method to define the executable Spring app. Use the `JavaAppExecutableResourceOptions` to define the executable Spring app.
+
+```csharp
+var executableapp = builder.AddSpringApp(
+ "executableapp",
+ new JavaAppExecutableResourceOptions
+ {
+ ApplicationName = "target/app.jar",
+ OtelAgentPath = "../../../agents"
+ });
+```
+
+---
+
+## See also
+
+- [Java developer resources](/java)
+- [.NET Aspire Community Toolkit GitHub repo](https://github.com/CommunityToolkit/Aspire)
diff --git a/docs/community-toolkit/hosting-nodejs-extensions.md b/docs/community-toolkit/hosting-nodejs-extensions.md
new file mode 100644
index 000000000..45287d17f
--- /dev/null
+++ b/docs/community-toolkit/hosting-nodejs-extensions.md
@@ -0,0 +1,95 @@
+---
+title: Node.js hosting extensions
+description: Learn about the .NET Aspire Community Toolkit Node.js hosting extensions package which provides extra functionality to the .NET Aspire NodeJS hosting package.
+ms.date: 10/11/2024
+---
+
+# .NET Aspire Community Toolkit Node.js hosting extensions
+
+[!INCLUDE [includes-hosting](../includes/includes-hosting.md)]
+
+[!INCLUDE [banner](includes/banner.md)]
+
+In this article, you learn about the .NET Aspire Community Toolkit Node.js hosting extensions package which provides extra functionality to the .NET Aspire [NodeJS hosting package](https://nuget.org/packages/Aspire.Hosting.NodeJS). The extensions package brings the following features:
+
+- Running [Vite](https://vitejs.dev/) applications
+- Running Node.js applications using [Yarn](https://yarnpkg.com/) and [pnpm](https://pnpm.io/)
+- Ensuring that the packages are installed before running the application (using the specified package manager)
+
+## Hosting integration
+
+To get started with the .NET Aspire Community Toolkit Node.js hosting extensions, install the [📦 Aspire.CommunityToolkit.Hosting.NodeJS.Extensions](https://dev.azure.com/dotnet/CommunityToolkit/_artifacts/feed/CommunityToolkit-MainLatest/NuGet/Aspire.CommunityToolkit.Hosting.NodeJS.Extensions) NuGet package in the AppHost project.
+
+### [.NET CLI](#tab/dotnet-cli)
+
+```dotnetcli
+dotnet add package Aspire.CommunityToolkit.Hosting.NodeJS.Extensions
+```
+
+### [PackageReference](#tab/package-reference)
+
+```xml
+
+```
+
+---
+
+For more information, see [dotnet add package](/dotnet/core/tools/dotnet-add-package) or [Manage package dependencies in .NET applications](/dotnet/core/tools/dependencies).
+
+## Example usage
+
+The following sections detail various usages, from running Vite applications to using specific package managers.
+
+### Run specific package managers
+
+This integration extension adds support for running Node.js applications using Yarn or pnpm as the package manager.
+
+# [yarn](#tab/yarn)
+
+```csharp
+var builder = DistributedApplication.CreateBuilder(args);
+
+builder.AddYarnApp("yarn-demo")
+ .WithExternalHttpEndpoints();
+```
+
+# [pnpm](#tab/pnpm)
+
+```csharp
+var builder = DistributedApplication.CreateBuilder(args);
+
+builder.AddPnpmApp("pnpm-demo")
+ .WithExternalHttpEndpoints();
+```
+
+---
+
+### Run Vite apps
+
+This integration extension adds support for running the development server for Vite applications. By default, it uses the `npm` package manager to launch, but this can be overridden with the `packageManager` argument.
+
+```csharp
+var builder = DistributedApplication.CreateBuilder(args);
+
+builder.AddViteApp("vite-demo")
+ .WithExternalHttpEndpoints();
+
+builder.AddViteApp("yarn-demo", packageManager: "yarn")
+ .WithExternalHttpEndpoints();
+
+builder.AddViteApp("pnpm-demo", packageManager: "pnpm")
+ .WithExternalHttpEndpoints();
+
+builder.Build().Run();
+```
+
+### Install packages
+
+When using the `WithNpmPackageInstallation`, `WithYarnPackageInstallation` or `WithPnpmPackageInstallation` methods, the package manager is used to install the packages before starting the application. These methods are useful to ensure that packages are installed before the application starts, similar to how a .NET application would restore NuGet packages before running.
+
+## See also
+
+- [Orchestrate Node.js apps in .NET Aspire](../get-started/build-aspire-apps-with-nodejs.md)
+- [.NET Aspire Community Toolkit GitHub repo](https://github.com/CommunityToolkit/Aspire)
+- [Sample Node.js apps](https://github.com/CommunityToolkit/Aspire/tree/main/examples/nodejs-ext)
diff --git a/docs/community-toolkit/includes/banner.md b/docs/community-toolkit/includes/banner.md
new file mode 100644
index 000000000..e165da6be
--- /dev/null
+++ b/docs/community-toolkit/includes/banner.md
@@ -0,0 +1,6 @@
+---
+ms.topic: include
+---
+
+> [!NOTE]
+> This integration is part of the [.NET Aspire Community Toolkit](https://github.com/CommunityToolkit/Aspire) and _isn't_ officially supported by the .NET Aspire team.
diff --git a/docs/community-toolkit/ollama.md b/docs/community-toolkit/ollama.md
new file mode 100644
index 000000000..d92e1e6a9
--- /dev/null
+++ b/docs/community-toolkit/ollama.md
@@ -0,0 +1,122 @@
+---
+title: Ollama
+description: Learn how to use the .NET Aspire Ollama hosting and client integration to host Ollama models using the Ollama container and accessing it via the OllamaSharp client.
+ms.date: 10/11/2024
+---
+
+# .NET Aspire Community Toolkit Ollama integration
+
+[!INCLUDE [includes-hosting-and-client](../includes/includes-hosting-and-client.md)]
+
+[!INCLUDE [banner](includes/banner.md)]
+
+In this article, you learn how to use the .NET Aspire Ollama hosting integration to host [Ollama](https://ollama.com) models using the Ollama container and accessing it via the [OllamaSharp](https://www.nuget.org/packages/OllamaSharp) client.
+
+## Hosting integration
+
+To model the Ollama server, install the [📦 Aspire.CommunityToolkit.Hosting.Ollama](https://dev.azure.com/dotnet/CommunityToolkit/_artifacts/feed/CommunityToolkit-MainLatest/NuGet/Aspire.CommunityToolkit.Hosting.Ollama) NuGet package in the [app host](xref:aspire/app-host) project.
+
+### [.NET CLI](#tab/dotnet-cli)
+
+```dotnetcli
+dotnet add package Aspire.CommunityToolkit.Hosting.Ollama
+```
+
+### [PackageReference](#tab/package-reference)
+
+```xml
+
+```
+
+---
+
+For more information, see [dotnet add package](/dotnet/core/tools/dotnet-add-package) or [Manage package dependencies in .NET applications](/dotnet/core/tools/dependencies).
+
+### Add Ollama resource
+
+In the app host project, register and consume the Ollama integration using the `AddOllama` extension method to add the Ollama container to the application builder. You can then add models to the container, which downloads and run when the container starts, using the `AddModel` extension method.
+
+```csharp
+var ollama = builder.AddOllama("ollama")
+ .AddModel("llama3");
+```
+
+When .NET Aspire adds a container image to the app host, as shown in the preceding example with the `docker.io/ollama/ollama` image, it creates a new Ollama instance on your local machine. For more information, see [Container resource lifecycle](../fundamentals/app-host-overview.md#container-resource-lifecycle).
+
+### Download the LLM
+
+When the Ollama container for this integration first spins up, it downloads one or more configured LLMs. The progress of this download displays in the **State** column for this integration on the Aspire orchestration app.
+
+> [!IMPORTANT]
+> Keep the .NET Aspire orchestration app open until the download is complete, otherwise the download will be cancelled.
+
+### Cache the LLM
+
+One or more LLMs are downloaded into the container which Ollama is running from, and by default this container is ephemeral. If you need to persist one or more LLMs across container restarts, you need to mount a volume into the container using the `WithDataVolume` method.
+
+```csharp
+var ollama = builder.AddOllama("ollama")
+ .AddModel("llama3")
+ .WithDataVolume();
+```
+
+### Open WebUI support
+
+The Ollama integration also provided support for running [Open WebUI](https://openwebui.com/) and having it communicate with the Ollama container.
+
+```csharp
+var ollama = builder.AddOllama("ollama")
+ .AddModel("llama3")
+ .WithOpenWebUI();
+```
+
+## Client integration
+
+To get started with the .NET Aspire OllamaSharp integration, install the [Aspire.CommunityToolkit.OllamaSharp](https://dev.azure.com/dotnet/CommunityToolkit/_artifacts/feed/CommunityToolkit-MainLatest/NuGet/Aspire.CommunityToolkit.OllamaSharp) NuGet package in the client-consuming project, that is, the project for the application that uses the Ollama client.
+
+### [.NET CLI](#tab/dotnet-cli)
+
+```dotnetcli
+dotnet add package Aspire.CommunityToolkit.OllamaSharp
+```
+
+### [PackageReference](#tab/package-reference)
+
+```xml
+
+```
+
+---
+
+### Add Ollama client API
+
+In the _:::no-loc text="Program.cs":::_ file of your client-consuming project, call the `AddOllamaClientApi` extension to register an `IOllamaClientApi` for use via the dependency injection container.
+
+```csharp
+builder.AddOllamaClientApi("ollama");
+```
+
+After adding `IOllamaClientApi` to the builder, you can get the `IOllamaClientApi` instance using dependency injection. For example, to retrieve your context object from service:
+
+```csharp
+public class ExampleService(IOllamaClientApi ollama)
+{
+ // Use ollama...
+}
+```
+
+### Access the Ollama server in other services
+
+The Ollama hosting integration exposes the endpoint of the Ollama server as a connection string that can be accessed from other services in the application.
+
+```csharp
+var connectionString = builder.Configuration.GetConnectionString("ollama");
+```
+
+## See also
+
+- [Ollama](https://ollama.com)
+- [Open WebUI](https://openwebui.com)
+- [.NET Aspire Community Toolkit GitHub repo](https://github.com/CommunityToolkit/Aspire)
diff --git a/docs/community-toolkit/overview.md b/docs/community-toolkit/overview.md
new file mode 100644
index 000000000..0be9d8c9a
--- /dev/null
+++ b/docs/community-toolkit/overview.md
@@ -0,0 +1,37 @@
+---
+title: Overview
+description: An overview of the .NET Aspire Community Toolkit project.
+ms.date: 10/11/2024
+---
+
+# .NET Aspire Community Toolkit
+
+The .NET Aspire Community Toolkit is a collection of integrations and extensions for .NET Aspire created by the community. These integrations aren't officially supported by the .NET Aspire team, and are provided as-is for the community to use and contribute to. The source code for the toolkit is available on [GitHub][github-repo].
+
+## Frequently Asked Questions
+
+The following section answers some frequently asked questions about the .NET Aspire Community Toolkit.
+
+### What is the purpose of this project?
+
+The goal of the project is to be a centralized home for extensions and integrations for [.NET Aspire](/dotnet/aspire), helping to provide consistency in the way that integrations are built and maintained, as well as easier discoverability for users.
+
+### How is this project different from the official .NET Aspire project?
+
+The .NET Aspire Community Toolkit is a community-driven project that's maintained by the community and isn't officially supported by the .NET Aspire team. The toolkit is a collection of integrations and extensions that are built on top of the .NET Aspire project.
+
+### How can I contribute to the project?
+
+Anyone can contribute to the .NET Aspire Community Toolkit and before you get started, be sure to read the [Contributing Guide](https://github.com/CommunityToolkit/Aspire/blob/main/CONTRIBUTING.md) to learn how to contribute to the project.
+
+### Should I propose a new integration on the Community Toolkit or the `dotnet/aspire` repo?
+
+If you have an idea for a new integration, you should propose it on the [.NET Aspire Community Toolkit repository][github-repo], rather than [`dotnet/aspire`](https://github.com/dotnet/aspire), as the official .NET Aspire project is focused on the core functionality of the .NET Aspire project.
+
+If you've proposed an integration on the `dotnet/aspire` repository, you can still propose it in the Community Toolkit, but link to the existing issue on the `dotnet/aspire` repository to provide context.
+
+### Finding Community Toolkit Integrations
+
+Integrations from the .NET Aspire Community Toolkit appear in the **Add Aspire Integration** dialog in Visual Studio under the namespace `Aspire.CommunityToolkit.*`.
+
+[github-repo]: https://github.com/CommunityToolkit/Aspire
diff --git a/docs/database/azure-cosmos-db-entity-framework-integration.md b/docs/database/azure-cosmos-db-entity-framework-integration.md
index 3840f191e..46a3f6285 100644
--- a/docs/database/azure-cosmos-db-entity-framework-integration.md
+++ b/docs/database/azure-cosmos-db-entity-framework-integration.md
@@ -23,7 +23,7 @@ dotnet add package Aspire.Microsoft.EntityFrameworkCore.Cosmos
```xml
+ Version="*" />
```
---
@@ -63,7 +63,7 @@ dotnet add package Aspire.Hosting.Azure.CosmosDB
```xml
+ Version="*" />
```
---
diff --git a/docs/database/azure-cosmos-db-integration.md b/docs/database/azure-cosmos-db-integration.md
index eb5b70681..0a1b38007 100644
--- a/docs/database/azure-cosmos-db-integration.md
+++ b/docs/database/azure-cosmos-db-integration.md
@@ -23,7 +23,7 @@ dotnet add package Aspire.Microsoft.Azure.Cosmos
```xml
+ Version="*" />
```
---
@@ -63,7 +63,7 @@ dotnet add package Aspire.Hosting.Azure.CosmosDB
```xml
+ Version="*" />
```
---
diff --git a/docs/database/includes/mysql-app-host.md b/docs/database/includes/mysql-app-host.md
index b0044ab70..0f431ea25 100644
--- a/docs/database/includes/mysql-app-host.md
+++ b/docs/database/includes/mysql-app-host.md
@@ -10,7 +10,7 @@ dotnet add package Aspire.Hosting.MySql
```xml
+ Version="*" />
```
---
diff --git a/docs/database/includes/postgresql-app-host.md b/docs/database/includes/postgresql-app-host.md
index 54af00e11..4e59831f4 100644
--- a/docs/database/includes/postgresql-app-host.md
+++ b/docs/database/includes/postgresql-app-host.md
@@ -10,7 +10,7 @@ dotnet add package Aspire.Hosting.PostgreSQL
```xml
+ Version="*" />
```
---
diff --git a/docs/database/includes/postgresql-flexible-server.md b/docs/database/includes/postgresql-flexible-server.md
index 19c6530eb..01ecb31b2 100644
--- a/docs/database/includes/postgresql-flexible-server.md
+++ b/docs/database/includes/postgresql-flexible-server.md
@@ -12,7 +12,7 @@ dotnet add package Aspire.Hosting.Azure.PostgreSQL
```xml
+ Version="*" />
```
---
diff --git a/docs/database/includes/sql-app-host.md b/docs/database/includes/sql-app-host.md
index f9fd3a595..46af33a49 100644
--- a/docs/database/includes/sql-app-host.md
+++ b/docs/database/includes/sql-app-host.md
@@ -10,7 +10,7 @@ dotnet add package Aspire.Hosting.SqlServer
```xml
+ Version="*" />
```
---
diff --git a/docs/database/milvus-integration.md b/docs/database/milvus-integration.md
index c7ccc701e..f11d8cdea 100644
--- a/docs/database/milvus-integration.md
+++ b/docs/database/milvus-integration.md
@@ -27,7 +27,7 @@ dotnet add package Aspire.Milvus.Client
```xml
+ Version="*" />
```
---
@@ -56,7 +56,7 @@ dotnet add package Aspire.Hosting.Milvus
```xml
+ Version="*" />
```
---
diff --git a/docs/database/mongodb-integration.md b/docs/database/mongodb-integration.md
index 7f3b9387e..6390d1a8d 100644
--- a/docs/database/mongodb-integration.md
+++ b/docs/database/mongodb-integration.md
@@ -32,7 +32,7 @@ dotnet add package Aspire.MongoDB.Driver
```xml
+ Version="*" />
```
---
@@ -72,7 +72,7 @@ dotnet add package Aspire.Hosting.MongoDB
```xml
+ Version="*" />
```
---
diff --git a/docs/database/mysql-entity-framework-integration.md b/docs/database/mysql-entity-framework-integration.md
index c1f39faa8..5c1a2638a 100644
--- a/docs/database/mysql-entity-framework-integration.md
+++ b/docs/database/mysql-entity-framework-integration.md
@@ -22,7 +22,7 @@ dotnet add package Aspire.Pomelo.EntityFrameworkCore.MySql
```xml
+ Version="*" />
```
---
diff --git a/docs/database/mysql-integration.md b/docs/database/mysql-integration.md
index a750111eb..c3d4b1b30 100644
--- a/docs/database/mysql-integration.md
+++ b/docs/database/mysql-integration.md
@@ -31,7 +31,7 @@ dotnet add package Aspire.MySqlConnector
```xml
+ Version="*" />
```
---
diff --git a/docs/database/oracle-entity-framework-integration.md b/docs/database/oracle-entity-framework-integration.md
index 78de17892..58b0a9ffd 100644
--- a/docs/database/oracle-entity-framework-integration.md
+++ b/docs/database/oracle-entity-framework-integration.md
@@ -22,7 +22,7 @@ dotnet add package Aspire.Oracle.EntityFrameworkCore
```xml
+ Version="*" />
```
---
@@ -71,7 +71,7 @@ dotnet add package Aspire.Hosting.Oracle
```xml
+ Version="*" />
```
---
diff --git a/docs/database/postgresql-entity-framework-integration.md b/docs/database/postgresql-entity-framework-integration.md
index cb761e529..b43365b32 100644
--- a/docs/database/postgresql-entity-framework-integration.md
+++ b/docs/database/postgresql-entity-framework-integration.md
@@ -36,7 +36,7 @@ dotnet add package Aspire.Npgsql.EntityFrameworkCore.PostgreSQL
```xml
+ Version="*" />
```
---
@@ -178,7 +178,7 @@ Here are the configurable options with corresponding default values:
| Name | Description |
|-----------------------|--------------------------------------------------------------------------------------------------------|
-| `ConnectionString` | The connection string of the SQL Server database to connect to. |
+| `ConnectionString` | The connection string of the PostgreSQL database to connect to. |
| `MaxRetryCount` | The maximum number of retry attempts. Default value is 6, set it to 0 to disable the retry mechanism. |
| `DisableHealthChecks` | A boolean value that indicates whether the database health check is disabled or not. |
| `DisableTracing` | A boolean value that indicates whether the OpenTelemetry tracing is disabled or not. |
diff --git a/docs/database/postgresql-integration.md b/docs/database/postgresql-integration.md
index 7bfd6537f..97c8cbc86 100644
--- a/docs/database/postgresql-integration.md
+++ b/docs/database/postgresql-integration.md
@@ -22,7 +22,7 @@ dotnet add package Aspire.Npgsql
### [PackageReference](#tab/package-reference)
```xml
-
+
```
---
diff --git a/docs/database/qdrant-integration.md b/docs/database/qdrant-integration.md
index 714a76d3b..3b7fd6cb6 100644
--- a/docs/database/qdrant-integration.md
+++ b/docs/database/qdrant-integration.md
@@ -23,7 +23,7 @@ dotnet add package Aspire.Qdrant.Client
```xml
+ Version="*" />
```
---
@@ -61,7 +61,7 @@ dotnet add package Aspire.Hosting.Qdrant
```xml
+ Version="*" />
```
---
diff --git a/docs/database/snippets/cosmos-db/AspireApp.ApiService/AspireApp.ApiService.csproj b/docs/database/snippets/cosmos-db/AspireApp.ApiService/AspireApp.ApiService.csproj
index 79d847a56..88d15291c 100644
--- a/docs/database/snippets/cosmos-db/AspireApp.ApiService/AspireApp.ApiService.csproj
+++ b/docs/database/snippets/cosmos-db/AspireApp.ApiService/AspireApp.ApiService.csproj
@@ -7,7 +7,7 @@
-
+
diff --git a/docs/database/snippets/cosmos-db/AspireApp.AppHost/AspireApp.AppHost.csproj b/docs/database/snippets/cosmos-db/AspireApp.AppHost/AspireApp.AppHost.csproj
index 6714d26c0..ce216f5a3 100644
--- a/docs/database/snippets/cosmos-db/AspireApp.AppHost/AspireApp.AppHost.csproj
+++ b/docs/database/snippets/cosmos-db/AspireApp.AppHost/AspireApp.AppHost.csproj
@@ -15,8 +15,8 @@
-
-
+
+
diff --git a/docs/database/snippets/cosmos-db/AspireApp.ServiceDefaults/AspireApp.ServiceDefaults.csproj b/docs/database/snippets/cosmos-db/AspireApp.ServiceDefaults/AspireApp.ServiceDefaults.csproj
index 1dacfbff4..eb79c9d89 100644
--- a/docs/database/snippets/cosmos-db/AspireApp.ServiceDefaults/AspireApp.ServiceDefaults.csproj
+++ b/docs/database/snippets/cosmos-db/AspireApp.ServiceDefaults/AspireApp.ServiceDefaults.csproj
@@ -10,8 +10,8 @@
-
-
+
+
diff --git a/docs/database/snippets/tutorial/aspiresqldeployazure/AspireSql.AppHost/AspireSql.AppHost.csproj b/docs/database/snippets/tutorial/aspiresqldeployazure/AspireSql.AppHost/AspireSql.AppHost.csproj
index 69d70202e..d7e65828e 100644
--- a/docs/database/snippets/tutorial/aspiresqldeployazure/AspireSql.AppHost/AspireSql.AppHost.csproj
+++ b/docs/database/snippets/tutorial/aspiresqldeployazure/AspireSql.AppHost/AspireSql.AppHost.csproj
@@ -15,8 +15,8 @@
-
-
+
+
diff --git a/docs/database/snippets/tutorial/aspiresqldeployazure/AspireSql.ServiceDefaults/AspireSql.ServiceDefaults.csproj b/docs/database/snippets/tutorial/aspiresqldeployazure/AspireSql.ServiceDefaults/AspireSql.ServiceDefaults.csproj
index 1dacfbff4..eb79c9d89 100644
--- a/docs/database/snippets/tutorial/aspiresqldeployazure/AspireSql.ServiceDefaults/AspireSql.ServiceDefaults.csproj
+++ b/docs/database/snippets/tutorial/aspiresqldeployazure/AspireSql.ServiceDefaults/AspireSql.ServiceDefaults.csproj
@@ -10,8 +10,8 @@
-
-
+
+
diff --git a/docs/database/snippets/tutorial/aspiresqldeploycontainer/AspireSql.AppHost/AspireSql.AppHost.csproj b/docs/database/snippets/tutorial/aspiresqldeploycontainer/AspireSql.AppHost/AspireSql.AppHost.csproj
index 239036d8f..0d0ca9622 100644
--- a/docs/database/snippets/tutorial/aspiresqldeploycontainer/AspireSql.AppHost/AspireSql.AppHost.csproj
+++ b/docs/database/snippets/tutorial/aspiresqldeploycontainer/AspireSql.AppHost/AspireSql.AppHost.csproj
@@ -15,8 +15,8 @@
-
-
+
+
diff --git a/docs/database/snippets/tutorial/aspiresqldeploycontainer/AspireSql.ServiceDefaults/AspireSql.ServiceDefaults.csproj b/docs/database/snippets/tutorial/aspiresqldeploycontainer/AspireSql.ServiceDefaults/AspireSql.ServiceDefaults.csproj
index 1dacfbff4..eb79c9d89 100644
--- a/docs/database/snippets/tutorial/aspiresqldeploycontainer/AspireSql.ServiceDefaults/AspireSql.ServiceDefaults.csproj
+++ b/docs/database/snippets/tutorial/aspiresqldeploycontainer/AspireSql.ServiceDefaults/AspireSql.ServiceDefaults.csproj
@@ -10,8 +10,8 @@
-
-
+
+
diff --git a/docs/database/snippets/tutorial/aspiresqlefcore/AspireSQLEFCore.AppHost/AspireSQLEFCore.AppHost.csproj b/docs/database/snippets/tutorial/aspiresqlefcore/AspireSQLEFCore.AppHost/AspireSQLEFCore.AppHost.csproj
index 6d14df1d8..f00391d89 100644
--- a/docs/database/snippets/tutorial/aspiresqlefcore/AspireSQLEFCore.AppHost/AspireSQLEFCore.AppHost.csproj
+++ b/docs/database/snippets/tutorial/aspiresqlefcore/AspireSQLEFCore.AppHost/AspireSQLEFCore.AppHost.csproj
@@ -10,8 +10,8 @@
-
-
+
+
diff --git a/docs/database/snippets/tutorial/aspiresqlefcore/AspireSQLEFCore.ServiceDefaults/AspireSQLEFCore.ServiceDefaults.csproj b/docs/database/snippets/tutorial/aspiresqlefcore/AspireSQLEFCore.ServiceDefaults/AspireSQLEFCore.ServiceDefaults.csproj
index 1dacfbff4..eb79c9d89 100644
--- a/docs/database/snippets/tutorial/aspiresqlefcore/AspireSQLEFCore.ServiceDefaults/AspireSQLEFCore.ServiceDefaults.csproj
+++ b/docs/database/snippets/tutorial/aspiresqlefcore/AspireSQLEFCore.ServiceDefaults/AspireSQLEFCore.ServiceDefaults.csproj
@@ -10,8 +10,8 @@
-
-
+
+
diff --git a/docs/database/snippets/tutorial/aspiresqlefcore/AspireSQLEFCore/AspireSQLEFCore.csproj b/docs/database/snippets/tutorial/aspiresqlefcore/AspireSQLEFCore/AspireSQLEFCore.csproj
index a39b3fe9f..206a283ba 100644
--- a/docs/database/snippets/tutorial/aspiresqlefcore/AspireSQLEFCore/AspireSQLEFCore.csproj
+++ b/docs/database/snippets/tutorial/aspiresqlefcore/AspireSQLEFCore/AspireSQLEFCore.csproj
@@ -7,7 +7,7 @@
-
+
diff --git a/docs/database/sql-server-entity-framework-integration.md b/docs/database/sql-server-entity-framework-integration.md
index 803bbcc63..52fac037a 100644
--- a/docs/database/sql-server-entity-framework-integration.md
+++ b/docs/database/sql-server-entity-framework-integration.md
@@ -32,7 +32,7 @@ dotnet add package Aspire.Microsoft.EntityFrameworkCore.SqlServer
```xml
+ Version="*" />
```
---
diff --git a/docs/database/sql-server-integration.md b/docs/database/sql-server-integration.md
index f978cd07f..b1efe1109 100644
--- a/docs/database/sql-server-integration.md
+++ b/docs/database/sql-server-integration.md
@@ -33,7 +33,7 @@ dotnet add package Aspire.Microsoft.Data.SqlClient
```xml
+ Version="*" />
```
---
diff --git a/docs/deployment/azure/aca-deployment-azd-in-depth.md b/docs/deployment/azure/aca-deployment-azd-in-depth.md
index 18db2fc98..bac6b7692 100644
--- a/docs/deployment/azure/aca-deployment-azd-in-depth.md
+++ b/docs/deployment/azure/aca-deployment-azd-in-depth.md
@@ -213,7 +213,7 @@ After this command is executed in the starter template example used in this guid
- _infra/main.bicep_: Represents the main entry point for the deployment.
- _infra/main.parameters.json_: Used as the parameters for main Bicep (maps to environment variables defined in _.azure_ folder).
-- _infra/resoures.bicep_: Defines the Azure resources required to support the .NET Aspire project model.
+- _infra/resources.bicep_: Defines the Azure resources required to support the .NET Aspire project model.
- _AspireSample.Web/manifests/containerApp.tmpl.yaml_: The container app definition for `webfrontend`.
- _AspireSample.ApiService/manifests/containerApp.tmpl.yaml_: The container app definition for `apiservice`.
diff --git a/docs/deployment/azure/application-insights.md b/docs/deployment/azure/application-insights.md
index e38abf2b6..12c819dee 100644
--- a/docs/deployment/azure/application-insights.md
+++ b/docs/deployment/azure/application-insights.md
@@ -120,7 +120,7 @@ Add the following package to the `ServiceDefaults` project, so that it will be i
``` xml
+ Version="*" />
```
Add a using statement to the top of the project.
diff --git a/docs/deployment/azure/custom-bicep-templates.md b/docs/deployment/azure/custom-bicep-templates.md
index 6f0e8b9cf..b97e45133 100644
--- a/docs/deployment/azure/custom-bicep-templates.md
+++ b/docs/deployment/azure/custom-bicep-templates.md
@@ -29,7 +29,7 @@ dotnet add package Aspire.Hosting.Azure
```xml
+ Version="*" />
```
---
diff --git a/docs/deployment/azure/snippets/AppHost.Bicep/AppHost.Bicep.csproj b/docs/deployment/azure/snippets/AppHost.Bicep/AppHost.Bicep.csproj
index 7745561db..688869abc 100644
--- a/docs/deployment/azure/snippets/AppHost.Bicep/AppHost.Bicep.csproj
+++ b/docs/deployment/azure/snippets/AppHost.Bicep/AppHost.Bicep.csproj
@@ -10,8 +10,8 @@
-
-
+
+
diff --git a/docs/deployment/azure/snippets/WebHook.Api/WebHook.Api.csproj b/docs/deployment/azure/snippets/WebHook.Api/WebHook.Api.csproj
index e7f5c09fa..5a2437e12 100644
--- a/docs/deployment/azure/snippets/WebHook.Api/WebHook.Api.csproj
+++ b/docs/deployment/azure/snippets/WebHook.Api/WebHook.Api.csproj
@@ -7,8 +7,8 @@
-
-
+
+
diff --git a/docs/extensibility/snippets/MailDevResource/MailDev.Hosting/MailDev.Hosting.csproj b/docs/extensibility/snippets/MailDevResource/MailDev.Hosting/MailDev.Hosting.csproj
index 578bc3e26..1eedbd043 100644
--- a/docs/extensibility/snippets/MailDevResource/MailDev.Hosting/MailDev.Hosting.csproj
+++ b/docs/extensibility/snippets/MailDevResource/MailDev.Hosting/MailDev.Hosting.csproj
@@ -7,7 +7,7 @@
-
+
diff --git a/docs/extensibility/snippets/MailDevResource/MailDevResource.AppHost/MailDevResource.AppHost.csproj b/docs/extensibility/snippets/MailDevResource/MailDevResource.AppHost/MailDevResource.AppHost.csproj
index cc335ea81..3cfa77363 100644
--- a/docs/extensibility/snippets/MailDevResource/MailDevResource.AppHost/MailDevResource.AppHost.csproj
+++ b/docs/extensibility/snippets/MailDevResource/MailDevResource.AppHost/MailDevResource.AppHost.csproj
@@ -10,7 +10,7 @@
-
+
diff --git a/docs/extensibility/snippets/MailDevResource/MailDevResource.NewsletterService/MailDevResource.NewsletterService.csproj b/docs/extensibility/snippets/MailDevResource/MailDevResource.NewsletterService/MailDevResource.NewsletterService.csproj
index f860a324a..e45d528ec 100644
--- a/docs/extensibility/snippets/MailDevResource/MailDevResource.NewsletterService/MailDevResource.NewsletterService.csproj
+++ b/docs/extensibility/snippets/MailDevResource/MailDevResource.NewsletterService/MailDevResource.NewsletterService.csproj
@@ -1,8 +1,8 @@
-
-
+
+
diff --git a/docs/extensibility/snippets/MailDevResource/MailDevResource.ServiceDefaults/MailDevResource.ServiceDefaults.csproj b/docs/extensibility/snippets/MailDevResource/MailDevResource.ServiceDefaults/MailDevResource.ServiceDefaults.csproj
index 1dacfbff4..eb79c9d89 100644
--- a/docs/extensibility/snippets/MailDevResource/MailDevResource.ServiceDefaults/MailDevResource.ServiceDefaults.csproj
+++ b/docs/extensibility/snippets/MailDevResource/MailDevResource.ServiceDefaults/MailDevResource.ServiceDefaults.csproj
@@ -10,8 +10,8 @@
-
-
+
+
diff --git a/docs/extensibility/snippets/MailDevResourceAndComponent/MailDev.Hosting/MailDev.Hosting.csproj b/docs/extensibility/snippets/MailDevResourceAndComponent/MailDev.Hosting/MailDev.Hosting.csproj
index 578bc3e26..1eedbd043 100644
--- a/docs/extensibility/snippets/MailDevResourceAndComponent/MailDev.Hosting/MailDev.Hosting.csproj
+++ b/docs/extensibility/snippets/MailDevResourceAndComponent/MailDev.Hosting/MailDev.Hosting.csproj
@@ -7,7 +7,7 @@
-
+
diff --git a/docs/extensibility/snippets/MailDevResourceAndComponent/MailDevResource.AppHost/MailDevResource.AppHost.csproj b/docs/extensibility/snippets/MailDevResourceAndComponent/MailDevResource.AppHost/MailDevResource.AppHost.csproj
index cc335ea81..3cfa77363 100644
--- a/docs/extensibility/snippets/MailDevResourceAndComponent/MailDevResource.AppHost/MailDevResource.AppHost.csproj
+++ b/docs/extensibility/snippets/MailDevResourceAndComponent/MailDevResource.AppHost/MailDevResource.AppHost.csproj
@@ -10,7 +10,7 @@
-
+
diff --git a/docs/extensibility/snippets/MailDevResourceAndComponent/MailDevResource.NewsletterService/MailDevResource.NewsletterService.csproj b/docs/extensibility/snippets/MailDevResourceAndComponent/MailDevResource.NewsletterService/MailDevResource.NewsletterService.csproj
index 6525d044b..f9a2a07f0 100644
--- a/docs/extensibility/snippets/MailDevResourceAndComponent/MailDevResource.NewsletterService/MailDevResource.NewsletterService.csproj
+++ b/docs/extensibility/snippets/MailDevResourceAndComponent/MailDevResource.NewsletterService/MailDevResource.NewsletterService.csproj
@@ -1,8 +1,8 @@
-
-
+
+
diff --git a/docs/extensibility/snippets/MailDevResourceAndComponent/MailDevResource.ServiceDefaults/MailDevResource.ServiceDefaults.csproj b/docs/extensibility/snippets/MailDevResourceAndComponent/MailDevResource.ServiceDefaults/MailDevResource.ServiceDefaults.csproj
index 1dacfbff4..eb79c9d89 100644
--- a/docs/extensibility/snippets/MailDevResourceAndComponent/MailDevResource.ServiceDefaults/MailDevResource.ServiceDefaults.csproj
+++ b/docs/extensibility/snippets/MailDevResourceAndComponent/MailDevResource.ServiceDefaults/MailDevResource.ServiceDefaults.csproj
@@ -10,8 +10,8 @@
-
-
+
+
diff --git a/docs/extensibility/snippets/MailDevResourceAndComponent/MailKit.Client/MailKit.Client.csproj b/docs/extensibility/snippets/MailDevResourceAndComponent/MailKit.Client/MailKit.Client.csproj
index 457237de6..90309ddbd 100644
--- a/docs/extensibility/snippets/MailDevResourceAndComponent/MailKit.Client/MailKit.Client.csproj
+++ b/docs/extensibility/snippets/MailDevResourceAndComponent/MailKit.Client/MailKit.Client.csproj
@@ -7,11 +7,11 @@
-
-
-
-
-
+
+
+
+
+
diff --git a/docs/extensibility/snippets/MailDevResourceWithCredentials/MailDev.Hosting/MailDev.Hosting.csproj b/docs/extensibility/snippets/MailDevResourceWithCredentials/MailDev.Hosting/MailDev.Hosting.csproj
index 578bc3e26..1eedbd043 100644
--- a/docs/extensibility/snippets/MailDevResourceWithCredentials/MailDev.Hosting/MailDev.Hosting.csproj
+++ b/docs/extensibility/snippets/MailDevResourceWithCredentials/MailDev.Hosting/MailDev.Hosting.csproj
@@ -7,7 +7,7 @@
-
+
diff --git a/docs/extensibility/snippets/MailDevResourceWithCredentials/MailDevResource.AppHost/MailDevResource.AppHost.csproj b/docs/extensibility/snippets/MailDevResourceWithCredentials/MailDevResource.AppHost/MailDevResource.AppHost.csproj
index cc335ea81..3cfa77363 100644
--- a/docs/extensibility/snippets/MailDevResourceWithCredentials/MailDevResource.AppHost/MailDevResource.AppHost.csproj
+++ b/docs/extensibility/snippets/MailDevResourceWithCredentials/MailDevResource.AppHost/MailDevResource.AppHost.csproj
@@ -10,7 +10,7 @@
-
+
diff --git a/docs/extensibility/snippets/MailDevResourceWithCredentials/MailDevResource.NewsletterService/MailDevResource.NewsletterService.csproj b/docs/extensibility/snippets/MailDevResourceWithCredentials/MailDevResource.NewsletterService/MailDevResource.NewsletterService.csproj
index 6525d044b..f9a2a07f0 100644
--- a/docs/extensibility/snippets/MailDevResourceWithCredentials/MailDevResource.NewsletterService/MailDevResource.NewsletterService.csproj
+++ b/docs/extensibility/snippets/MailDevResourceWithCredentials/MailDevResource.NewsletterService/MailDevResource.NewsletterService.csproj
@@ -1,8 +1,8 @@
-
-
+
+
diff --git a/docs/extensibility/snippets/MailDevResourceWithCredentials/MailDevResource.ServiceDefaults/MailDevResource.ServiceDefaults.csproj b/docs/extensibility/snippets/MailDevResourceWithCredentials/MailDevResource.ServiceDefaults/MailDevResource.ServiceDefaults.csproj
index 1dacfbff4..eb79c9d89 100644
--- a/docs/extensibility/snippets/MailDevResourceWithCredentials/MailDevResource.ServiceDefaults/MailDevResource.ServiceDefaults.csproj
+++ b/docs/extensibility/snippets/MailDevResourceWithCredentials/MailDevResource.ServiceDefaults/MailDevResource.ServiceDefaults.csproj
@@ -10,8 +10,8 @@
-
-
+
+
diff --git a/docs/frameworks/dapr.md b/docs/frameworks/dapr.md
index 63d4fd7d1..158be383e 100644
--- a/docs/frameworks/dapr.md
+++ b/docs/frameworks/dapr.md
@@ -40,7 +40,7 @@ dotnet add package Aspire.Hosting.Dapr
```xml
+ Version="*" />
```
---
@@ -87,7 +87,7 @@ dotnet add package Dapr.AspNetCore
```xml
+ Version="*" />
```
---
diff --git a/docs/frameworks/orleans.md b/docs/frameworks/orleans.md
index 5e4ab7b9e..7c73c94fe 100644
--- a/docs/frameworks/orleans.md
+++ b/docs/frameworks/orleans.md
@@ -33,7 +33,7 @@ dotnet add package Aspire.Hosting.Orleans
```xml
+ Version="*" />
```
---
diff --git a/docs/frameworks/snippets/Dapr/Dapr.AppHost/Dapr.AppHost.csproj b/docs/frameworks/snippets/Dapr/Dapr.AppHost/Dapr.AppHost.csproj
index a18a1877d..c0a250ba9 100644
--- a/docs/frameworks/snippets/Dapr/Dapr.AppHost/Dapr.AppHost.csproj
+++ b/docs/frameworks/snippets/Dapr/Dapr.AppHost/Dapr.AppHost.csproj
@@ -15,8 +15,8 @@
-
-
+
+
diff --git a/docs/frameworks/snippets/Dapr/Dapr.ServiceDefaults/Dapr.ServiceDefaults.csproj b/docs/frameworks/snippets/Dapr/Dapr.ServiceDefaults/Dapr.ServiceDefaults.csproj
index 1dacfbff4..eb79c9d89 100644
--- a/docs/frameworks/snippets/Dapr/Dapr.ServiceDefaults/Dapr.ServiceDefaults.csproj
+++ b/docs/frameworks/snippets/Dapr/Dapr.ServiceDefaults/Dapr.ServiceDefaults.csproj
@@ -10,8 +10,8 @@
-
-
+
+
diff --git a/docs/frameworks/snippets/Orleans/OrleansAppHost/OrleansAppHost.csproj b/docs/frameworks/snippets/Orleans/OrleansAppHost/OrleansAppHost.csproj
index fdfcb0ee8..475a22543 100644
--- a/docs/frameworks/snippets/Orleans/OrleansAppHost/OrleansAppHost.csproj
+++ b/docs/frameworks/snippets/Orleans/OrleansAppHost/OrleansAppHost.csproj
@@ -10,10 +10,10 @@
-
-
-
-
+
+
+
+
diff --git a/docs/frameworks/snippets/Orleans/OrleansClient/OrleansClient.csproj b/docs/frameworks/snippets/Orleans/OrleansClient/OrleansClient.csproj
index 7f5269c36..b28f76f03 100644
--- a/docs/frameworks/snippets/Orleans/OrleansClient/OrleansClient.csproj
+++ b/docs/frameworks/snippets/Orleans/OrleansClient/OrleansClient.csproj
@@ -11,7 +11,7 @@
-
+
diff --git a/docs/frameworks/snippets/Orleans/OrleansServer/OrleansServer.csproj b/docs/frameworks/snippets/Orleans/OrleansServer/OrleansServer.csproj
index 5c2bf8ddf..0e1240f1b 100644
--- a/docs/frameworks/snippets/Orleans/OrleansServer/OrleansServer.csproj
+++ b/docs/frameworks/snippets/Orleans/OrleansServer/OrleansServer.csproj
@@ -14,8 +14,8 @@
-
-
+
+
diff --git a/docs/frameworks/snippets/Orleans/OrleansServiceDefaults/OrleansServiceDefaults.csproj b/docs/frameworks/snippets/Orleans/OrleansServiceDefaults/OrleansServiceDefaults.csproj
index c5fa5a4f7..5cec29100 100644
--- a/docs/frameworks/snippets/Orleans/OrleansServiceDefaults/OrleansServiceDefaults.csproj
+++ b/docs/frameworks/snippets/Orleans/OrleansServiceDefaults/OrleansServiceDefaults.csproj
@@ -14,8 +14,8 @@
-
-
+
+
diff --git a/docs/fundamentals/app-host-overview.md b/docs/fundamentals/app-host-overview.md
index 1c68a07ef..165b4703d 100644
--- a/docs/fundamentals/app-host-overview.md
+++ b/docs/fundamentals/app-host-overview.md
@@ -105,7 +105,7 @@ The "webfrontend" project resource uses method:
+To express a , use the method:
#### [Docker](#tab/docker)
@@ -141,6 +141,15 @@ For more information, see [GPU support in Podman](https://github.com/containers/
The preceding code adds a container resource named "ollama" with the image "ollama/ollama". The container resource is configured with multiple bind mounts, a named HTTP endpoint, an entrypoint that resolves to Unix shell script, and container run arguments with the method.
+#### Container resource lifecycle
+
+When the app host is run, the container resource is used to determine what container image to create and start. Under the hood, .NET Aspire runs the container using the defined container image by delegating calls to the appropriate OCI-compliant container runtime, either Docker or Podman. The following commands are used:
+
+- `docker/podman container create`: Create the container.
+- `docker/podman container start`: Start the container.
+
+These commands are used instead of `docker/podman run` to manage attached container networks, volumes, and ports. Calling these commands in this order allows any IP (network configuration) to already be present at initial startup.
+
Beyond the base resource types, , , and , .NET Aspire provides extension methods to add common resources to your app model. For more information, see [Hosting integrations](integrations-overview.md#hosting-integrations).
### Connection string and endpoint references
diff --git a/docs/fundamentals/dashboard/configuration.md b/docs/fundamentals/dashboard/configuration.md
index 3c50774a7..5928238f4 100644
--- a/docs/fundamentals/dashboard/configuration.md
+++ b/docs/fundamentals/dashboard/configuration.md
@@ -1,7 +1,7 @@
---
title: .NET Aspire dashboard configuration
description: .NET Aspire dashboard configuration options
-ms.date: 09/11/2024
+ms.date: 10/03/2024
ms.topic: reference
---
@@ -26,7 +26,7 @@ docker run --rm -it -p 18888:18888 -p 4317:18889 -d --name aspire-dashboard \
-e DASHBOARD__TELEMETRYLIMITS__MAXLOGCOUNT='1000' \
-e DASHBOARD__TELEMETRYLIMITS__MAXTRACECOUNT='1000' \
-e DASHBOARD__TELEMETRYLIMITS__MAXMETRICSCOUNT='1000' \
- mcr.microsoft.com/dotnet/aspire-dashboard:8.0.0
+ mcr.microsoft.com/dotnet/aspire-dashboard:8.2
```
## [PowerShell](#tab/powershell)
@@ -36,7 +36,7 @@ docker run --rm -it -p 18888:18888 -p 4317:18889 -d --name aspire-dashboard `
-e DASHBOARD__TELEMETRYLIMITS__MAXLOGCOUNT='1000' `
-e DASHBOARD__TELEMETRYLIMITS__MAXTRACECOUNT='1000' `
-e DASHBOARD__TELEMETRYLIMITS__MAXMETRICSCOUNT='1000' `
- mcr.microsoft.com/dotnet/aspire-dashboard:8.0.0
+ mcr.microsoft.com/dotnet/aspire-dashboard:8.2
```
---
@@ -106,13 +106,9 @@ API key authentication works by requiring each OTLP request to have a valid `x-o
## OTLP CORS
-CORS (Cross-Origin Resource Sharing) can be configured to allow browser apps to send telemetry to the dashboard.
+Cross-origin resource sharing (CORS) can be configured to allow browser apps to send telemetry to the dashboard.
-By default, browser apps are restricted from making cross domain API calls. This impacts sending telemetry to the dashboard because the dashboard and the browser app are always on different domains. Configuring CORS in the .NET Aspire dashboard removes the restriction and allows browser apps with the [OpenTelemetry SDK for JavaScript](https://opentelemetry.io/docs/languages/js/) to send telemetry directly to the dashboard OTLP HTTP endpoint.
-
-Using CORS, the dashboard and browser telemetry together is demonstrated in the [browser telemetry](https://github.com/dotnet/aspire/tree/main/playground/BrowserTelemetry) sample.
-
-To configure CORS, use the `Dashboard:Otlp:Cors` section and specify the allowed origins and headers:
+By default, browser apps are restricted from making cross domain API calls. This impacts sending telemetry to the dashboard because the dashboard and the browser app are always on different domains. To configure CORS, use the `Dashboard:Otlp:Cors` section and specify the allowed origins and headers:
```json
{
diff --git a/docs/fundamentals/dashboard/enable-browser-telemetry.md b/docs/fundamentals/dashboard/enable-browser-telemetry.md
new file mode 100644
index 000000000..d441f4400
--- /dev/null
+++ b/docs/fundamentals/dashboard/enable-browser-telemetry.md
@@ -0,0 +1,170 @@
+---
+title: Enable browser telemetry
+description: Learn how to enable browser telemetry in the .NET Aspire dashboard.
+ms.date: 10/11/2024
+---
+
+# Enable browser telemetry
+
+The .NET Aspire dashboard can be configured to receive telemetry sent from browser apps. This feature is useful for monitoring client-side performance and user interactions. Browser telemetry requires additional dashboard configuration and that the [JavaScript OTEL SDK](https://opentelemetry.io/docs/languages/js/getting-started/browser/) is added to the browser apps.
+
+This article discusses how to enable browser telemetry in the .NET Aspire dashboard.
+
+## Dashboard configuration
+
+Browser telemetry requires the dashboard to enable these features:
+
+- OTLP HTTP endpoint. This endpoint is used by the dashboard to receive telemetry from browser apps.
+- Cross-origin resource sharing (CORS). CORS allows browser apps to make requests to the dashboard.
+
+### OTLP configuration
+
+The .NET Aspire dashboard receives telemetry through OTLP endpoints. [HTTP OTLP endpoints](https://opentelemetry.io/docs/specs/otlp/#otlphttp) and gRPC OTLP endpoints are supported by the dashboard. Browser apps must use HTTP OLTP to send telemetry to the dashboard because browser apps don't support gRPC.
+
+To configure the gPRC or HTTP endpoints, specify the following environment variables:
+
+- `DOTNET_DASHBOARD_OTLP_ENDPOINT_URL`: The gRPC endpoint to which the dashboard connects for its data.
+- `DOTNET_DASHBOARD_OTLP_HTTP_ENDPOINT_URL`: The HTTP endpoint to which the dashboard connects for its data.
+
+Configuration of the HTTP OTLP endpoint depends on whether the dashboard is started by the app host or is run standalone.
+
+#### Configure OTLP HTTP with app host
+
+If the dashboard and your app are started by the app host, the dashboard OTLP endpoints are configured in the app host's _launchSettings.json_ file.
+
+Consider the following example JSON file:
+
+:::code language="json" source="snippets/BrowserTelemetry/BrowserTelemetry.AppHost/Properties/launchSettings.json" highlight="12,25":::
+
+The preceding launch settings JSON file configures all profiles to include the `DOTNET_DASHBOARD_OTLP_HTTP_ENDPOINT_URL` environment variable.
+
+#### Configure OTLP HTTP with standalone dashboard
+
+If the dashboard is used standalone, without the rest of .NET Aspire, the OTLP HTTP endpoint is enabled by default on port `18890`. However, the port must be mapped when the dashboard container is started:
+
+### [Bash](#tab/bash)
+
+```bash
+docker run --rm -it -d \
+ -p 18888:18888 \
+ -p 4317:18889 \
+ -p 4318:18890 \
+ --name aspire-dashboard \
+ mcr.microsoft.com/dotnet/aspire-dashboard:8.2
+```
+
+### [PowerShell](#tab/powershell)
+
+```powershell
+docker run --rm -it -d `
+ -p 18888:18888 `
+ -p 4317:18889 `
+ -p 4318:18890 `
+ --name aspire-dashboard `
+ mcr.microsoft.com/dotnet/aspire-dashboard:8.2
+```
+
+---
+
+The preceding command runs the dashboard container and maps gRPC OTLP to port `4317` and HTTP OTLP to port `4318`.
+
+### CORS configuration
+
+By default, browser apps are restricted from making cross domain API calls. This impacts sending telemetry to the dashboard because the dashboard and the browser app are always on different domains. Configuring CORS in the .NET Aspire dashboard removes the restriction.
+
+If the dashboard and your app are started by the app host, no CORS configuration is required. .NET Aspire automatically configures the dashboard to allow all resource origins.
+
+If the dashboard is used standlone then CORS must be configured manually. The domain used to view the browser app must be configured as an allowed origin by specifing the `DASHBOARD__OTLP__CORS__ALLOWEDORIGINS` environment variable when the dashboard container is started:
+
+### [Bash](#tab/bash)
+
+```bash
+docker run --rm -it -d \
+ -p 18888:18888 \
+ -p 4317:18889 \
+ -p 4318:18890 \
+ -e DASHBOARD__OTLP__CORS__ALLOWEDORIGINS=https://localhost:8080 \
+ --name aspire-dashboard \
+ mcr.microsoft.com/dotnet/aspire-dashboard:8.2
+```
+
+### [PowerShell](#tab/powershell)
+
+```powershell
+docker run --rm -it -d `
+ -p 18888:18888 `
+ -p 4317:18889 `
+ -p 4318:18890 `
+ -e DASHBOARD__OTLP__CORS__ALLOWEDORIGINS=https://localhost:8080 `
+ --name aspire-dashboard `
+ mcr.microsoft.com/dotnet/aspire-dashboard:8.2
+```
+
+---
+
+The preceding command runs the dashboard container and configures `https://localhost:8080` as an allowed origin. That means a browser app that is accessed using `https://localhost:8080` has permission to send the dashboard telemetry.
+
+Multiple origins can be allowed with a comma separated value. Or all origins can be allowed with the `*` wildcard. For example, `DASHBOARD__OTLP__CORS__ALLOWEDORIGINS=*`.
+
+For more information, see [.NET Aspire dashboard configuration: OTLP CORS](configuration.md#otlp-cors).
+
+### OTLP endpoint security
+
+Dashboard OTLP endpoints can be secured with API key authentication. When enabled, HTTP OTLP requests to the dashboard must include the API key as the `x-otlp-api-key` header. By default a new API key is generated each time the dashboard is run.
+
+API key authentication is automatically enabled when the dashboard is run from the app host. Dashboard authentication can be disabled by setting `DOTNET_DASHBOARD_UNSECURED_ALLOW_ANONYMOUS` to `true` in the app host's _launchSettings.json_ file.
+
+OTLP endpoints are unsecured by default in the standalone dashboard.
+
+## Browser app configuration
+
+A browser app uses the [JavaScript OTEL SDK](https://opentelemetry.io/docs/languages/js/getting-started/browser/) to send telemetry to the dashboard. Successfully sending telemetry to the dashboard requires the SDK to be correctly configured.
+
+### OTLP exporter
+
+OTLP exporters must be included in the browser app and configured with the SDK. For example, exporting distributed tracing with OTLP uses the [@opentelemetry/exporter-trace-otlp-proto](https://www.npmjs.com/package/@opentelemetry/exporter-trace-otlp-proto) package.
+
+When OTLP is added to the SDK, OTLP options must be specified. OTLP options includes:
+
+- `url`: The address that HTTP OTLP requests are made to. The address should be the dashboard HTTP OTLP endpoint and the path to the OTLP HTTP API. For example, `https://localhost:4318/v1/traces` for the trace OTLP exporter. If the browser app is launched by the app host then the HTTP OTLP endpoint is available from the `OTEL_EXPORTER_OTLP_ENDPOINT` environment variable.
+
+- `headers`: The headers sent with requests. If OTLP endpoint API key authentication is enabled the `x-otlp-api-key` header must be sent with OTLP requests. If the browser app is launched by the app host then the API key is available from the `OTEL_EXPORTER_OTLP_HEADERS` environment variable.
+
+### Browser metadata
+
+When a browser app is configured to collect distributed traces, the browser app can set the trace parent a browser's spans using the `meta` element in the HTML. The value of the `name="traceparent"` meta element should correspond to the current trace.
+
+In a .NET app, for example, the trace parent value would likely be assigned from the and passing its value as the `content`. For example, consider the following Razor code:
+
+```razor
+
+ @if (Activity.Current is { } currentActivity)
+ {
+
+ }
+
+
+```
+
+The preceding code sets the `traceparent` meta element to the current activity ID.
+
+## Example browser telemetry code
+
+The following JavaScript code demonstrates the initialization of the OpenTelemetry JavaScript SDK and the sending of telemetry data to the dashboard:
+
+:::code language="javascript" source="snippets/BrowserTelemetry/BrowserTelemetry.Web/Scripts/index.js":::
+
+The preceding JavaScript code defines an `initializeTelemetry` function that expects the OTLP endpoint URL, the headers, and the resource attributes. These parameters are provided by the consuming browser app that pulls them from the environment variables set by the app host. Consider the following Razor code:
+
+:::code language="razor" source="snippets/BrowserTelemetry/BrowserTelemetry.Web/Pages/Shared/_Layout.cshtml" highlight="31-38":::
+
+> [!TIP]
+> The bundling and minification of the JavaScript code is beyond the scope of this article.
+
+For the complete working example of how to configure the JavaScript OTEL SDK to send telemetry to the dashboard, see the [browser telemetry sample](https://github.com/dotnet/aspire/tree/main/playground/BrowserTelemetry).
+
+## See also
+
+- [.NET Aspire dashboard configuration](configuration.md)
+- [Standalone .NET Aspire dashboard](standalone.md)
+- [Browser telemetry sample](https://github.com/dotnet/aspire/tree/main/playground/BrowserTelemetry)
diff --git a/docs/fundamentals/dashboard/overview.md b/docs/fundamentals/dashboard/overview.md
index b09dafc27..3db9b72c4 100644
--- a/docs/fundamentals/dashboard/overview.md
+++ b/docs/fundamentals/dashboard/overview.md
@@ -1,15 +1,15 @@
---
title: .NET Aspire dashboard overview
description: Overview of .NET Aspire dashboard and getting started.
-ms.date: 05/30/2024
+ms.date: 10/03/2024
ms.topic: reference
---
# .NET Aspire dashboard overview
-[.NET Aspire](../../get-started/aspire-overview.md) project templates offer a sophisticated dashboard for comprehensive app monitoring and inspection. This dashboard allows you to closely track various aspects of your app, including logs, traces, and environment configurations, in real-time. It's purpose-built to enhance the local development experience, providing an insightful overview of your app's state and structure.
+[.NET Aspire](../../get-started/aspire-overview.md) project templates offer a sophisticated dashboard for comprehensive app monitoring and inspection, and it's also available in [standalone mode](#standalone-mode). This dashboard allows you to closely track various aspects of your app, including logs, traces, and environment configurations, in real-time. It's purpose-built to enhance the development experience, providing an insightful overview of your app's state and structure.
-## Using the dashboard with .NET Aspire projects
+## Use the dashboard with .NET Aspire projects
The dashboard is integrated into the .NET Aspire **AppHost**. During development the dashboard is automatically launched when you start the project. It's configured to display the .NET Aspire project's resources and telemetry.
@@ -25,21 +25,21 @@ The .NET Aspire dashboard is also shipped as a Docker image and can be used stan
```bash
docker run --rm -it -p 18888:18888 -p 4317:18889 -d --name aspire-dashboard \
- mcr.microsoft.com/dotnet/aspire-dashboard:8.0.0
+ mcr.microsoft.com/dotnet/aspire-dashboard:8.2
```
## [PowerShell](#tab/powershell)
```powershell
docker run --rm -it -p 18888:18888 -p 4317:18889 -d --name aspire-dashboard `
- mcr.microsoft.com/dotnet/aspire-dashboard:8.0.0
+ mcr.microsoft.com/dotnet/aspire-dashboard:8.2
```
---
The preceding Docker command:
-- Starts a container from the `mcr.microsoft.com/dotnet/aspire-dashboard:8.0.0` image.
+- Starts a container from the `mcr.microsoft.com/dotnet/aspire-dashboard:8.2` image.
- The container publishes exposing two ports:
- Maps the dashboard's OTLP port `18889` to the host's port `4317`. Port `4317` receives OpenTelemetry data from apps. Apps send data using [OpenTelemetry Protocol (OTLP)](https://opentelemetry.io/docs/specs/otlp/).
- Maps the dashboard's port `18888` to the host's port `18888`. Port `18888` has the dashboard UI. Navigate to `http://localhost:18888` in the browser to view the dashboard.
diff --git a/docs/fundamentals/dashboard/security-considerations.md b/docs/fundamentals/dashboard/security-considerations.md
index 137c6f8d7..08df07060 100644
--- a/docs/fundamentals/dashboard/security-considerations.md
+++ b/docs/fundamentals/dashboard/security-considerations.md
@@ -54,19 +54,19 @@ API key authentication can be enabled on the telemetry endpoint with some additi
## [Bash](#tab/bash)
```bash
-docker run --rm -it -p 18888:18888 -p 4317:18889 -d --name aspire-dashboard \
+docker run --rm -it -d -p 18888:18888 -p 4317:18889 --name aspire-dashboard \
-e DASHBOARD__OTLP__AUTHMODE='ApiKey' \
-e DASHBOARD__OTLP__PRIMARYAPIKEY='{MY_APIKEY}' \
- mcr.microsoft.com/dotnet/aspire-dashboard:8.0.0
+ mcr.microsoft.com/dotnet/aspire-dashboard:8.2
```
## [PowerShell](#tab/powershell)
```powershell
-docker run --rm -it -p 18888:18888 -p 4317:18889 -d --name aspire-dashboard `
+docker run --rm -it -d -p 18888:18888 -p 4317:18889 --name aspire-dashboard `
-e DASHBOARD__OTLP__AUTHMODE='ApiKey' `
-e DASHBOARD__OTLP__PRIMARYAPIKEY='{MY_APIKEY}' `
- mcr.microsoft.com/dotnet/aspire-dashboard:8.0.0
+ mcr.microsoft.com/dotnet/aspire-dashboard:8.2
```
---
diff --git a/docs/fundamentals/dashboard/snippets/BrowserTelemetry/BrowserTelemetry.AppHost/BrowserTelemetry.AppHost.csproj b/docs/fundamentals/dashboard/snippets/BrowserTelemetry/BrowserTelemetry.AppHost/BrowserTelemetry.AppHost.csproj
new file mode 100644
index 000000000..282963264
--- /dev/null
+++ b/docs/fundamentals/dashboard/snippets/BrowserTelemetry/BrowserTelemetry.AppHost/BrowserTelemetry.AppHost.csproj
@@ -0,0 +1,17 @@
+
+
+
+ Exe
+ net8.0
+ enable
+ enable
+ true
+ 7247ba20-5e3e-4299-afa7-4ca58ebe3488
+
+
+
+
+
+
+
+
diff --git a/docs/fundamentals/dashboard/snippets/BrowserTelemetry/BrowserTelemetry.AppHost/Program.cs b/docs/fundamentals/dashboard/snippets/BrowserTelemetry/BrowserTelemetry.AppHost/Program.cs
new file mode 100644
index 000000000..4ae2eae6c
--- /dev/null
+++ b/docs/fundamentals/dashboard/snippets/BrowserTelemetry/BrowserTelemetry.AppHost/Program.cs
@@ -0,0 +1,6 @@
+var builder = DistributedApplication.CreateBuilder(args);
+
+builder.AddProject("web")
+ .WithExternalHttpEndpoints();
+
+builder.Build().Run();
diff --git a/docs/fundamentals/dashboard/snippets/BrowserTelemetry/BrowserTelemetry.AppHost/Properties/launchSettings.json b/docs/fundamentals/dashboard/snippets/BrowserTelemetry/BrowserTelemetry.AppHost/Properties/launchSettings.json
new file mode 100644
index 000000000..c63a8da2d
--- /dev/null
+++ b/docs/fundamentals/dashboard/snippets/BrowserTelemetry/BrowserTelemetry.AppHost/Properties/launchSettings.json
@@ -0,0 +1,43 @@
+{
+ "$schema": "http://json.schemastore.org/launchsettings.json",
+ "profiles": {
+ "https": {
+ "commandName": "Project",
+ "dotnetRunMessages": true,
+ "launchBrowser": true,
+ "applicationUrl": "https://localhost:15887;http://localhost:15888",
+ "environmentVariables": {
+ "ASPNETCORE_ENVIRONMENT": "Development",
+ "DOTNET_ENVIRONMENT": "Development",
+ "DOTNET_DASHBOARD_OTLP_HTTP_ENDPOINT_URL": "https://localhost:16175",
+ "DOTNET_RESOURCE_SERVICE_ENDPOINT_URL": "https://localhost:17037",
+ "DOTNET_ASPIRE_SHOW_DASHBOARD_RESOURCES": "true"
+ }
+ },
+ "http": {
+ "commandName": "Project",
+ "dotnetRunMessages": true,
+ "launchBrowser": true,
+ "applicationUrl": "http://localhost:15888",
+ "environmentVariables": {
+ "ASPNETCORE_ENVIRONMENT": "Development",
+ "DOTNET_ENVIRONMENT": "Development",
+ "DOTNET_DASHBOARD_OTLP_HTTP_ENDPOINT_URL": "http://localhost:16175",
+ "DOTNET_RESOURCE_SERVICE_ENDPOINT_URL": "http://localhost:17037",
+ "DOTNET_ASPIRE_SHOW_DASHBOARD_RESOURCES": "true",
+ "ASPIRE_ALLOW_UNSECURED_TRANSPORT": "true"
+ }
+ },
+ "generate-manifest": {
+ "commandName": "Project",
+ "launchBrowser": true,
+ "dotnetRunMessages": true,
+ "commandLineArgs": "--publisher manifest --output-path aspire-manifest.json",
+ "applicationUrl": "http://localhost:15888",
+ "environmentVariables": {
+ "ASPNETCORE_ENVIRONMENT": "Development",
+ "DOTNET_ENVIRONMENT": "Development"
+ }
+ }
+ }
+}
diff --git a/docs/fundamentals/dashboard/snippets/BrowserTelemetry/BrowserTelemetry.AppHost/appsettings.Development.json b/docs/fundamentals/dashboard/snippets/BrowserTelemetry/BrowserTelemetry.AppHost/appsettings.Development.json
new file mode 100644
index 000000000..0c208ae91
--- /dev/null
+++ b/docs/fundamentals/dashboard/snippets/BrowserTelemetry/BrowserTelemetry.AppHost/appsettings.Development.json
@@ -0,0 +1,8 @@
+{
+ "Logging": {
+ "LogLevel": {
+ "Default": "Information",
+ "Microsoft.AspNetCore": "Warning"
+ }
+ }
+}
diff --git a/docs/fundamentals/dashboard/snippets/BrowserTelemetry/BrowserTelemetry.AppHost/appsettings.json b/docs/fundamentals/dashboard/snippets/BrowserTelemetry/BrowserTelemetry.AppHost/appsettings.json
new file mode 100644
index 000000000..31c092aa4
--- /dev/null
+++ b/docs/fundamentals/dashboard/snippets/BrowserTelemetry/BrowserTelemetry.AppHost/appsettings.json
@@ -0,0 +1,9 @@
+{
+ "Logging": {
+ "LogLevel": {
+ "Default": "Information",
+ "Microsoft.AspNetCore": "Warning",
+ "Aspire.Hosting.Dcp": "Warning"
+ }
+ }
+}
diff --git a/docs/fundamentals/dashboard/snippets/BrowserTelemetry/BrowserTelemetry.ServiceDefaults/BrowserTelemetry.ServiceDefaults.csproj b/docs/fundamentals/dashboard/snippets/BrowserTelemetry/BrowserTelemetry.ServiceDefaults/BrowserTelemetry.ServiceDefaults.csproj
new file mode 100644
index 000000000..eb79c9d89
--- /dev/null
+++ b/docs/fundamentals/dashboard/snippets/BrowserTelemetry/BrowserTelemetry.ServiceDefaults/BrowserTelemetry.ServiceDefaults.csproj
@@ -0,0 +1,22 @@
+
+
+
+ net8.0
+ enable
+ enable
+ true
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/docs/fundamentals/dashboard/snippets/BrowserTelemetry/BrowserTelemetry.ServiceDefaults/Extensions.cs b/docs/fundamentals/dashboard/snippets/BrowserTelemetry/BrowserTelemetry.ServiceDefaults/Extensions.cs
new file mode 100644
index 000000000..9b608dc41
--- /dev/null
+++ b/docs/fundamentals/dashboard/snippets/BrowserTelemetry/BrowserTelemetry.ServiceDefaults/Extensions.cs
@@ -0,0 +1,116 @@
+using Microsoft.AspNetCore.Builder;
+using Microsoft.AspNetCore.Diagnostics.HealthChecks;
+using Microsoft.Extensions.DependencyInjection;
+using Microsoft.Extensions.Diagnostics.HealthChecks;
+using Microsoft.Extensions.Logging;
+using OpenTelemetry;
+using OpenTelemetry.Metrics;
+using OpenTelemetry.Trace;
+
+namespace Microsoft.Extensions.Hosting;
+// Adds common .NET Aspire services: service discovery, resilience, health checks, and OpenTelemetry.
+// This project should be referenced by each service project in your solution.
+// To learn more about using this project, see https://aka.ms/dotnet/aspire/service-defaults
+public static class Extensions
+{
+ public static IHostApplicationBuilder AddServiceDefaults(this IHostApplicationBuilder builder)
+ {
+ builder.ConfigureOpenTelemetry();
+
+ builder.AddDefaultHealthChecks();
+
+ builder.Services.AddServiceDiscovery();
+
+ builder.Services.ConfigureHttpClientDefaults(http =>
+ {
+ // Turn on resilience by default
+ http.AddStandardResilienceHandler();
+
+ // Turn on service discovery by default
+ http.AddServiceDiscovery();
+ });
+
+ // Uncomment the following to restrict the allowed schemes for service discovery.
+ // builder.Services.Configure(options =>
+ // {
+ // options.AllowedSchemes = ["https"];
+ // });
+
+ return builder;
+ }
+
+ public static IHostApplicationBuilder ConfigureOpenTelemetry(this IHostApplicationBuilder builder)
+ {
+ builder.Logging.AddOpenTelemetry(logging =>
+ {
+ logging.IncludeFormattedMessage = true;
+ logging.IncludeScopes = true;
+ });
+
+ builder.Services.AddOpenTelemetry()
+ .WithMetrics(metrics =>
+ {
+ metrics.AddAspNetCoreInstrumentation()
+ .AddHttpClientInstrumentation()
+ .AddRuntimeInstrumentation();
+ })
+ .WithTracing(tracing =>
+ {
+ tracing.AddAspNetCoreInstrumentation()
+ // Uncomment the following line to enable gRPC instrumentation (requires the OpenTelemetry.Instrumentation.GrpcNetClient package)
+ //.AddGrpcClientInstrumentation()
+ .AddHttpClientInstrumentation();
+ });
+
+ builder.AddOpenTelemetryExporters();
+
+ return builder;
+ }
+
+ private static IHostApplicationBuilder AddOpenTelemetryExporters(this IHostApplicationBuilder builder)
+ {
+ var useOtlpExporter = !string.IsNullOrWhiteSpace(builder.Configuration["OTEL_EXPORTER_OTLP_ENDPOINT"]);
+
+ if (useOtlpExporter)
+ {
+ builder.Services.AddOpenTelemetry().UseOtlpExporter();
+ }
+
+ // Uncomment the following lines to enable the Azure Monitor exporter (requires the Azure.Monitor.OpenTelemetry.AspNetCore package)
+ //if (!string.IsNullOrEmpty(builder.Configuration["APPLICATIONINSIGHTS_CONNECTION_STRING"]))
+ //{
+ // builder.Services.AddOpenTelemetry()
+ // .UseAzureMonitor();
+ //}
+
+ return builder;
+ }
+
+ public static IHostApplicationBuilder AddDefaultHealthChecks(this IHostApplicationBuilder builder)
+ {
+ builder.Services.AddHealthChecks()
+ // Add a default liveness check to ensure app is responsive
+ .AddCheck("self", () => HealthCheckResult.Healthy(), ["live"]);
+
+ return builder;
+ }
+
+ public static WebApplication MapDefaultEndpoints(this WebApplication app)
+ {
+ // Adding health checks endpoints to applications in non-development environments has security implications.
+ // See https://aka.ms/dotnet/aspire/healthchecks for details before enabling these endpoints in non-development environments.
+ if (app.Environment.IsDevelopment())
+ {
+ // All health checks must pass for app to be considered ready to accept traffic after starting
+ app.MapHealthChecks("/health");
+
+ // Only health checks tagged with the "live" tag must pass for app to be considered alive
+ app.MapHealthChecks("/alive", new HealthCheckOptions
+ {
+ Predicate = r => r.Tags.Contains("live")
+ });
+ }
+
+ return app;
+ }
+}
diff --git a/docs/fundamentals/dashboard/snippets/BrowserTelemetry/BrowserTelemetry.Web/BrowserTelemetry.Web.csproj b/docs/fundamentals/dashboard/snippets/BrowserTelemetry/BrowserTelemetry.Web/BrowserTelemetry.Web.csproj
new file mode 100644
index 000000000..e2f43bf72
--- /dev/null
+++ b/docs/fundamentals/dashboard/snippets/BrowserTelemetry/BrowserTelemetry.Web/BrowserTelemetry.Web.csproj
@@ -0,0 +1,39 @@
+
+
+
+ net8.0
+ enable
+ enable
+
+ true
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/docs/fundamentals/dashboard/snippets/BrowserTelemetry/BrowserTelemetry.Web/Pages/Index.cshtml b/docs/fundamentals/dashboard/snippets/BrowserTelemetry/BrowserTelemetry.Web/Pages/Index.cshtml
new file mode 100644
index 000000000..c19b38067
--- /dev/null
+++ b/docs/fundamentals/dashboard/snippets/BrowserTelemetry/BrowserTelemetry.Web/Pages/Index.cshtml
@@ -0,0 +1,4 @@
+@page
+