Skip to content
Merged
17 changes: 17 additions & 0 deletions all.sln
Original file line number Diff line number Diff line change
Expand Up @@ -199,6 +199,12 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Dapr.AI.Microsoft.Extension
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MicrosoftAiExtensionsDemo", "examples\AI\MicrosoftAiExtensionsDemo\MicrosoftAiExtensionsDemo.csproj", "{EDEEEAED-1856-4408-BAA6-A83E1B497B2A}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Dapr.DistributedLock", "src\Dapr.DistributedLock\Dapr.DistributedLock.csproj", "{9BD12D26-AD9B-4C76-A97F-7A89B7276ABE}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "DistributedLock", "DistributedLock", "{11D2CA0F-6D38-4DC7-AE06-C1DAE7FC1C20}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DistributedLock", "examples\DistributedLock\DistributedLock\DistributedLock.csproj", "{F2DFB0FE-DF35-4D94-9CC9-43212B1D6F93}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Expand Down Expand Up @@ -527,6 +533,14 @@ Global
{EDEEEAED-1856-4408-BAA6-A83E1B497B2A}.Debug|Any CPU.Build.0 = Debug|Any CPU
{EDEEEAED-1856-4408-BAA6-A83E1B497B2A}.Release|Any CPU.ActiveCfg = Release|Any CPU
{EDEEEAED-1856-4408-BAA6-A83E1B497B2A}.Release|Any CPU.Build.0 = Release|Any CPU
{9BD12D26-AD9B-4C76-A97F-7A89B7276ABE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{9BD12D26-AD9B-4C76-A97F-7A89B7276ABE}.Debug|Any CPU.Build.0 = Debug|Any CPU
{9BD12D26-AD9B-4C76-A97F-7A89B7276ABE}.Release|Any CPU.ActiveCfg = Release|Any CPU
{9BD12D26-AD9B-4C76-A97F-7A89B7276ABE}.Release|Any CPU.Build.0 = Release|Any CPU
{F2DFB0FE-DF35-4D94-9CC9-43212B1D6F93}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{F2DFB0FE-DF35-4D94-9CC9-43212B1D6F93}.Debug|Any CPU.Build.0 = Debug|Any CPU
{F2DFB0FE-DF35-4D94-9CC9-43212B1D6F93}.Release|Any CPU.ActiveCfg = Release|Any CPU
{F2DFB0FE-DF35-4D94-9CC9-43212B1D6F93}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
Expand Down Expand Up @@ -623,6 +637,9 @@ Global
{AE9804A8-906C-4C3B-B2A8-41F4D3269C19} = {27C5D71D-0721-4221-9286-B94AB07B58CF}
{CA680984-0D3A-40E5-88FD-E2A125C6A126} = {27C5D71D-0721-4221-9286-B94AB07B58CF}
{EDEEEAED-1856-4408-BAA6-A83E1B497B2A} = {3046DBF4-C2FF-4F3A-9176-E1C01E0A90E5}
{9BD12D26-AD9B-4C76-A97F-7A89B7276ABE} = {27C5D71D-0721-4221-9286-B94AB07B58CF}
{11D2CA0F-6D38-4DC7-AE06-C1DAE7FC1C20} = {D687DDC4-66C5-4667-9E3A-FD8B78ECAA78}
{F2DFB0FE-DF35-4D94-9CC9-43212B1D6F93} = {11D2CA0F-6D38-4DC7-AE06-C1DAE7FC1C20}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {65220BF2-EAE1-4CB2-AA58-EBE80768CB40}
Expand Down
64 changes: 20 additions & 44 deletions daprdocs/content/en/dotnet-sdk-docs/_index.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,50 +39,26 @@ Put the Dapr .NET SDK to the test. Walk through the .NET quickstarts and tutoria

## Available packages

<div class="card-deck">
<div class="card">
<div class="card-body">
<h5 class="card-title"><b>Client</b></h5>
<p class="card-text">Create .NET clients that interact with a Dapr sidecar and other Dapr applications.</p>
<a href="{{% ref dotnet-client %}}" class="stretched-link"></a>
</div>
</div>
<div class="card">
<div class="card-body">
<h5 class="card-title"><b>Server</b></h5>
<p class="card-text">Write servers and services in .NET using the Dapr SDK. Includes support for ASP.NET.</p>
<a href="https://github.com/dapr/dotnet-sdk/tree/master/examples/AspNetCore" class="stretched-link"></a>
</div>
</div>
<div class="card">
<div class="card-body">
<h5 class="card-title"><b>Actors</b></h5>
<p class="card-text">Create virtual actors with state, reminders/timers, and methods in .NET.</p>
<a href="{{% ref dotnet-actors %}}" class="stretched-link"></a>
</div>
</div>
<div class="card">
<div class="card-body">
<h5 class="card-title"><b>Workflow</b></h5>
<p class="card-text">Create and manage workflows that work with other Dapr APIs in .NET.</p>
<a href="{{% ref dotnet-workflow %}}" class="stretched-link"></a>
</div>
</div>
<div class="card">
<div class="card-body">
<h5 class="card-title"><b>Jobs</b></h5>
<p class="card-text">Create and manage the scheduling and orchestration of jobs in .NET.</p>
<a href="{{% ref dotnet-jobs %}}" class="stretched-link"></a>
</div>
</div>
<div class="card">
<div class="card-body">
<h5 class="card-title"><b>AI</b></h5>
<p class="card-text">Create and manage AI operations in .NET</p>
<a href="{{% ref dotnet-ai %}}" class="stretched-link"></a>
</div>
</div>
</div>
| Package Name | Documentation Link | Description |
|-----------------------------------------------------------------------------------------------------------|---------------------------------------------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------|
| [Dapr.Client](https://www.nuget.org/packages/Dapr.Client) | [Documentation]({{% ref dotnet-client %}}) | Create .NET clients that interact with a Dapr sidecar and other Dapr applications. |
| [Dapr.AI](https://www.nuget.org/packages/Dapr.AI) | [Documentation]({{% ref dotnet-ai %}}) | Create and manage AI operations in .NET. |
| [Dapr.AI.A2a](https://www.nuget.org/packages/Dapr.AI.A2a) | | Dapr SDK for implementing agent-to-agent operations using the [A2A](https://github.com/a2aproject/a2a-dotnet) framework. |
| [Dapr.AI.Microsoft.Extensions](https://www.nuget.org/packages/Dapr.AI.Microsoft.Extensions) | [Documentation]({{% ref dotnet-ai-extensions-howto %}}) | Easily interact with LLMs conversationally and using tooling via the Dapr Conversation building block. |
| [Dapr.AspNetCore](https://www.nuget.org/packages/Dapr.AspNetCore) | [Documentation]({{% ref dotnet-server %}}) | Write servers and services in .NET using the Dapr SDK. Includes support and utilities providing richer integration with ASP.NET Core. |
| [Dapr.Actors](https://www.nuget.org/packages/Dapr.Actors) | [Documentation]({{% ref dotnet-actors %}}) | Create virtual actors with state, reminders/timers, and methods. |
| [Dapr.Actors.AspNetCore](https://www.nuget.org/packages/Dapr.Actors) | [Documentation]({{% ref dotnet-actors %}}) | Create virtual actors with state, reminders/timers, and methods with rich integration with ASP.NET Core. |
| [Dapr.Actors.Analyzers](https://www.nuget.org/packages/Dapr.Actors.Analyzers) | [Documentation]({{% ref dotnet-guidance-source-generators %}}) | A collection of Roslyn source generators and analyzers for enabling better practices and preventing common errors when using Dapr Actors in .NET |
| [Dapr.Cryptography](https://www.nuget.org/packages/Dapr.Cryptography) | [Documentation]({{% dotnet-cryptography %}}) | Encrypt and decrypt streaming state of any size using Dapr's cryptography building block. |
| [Dapr.Jobs](https://www.nuget.org/packages/Dapr.Jobs) | [Documentation]({{% ref dotnet-jobs %}}) | Create and manage the scheduling and orchestration of jobs. |
| [Dapr.DistributedLocks](https://www.nuget.org/packages/Dapr.DistributedLocks) | [Documentation]({{% ref dotnet-distributed-lock %}}) | Create and manage distributed locks for managing exclusive resource access. |
| [Dapr.Extensions.Configuration](https://www.nuget.org/packages/Dapr.Extensions.Configuration) | | Dapr secret store configuration provider implementation for `Microsoft.Extensions.Configuration`. |
| [Dapr.PluggableComponents](https://www.nuget.org/packages/Dapr.PluggableComponents) | | Used to implement pluggable components with Dapr using .NET. |
| [Dapr.PluggableComponents.AspNetCore](https://www.nuget.org/packages/Dapr.PluggableComponents.AspNetCore) | | Implement pluggable components with Dapr using .NET with rich ASP.NET Core support. |
| [Dapr.PluggableComponents.Protos](https://www.nuget.org/packages/Dapr.PluggableComponents.Protos) | | **Note:** Developers needn't install this package directly in their applications. |
| [Dapr.Messaging](https://www.nuget.org/packages/Dapr.Messaging) | [Documentation]({{% ref dotnet-messaging %}}) | Build distributed applications using the Dapr Messaging SDK that utilize messaging components like streaming pub/sub subscriptions. |
| [Dapr.Workflow](https://www.nuget.org/packages/Dapr.Workflow) | [Documentation]({{% ref dotnet-workflow %}}) | Create and manage workflows that work with other Dapr APIs. |
| [Dapr.Workflow.Analyzers](https://www.nuget.org/packages/Dapr.Workflow.Analyzers) | [Documentation]({{% ref dotnet-guidance-source-generators %}}) | A collection of Roslyn source generators and analyzers for enabling better practices and preventing common errors when using Dapr Workflows in .NET |

## More information

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ instance throughout your application. `DaprConversationClient` instances are thr

This can be aided by utilizing the dependency injection functionality. The registration method supports registration
as a singleton, a scoped instance or as transient (meaning it's recreated every time it's injected), but also enables
registration to utilize values from an `IConfiguration` or other injected service in a way that's impractical when
registration to utilize values from an `IConfiguration` or other injected services in a way that's impractical when
creating the client from scratch in each of your classes.

Avoid creating a `DaprConversationClient` for each operation.
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,143 @@
---
type: docs
title: "Dapr Distributed Lock .NET SDK"
linkTitle: "Distributed Lock"
weight: 61000
description: Get up and running with the Dapr Distributed .NET SDK
---

With the Dapr Distributed Lock package, you can create and remove locks on resources to manage exclusivity across
your distributed applications.

While this capability is implemented in both the `Dapr.Client` and `Dapr.DistributedLock` packages, the approach differs
slightly between them and a future release will see the `Dapr.Client` package be deprecated. It's recommended that new
implementations use the `Dapr.DistributedLock` package. This document will reflect the implementation in the
`Dapr.DistributedLock` package.

## Lifetime management
A `DaprDistributedLockClient` is a version of the Dapr client that is dedicated to interacting with Dapr's distributed
lock API. It can be registered alongside a `DaprClient` and other Dapr clients without issue.

It maintains access to networking resources in the form of TCP sockets used to communicate with the Dapr sidecar runtime.

For best performance, it is recommended that you utilize the dependency injection container mechanisms provided with the
`Dapr.DistributedLock` package to provide easy access to an injected instance throughout your application. These injected
instances are thread-safe and intended to be used across different types within your application. Registration via
dependency injection can utilize values from an `IConfiguration` or other injected services in a way that's impractical
when creating the client from scratch in each of your classes.

If you do opt to manually create a `DaprDistributedLockClient` instance, it is recommended that you use the `DaprClientBuilder`
to create the client. This will ensure that the client is properly configured to communicate with the Dapr sidecar runtime.`

Avoid creawting a `DaprDistributedLockClient` for each operation.

## Configuring a `DaprDistributedLockClient` via `DaprDistributedLockBuilder`

A `DaprDistributedLockClient` can be configured by invoking methods on the `DaprDistributedLockBuilder` class before calling
`.Build()` to create the client itself. The settings for each `DaprDistributedLockClient` are separate and cannot be changed
after calling `.Build()`.

```csharp
var daprDistributedLockClient = new DaprDistributedLockBuilder()
.UseDaprApiToken("abc123") // Optionally specify the API token used to authenticate to other Dapr sidecars
.Build();
```

The `DaprDistributedLockBuilder` contains settings for:

- The HTTP endpoint of the Dapr sidecar
- The gRPC endpoint of the Dapr sidecar
- The `JsonSerializerOptions` object used to configure JSON serialization
- The `GrpcChannelOptions` object used to configure gRPC
- The API token used to authenticate requests to the sidecar
- The factory method used to create the `HttpClient` instance used by the SDK
- The timeout used for the `HttpClient` instance when making requests to the sidecar

The SDK will read the following environment variables to configure the default values:

- `DAPR_HTTP_ENDPOINT`: used to find the HTTP endpoint of the Dapr sidecar, example: `https://dapr-api.mycompany.com`
- `DAPR_GRPC_ENDPOINT`: used to find the gRPC endpoint of the Dapr sidecar, example: `https://dapr-grpc-api.mycompany.com`
- `DAPR_HTTP_PORT`: if `DAPR_HTTP_ENDPOINT` is not set, this is used to find the HTTP local endpoint of the Dapr sidecar
- `DAPR_GRPC_PORT`: if `DAPR_GRPC_ENDPOINT` is not set, this is used to find the gRPC local endpoint of the Dapr sidecar
- `DAPR_API_TOKEN`: used to set the API token

### Configuring gRPC channel options

Dapr's use of `CancellationToken` for cancellation relies on the configuration of the gRPC channel options. If you need
to configure these options yourself, make sure to enable the [ThrowOperationCanceledOnCancellation setting](https://grpc.github.io/grpc/csharp-dotnet/api/Grpc.Net.Client.GrpcChannelOptions.html#Grpc_Net_Client_GrpcChannelOptions_ThrowOperationCanceledOnCancellation).

```cs
var daprDistributedLockClient = new DaprDistributedLockBuilder()
.UseGrpcChannelOptions(new GrpcChannelOptions { ... ThrowOperationCanceledOnCancellation = true })
.Build();
```

## Using cancellation with `DaprDistributedLockClient`

The APIs on `DaprDistributedLockClient` perform asynchronous operations and accept an optional `CancellationToken` parameter. This
follows a standard .NET practice for cancellable operations. Note that when cancellation occurs, there is no guarantee that
the remote endpoint stops processing the request, only that the client has stopped waiting for completion.

When an operation is cancelled, it will throw an `OperationCancelledException`.

## Configuring `DaprDistributedLockClient` via dependency injection

Using the built-in extension methods for registering the `DaprDistributedLockClient` in a dependency injection container can
provide the benefit of registering the long-lived service a single time, centralize complex configuration and improve
performance by ensuring similarly long-lived resources are re-purposed when possible (e.g. `HttpClient` instances).

There are three overloads available to give the developer the greatest flexibility in configuring the client for their
scenario. Each of these will register the `IHttpClientFactory` on your behalf if not already registered, and configure
the `DaprDistributedLockBuilder` to use it when creating the `HttpClient` instance in order to re-use the same instance as
much as possible and avoid socket exhaustion and other issues.

In the first approach, there's no configuration done by the developer and the `DaprDistributedLockClient` is configured with the
default settings.

```cs
var builder = WebApplication.CreateBuilder(args);

builder.Services.AddDaprDistributedLock(); //Registers the `DaprDistributedLockClient` to be injected as needed
var app = builder.Build();
```

Sometimes the developer will need to configure the created client using the various configuration options detailed
above. This is done through an overload that passes in the `DaprDistributedLockBuilder` and exposes methods for configuring
the necessary options.

```cs
var builder = WebApplication.CreateBuilder(args);

builder.Services.AddDaprDistributedLock((_, daprDistributedLockBuilder) => {
//Set the API token
daprDistributedLockBuilder.UseDaprApiToken("abc123");
//Specify a non-standard HTTP endpoint
daprDistributedLockBuilder.UseHttpEndpoint("http://dapr.my-company.com");
});

var app = builder.Build();
```

Finally, it's possible that the developer may need to retrieve information from another service in order to populate
these configuration values. That value may be provided from a `DaprClient` instance, a vendor-specific SDK or some
local service, but as long as it's also registered in DI, it can be injected into this configuration operation via the
last overload:

```cs
var builder = WebApplication.CreateBuilder(args);

//Register a fictional service that retrieves secrets from somewhere
builder.Services.AddSingleton<SecretService>();

builder.Services.AddDaprDistributedLock((serviceProvider, daprDistributedLockBuilder) => {
//Retrieve an instance of the `SecretService` from the service provider
var secretService = serviceProvider.GetRequiredService<SecretService>();
var daprApiToken = secretService.GetSecret("DaprApiToken").Value;

//Configure the `DaprDistributedLockBuilder`
daprDistributedLockBuilder.UseDaprApiToken(daprApiToken);
});

var app = builder.Build();
```

Loading