Client
The Dapr client package allows you to interact with other Dapr applications from a .NET application.
Note
If you haven’t already, try out one of the quickstarts for a quick walk-through on how to use the Dapr .NET SDK with an API building block.Building blocks
The .NET SDK allows you to interface with all of the Dapr building blocks.
Invoke a service
HTTP
You can either use the DaprClient
or System.Net.Http.HttpClient
to invoke your services.
Note
You can also invoke a non-Dapr endpoint using either a namedHTTPEndpoint
or an FQDN URL to the non-Dapr environment.
using var client = new DaprClientBuilder().
UseTimeout(TimeSpan.FromSeconds(2)). // Optionally, set a timeout
Build();
// Invokes a POST method named "deposit" that takes input of type "Transaction"
var data = new { id = "17", amount = 99m };
var account = await client.InvokeMethodAsync<object, Account>("routing", "deposit", data, cancellationToken);
Console.WriteLine("Returned: id:{0} | Balance:{1}", account.Id, account.Balance);
var client = DaprClient.CreateInvokeHttpClient(appId: "routing");
// To set a timeout on the HTTP client:
client.Timeout = TimeSpan.FromSeconds(2);
var deposit = new Transaction { Id = "17", Amount = 99m };
var response = await client.PostAsJsonAsync("/deposit", deposit, cancellationToken);
var account = await response.Content.ReadFromJsonAsync<Account>(cancellationToken: cancellationToken);
Console.WriteLine("Returned: id:{0} | Balance:{1}", account.Id, account.Balance);
gRPC
You can use the DaprClient
to invoke your services over gRPC.
using var cts = new CancellationTokenSource(TimeSpan.FromSeconds(20));
var invoker = DaprClient.CreateInvocationInvoker(appId: myAppId, daprEndpoint: serviceEndpoint);
var client = new MyService.MyServiceClient(invoker);
var options = new CallOptions(cancellationToken: cts.Token, deadline: DateTime.UtcNow.AddSeconds(1));
await client.MyMethodAsync(new Empty(), options);
Assert.Equal(StatusCode.DeadlineExceeded, ex.StatusCode);
- For a full guide on service invocation visit How-To: Invoke a service.
Save & get application state
var client = new DaprClientBuilder().Build();
var state = new Widget() { Size = "small", Color = "yellow", };
await client.SaveStateAsync(storeName, stateKeyName, state, cancellationToken: cancellationToken);
Console.WriteLine("Saved State!");
state = await client.GetStateAsync<Widget>(storeName, stateKeyName, cancellationToken: cancellationToken);
Console.WriteLine($"Got State: {state.Size} {state.Color}");
await client.DeleteStateAsync(storeName, stateKeyName, cancellationToken: cancellationToken);
Console.WriteLine("Deleted State!");
Query State (Alpha)
var query = "{" +
"\"filter\": {" +
"\"EQ\": { \"value.Id\": \"1\" }" +
"}," +
"\"sort\": [" +
"{" +
"\"key\": \"value.Balance\"," +
"\"order\": \"DESC\"" +
"}" +
"]" +
"}";
var client = new DaprClientBuilder().Build();
var queryResponse = await client.QueryStateAsync<Account>("querystore", query, cancellationToken: cancellationToken);
Console.WriteLine($"Got {queryResponse.Results.Count}");
foreach (var account in queryResponse.Results)
{
Console.WriteLine($"Account: {account.Data.Id} has {account.Data.Balance}");
}
- For a full list of state operations visit How-To: Get & save state.
Publish messages
var client = new DaprClientBuilder().Build();
var eventData = new { Id = "17", Amount = 10m, };
await client.PublishEventAsync(pubsubName, "deposit", eventData, cancellationToken);
Console.WriteLine("Published deposit event!");
- For a full list of state operations visit How-To: Publish & subscribe.
- Visit .NET SDK examples for code samples and instructions to try out pub/sub
Interact with output bindings
using var client = new DaprClientBuilder().Build();
// Example payload for the Twilio SendGrid binding
var email = new
{
metadata = new
{
emailTo = "customer@example.com",
subject = "An email from Dapr SendGrid binding",
},
data = "<h1>Testing Dapr Bindings</h1>This is a test.<br>Bye!",
};
await client.InvokeBindingAsync("send-email", "create", email);
- For a full guide on output bindings visit How-To: Use bindings.
Retrieve secrets
var client = new DaprClientBuilder().Build();
// Retrieve a key-value-pair-based secret - returns a Dictionary<string, string>
var secrets = await client.GetSecretAsync("mysecretstore", "key-value-pair-secret");
Console.WriteLine($"Got secret keys: {string.Join(", ", secrets.Keys)}");
var client = new DaprClientBuilder().Build();
// Retrieve a key-value-pair-based secret - returns a Dictionary<string, string>
var secrets = await client.GetSecretAsync("mysecretstore", "key-value-pair-secret");
Console.WriteLine($"Got secret keys: {string.Join(", ", secrets.Keys)}");
// Retrieve a single-valued secret - returns a Dictionary<string, string>
// containing a single value with the secret name as the key
var data = await client.GetSecretAsync("mysecretstore", "single-value-secret");
var value = data["single-value-secret"]
Console.WriteLine("Got a secret value, I'm not going to be print it, it's a secret!");
- For a full guide on secrets visit How-To: Retrieve secrets.
Get Configuration Keys
var client = new DaprClientBuilder().Build();
// Retrieve a specific set of keys.
var specificItems = await client.GetConfiguration("configstore", new List<string>() { "key1", "key2" });
Console.WriteLine($"Here are my values:\n{specificItems[0].Key} -> {specificItems[0].Value}\n{specificItems[1].Key} -> {specificItems[1].Value}");
// Retrieve all configuration items by providing an empty list.
var specificItems = await client.GetConfiguration("configstore", new List<string>());
Console.WriteLine($"I got {configItems.Count} entires!");
foreach (var item in configItems)
{
Console.WriteLine($"{item.Key} -> {item.Value}")
}
Subscribe to Configuration Keys
var client = new DaprClientBuilder().Build();
// The Subscribe Configuration API returns a wrapper around an IAsyncEnumerable<IEnumerable<ConfigurationItem>>.
// Iterate through it by accessing its Source in a foreach loop. The loop will end when the stream is severed
// or if the cancellation token is cancelled.
var subscribeConfigurationResponse = await daprClient.SubscribeConfiguration(store, keys, metadata, cts.Token);
await foreach (var items in subscribeConfigurationResponse.Source.WithCancellation(cts.Token))
{
foreach (var item in items)
{
Console.WriteLine($"{item.Key} -> {item.Value}")
}
}
Distributed lock (Alpha)
Acquire a lock
using System;
using Dapr.Client;
namespace LockService
{
class Program
{
[Obsolete("Distributed Lock API is in Alpha, this can be removed once it is stable.")]
static async Task Main(string[] args)
{
var daprLockName = "lockstore";
var fileName = "my_file_name";
var client = new DaprClientBuilder().Build();
// Locking with this approach will also unlock it automatically, as this is a disposable object
await using (var fileLock = await client.Lock(DAPR_LOCK_NAME, fileName, "random_id_abc123", 60))
{
if (fileLock.Success)
{
Console.WriteLine("Success");
}
else
{
Console.WriteLine($"Failed to lock {fileName}.");
}
}
}
}
}
Unlock an existing lock
using System;
using Dapr.Client;
namespace LockService
{
class Program
{
static async Task Main(string[] args)
{
var daprLockName = "lockstore";
var client = new DaprClientBuilder().Build();
var response = await client.Unlock(DAPR_LOCK_NAME, "my_file_name", "random_id_abc123"));
Console.WriteLine(response.status);
}
}
}
Manage workflow instances (Alpha)
var daprClient = new DaprClientBuilder().Build();
string instanceId = "MyWorkflowInstance1";
string workflowComponentName = "dapr"; // alternatively, this could be the name of a workflow component defined in yaml
string workflowName = "MyWorkflowDefinition";
var input = new { name = "Billy", age = 30 }; // Any JSON-serializable value is OK
// Start workflow
var startResponse = await daprClient.StartWorkflowAsync(instanceId, workflowComponentName, workflowName, input);
// Terminate workflow
await daprClient.TerminateWorkflowAsync(instanceId, workflowComponentName);
// Get workflow metadata
var getResponse = await daprClient.GetWorkflowAsync(instanceId, workflowComponentName, workflowName);
Sidecar APIs
Sidecar Health
The .NET SDK provides a way to poll for the sidecar health, as well as a convenience method to wait for the sidecar to be ready.
Poll for health
This health endpoint returns true when both the sidecar and your application are up (fully initialized).
var client = new DaprClientBuilder().Build();
var isDaprReady = await client.CheckHealthAsync();
if (isDaprReady)
{
// Execute Dapr dependent code.
}
Poll for health (outbound)
This health endpoint returns true when Dapr has initialized all its components, but may not have finished setting up a communication channel with your application.
This is best used when you want to utilize a Dapr component in your startup path, for instance, loading secrets from a secretstore.
var client = new DaprClientBuilder().Build();
var isDaprComponentsReady = await client.CheckOutboundHealthAsync();
if (isDaprComponentsReady)
{
// Execute Dapr component dependent code.
}
Wait for sidecar
The DaprClient
also provides a helper method to wait for the sidecar to become healthy (components only). When using this method, it is recommended to include a CancellationToken
to
allow for the request to timeout. Below is an example of how this is used in the DaprSecretStoreConfigurationProvider
.
// Wait for the Dapr sidecar to report healthy before attempting use Dapr components.
using (var tokenSource = new CancellationTokenSource(sidecarWaitTimeout))
{
await client.WaitForSidecarAsync(tokenSource.Token);
}
// Perform Dapr component operations here i.e. fetching secrets.
Shutdown the sidecar
var client = new DaprClientBuilder().Build();
await client.ShutdownSidecarAsync();
Related links
Feedback
Was this page helpful?
Glad to hear it! Please tell us how we can improve.
Sorry to hear that. Please tell us how we can improve.