Best Practices for the Dapr .NET SDK
Using Dapr .NET SDK effectively
Building with confidence
The Dapr .NET SDK offers a rich set of capabilities for building distributed applications. This section provides
practical guidance for using the SDK effectively in production scenarios—focusing on reliability, maintainability, and
developer experience.
Topics covered include:
- Error handling strategies across Dapr building blocks
- Managing experimental features and suppressing related warnings
- Leveraging source analyzers and generators to reduce boilerplate and catch issues early
- General .NET development practices in Dapr-based applications
Error model guidance
Dapr operations can fail for many reasons—network issues, misconfigured components, or transient faults. The SDK
provides structured error types to help you distinguish between retryable and fatal errors.
Learn how to use DaprException
and its derived types effectively here.
Experimental attributes
Some SDK features are marked as experimental and may change in future releases. These are annotated with
[Experimental]
and generate build-time warnings by default. You can:
- Suppress warnings selectively using
#pragma warning disable
- Use
SuppressMessage
attributes for finer control - Track experimental usage across your codebase
Learn more about our use of the [Experimenta]
attribute here.
The SDK includes Roslyn-based analyzers and source generators to help you write better code with less effort. These tools:
- Warn about common misuses of the SDK
- Generate boilerplate for actor registration and invocation
- Support IDE integration for faster feedback
Read more about how to install and use these analyzers here.
Additional guidance
This section is designed to support a wide range of development scenarios. As your applications grow in complexity, you’ll find increasingly relevant practices and patterns for working with Dapr in .NET—from actor lifecycle management to configuration strategies and performance tuning.
1 - Error Model in the Dapr .NET SDK
Learn how to use the richer error model in the .NET SDK.
The Dapr .NET SDK supports the richer error model, implemented by the Dapr runtime. This model provides a way for applications to enrich their errors with added context,
allowing consumers of the application to better understand the issue and resolve it faster. You can read more about the richer error model here, and you
can find the Dapr proto file implementing these errors here.
The Dapr .NET SDK implements all details supported by the Dapr runtime, implemented in the Dapr.Common.Exceptions
namespace, and is accessible through
the DaprException
extension method TryGetExtendedErrorInfo
. Currently, this detail extraction is only supported for
RpcException
s where the details are present.
// Example usage of ExtendedErrorInfo
try
{
// Perform some action with the Dapr client that throws a DaprException.
}
catch (DaprException daprEx)
{
if (daprEx.TryGetExtendedErrorInfo(out DaprExtendedErrorInfo errorInfo)
{
Console.WriteLine(errorInfo.Code);
Console.WriteLine(errorInfo.Message);
foreach (DaprExtendedErrorDetail detail in errorInfo.Details)
{
Console.WriteLine(detail.ErrorType);
switch (detail.ErrorType)
case ExtendedErrorType.ErrorInfo:
Console.WriteLine(detail.Reason);
Console.WriteLine(detail.Domain);
default:
Console.WriteLine(detail.TypeUrl);
}
}
}
DaprExtendedErrorInfo
Contains Code
(the status code) and Message
(the error message) associated with the error, parsed from an inner RpcException
.
Also contains a collection of DaprExtendedErrorDetails
parsed from the details in the exception.
DaprExtendedErrorDetail
All details implement the abstract DaprExtendedErrorDetail
and have an associated DaprExtendedErrorType
.
RetryInfo
DebugInfo
QuotaFailure
PreconditionFailure
RequestInfo
LocalizedMessage
BadRequest
ErrorInfo
Help
ResourceInfo
Unknown
RetryInfo
Information notifying the client how long to wait before they should retry. Provides a DaprRetryDelay
with the properties
Second
(offset in seconds) and Nano
(offset in nanoseconds).
DebugInfo
Debugging information offered by the server. Contains StackEntries
(a collection of strings containing the stack trace), and
Detail
(further debugging information).
QuotaFailure
Information relating to some quota that may have been reached, such as a daily usage limit on an API. It has one property Violations
,
a collection of DaprQuotaFailureViolation
, which each contain a Subject
(the subject of the request) and Description
(further information regarding the failure).
PreconditionFailure
Information informing the client that some required precondition was not met. Has one property Violations
, a collection of
DaprPreconditionFailureViolation
, which each has Subject
(subject where the precondition failure occured, e.g. “Azure”),
Type
(representation of the precondition type, e.g. “TermsOfService”), and Description
(further description e.g. “ToS must be accepted.”).
RequestInfo
Information returned by the server that can be used by the server to identify the client’s request. Contains
RequestId
and ServingData
properties, RequestId
being some string (such as a UID) the server can interpret,
and ServingData
being some arbitrary data that made up part of the request.
LocalizedMessage
Contains a localized message, along with the locale of the message. Contains Locale
(the locale e.g. “en-US”) and Message
(the localized message).
BadRequest
Describes a bad request field. Contains collection of DaprBadRequestDetailFieldViolation
, which each has Field
(the offending field in request, e.g. ‘first_name’) and
Description
(further information detailing the reason, e.g. “first_name cannot contain special characters”).
ErrorInfo
Details the cause of an error. Contains three properties, Reason
(the reason for the error, which should take the form of UPPER_SNAKE_CASE, e.g. DAPR_INVALID_KEY),
Domain
(domain the error belongs to, e.g. ‘dapr.io’), and Metadata
, a key/value-based collection with further information.
Help
Provides resources for the client to perform further research into the issue. Contains a collection of DaprHelpDetailLink
,
which provides Url
(a url to help or documentation), and Description
(a description of what the link provides).
ResourceInfo
Provides information relating to an accessed resource. Provides three properties ResourceType
(type of the resource being access e.g. “Azure service bus”),
ResourceName
(the name of the resource e.g. “my-configured-service-bus”), Owner
(the owner of the resource e.g. “subscriptionowner@dapr.io”),
and Description
(further information on the resource relating to the error, e.g. “missing permissions to use this resource”).
Unknown
Returned when the detail type url cannot be mapped to the correct DaprExtendedErrorDetail
implementation.
Provides one property TypeUrl
(the type url that could not be parsed, e.g. “type.googleapis.com/Google.rpc.UnrecognizedType”).
2 - Experimental Attributes
Learn about why we mark some methods with the [Experimental]
attribute
Experimental Attributes
Introduction to Experimental Attributes
With the release of .NET 8, C# 12 introduced the [Experimental]
attribute, which provides a standardized way to mark
APIs that are still in development or experimental. This attribute is defined in the System.Diagnostics.CodeAnalysis
namespace and requires a diagnostic ID parameter used to generate compiler warnings when the experimental API
is used.
In the Dapr .NET SDK, we now use the [Experimental]
attribute instead of [Obsolete]
to mark building blocks and
components that have not yet passed the stable lifecycle certification. This approach provides a clearer distinction
between:
Experimental APIs - Features that are available but still evolving and have not yet been certified as stable
according to the Dapr Component Certification Lifecycle.
Obsolete APIs - Features that are truly deprecated and will be removed in a future release.
Usage in the Dapr .NET SDK
In the Dapr .NET SDK, we apply the [Experimental]
attribute at the class level for building blocks that are still in
the Alpha or Beta stages of the Component Certification Lifecycle.
The attribute includes:
- A diagnostic ID that identifies the experimental building block
- A URL that points to the relevant documentation for that block
For example:
using System.Diagnostics.CodeAnalysis;
namespace Dapr.Cryptography.Encryption
{
[Experimental("DAPR_CRYPTOGRAPHY", UrlFormat = "https://docs.dapr.io/developing-applications/building-blocks/cryptography/cryptography-overview/")]
public class DaprEncryptionClient
{
// Implementation
}
}
The diagnostic IDs follow a naming convention of DAPR_[BUILDING_BLOCK_NAME]
, such as:
DAPR_CONVERSATION
- For the Conversation building blockDAPR_CRYPTOGRAPHY
- For the Cryptography building blockDAPR_JOBS
- For the Jobs building blockDAPR_DISTRIBUTEDLOCK
- For the Distributed Lock building block
Suppressing Experimental Warnings
When you use APIs marked with the [Experimental]
attribute, the compiler will generate errors.
To build your solution without marking your own code as experimental, you will need to suppress these errors. Here are
several approaches to do this:
Option 1: Using #pragma directive
You can use the #pragma warning
directive to suppress the warning for specific sections of code:
// Disable experimental warning
#pragma warning disable DAPR_CRYPTOGRAPHY
// Your code using the experimental API
var client = new DaprEncryptionClient();
// Re-enable the warning
#pragma warning restore DAPR_CRYPTOGRAPHY
This approach is useful when you want to suppress warnings only for specific sections of your code.
Option 2: Project-level suppression
To suppress warnings for an entire project, add the following to your .csproj
file.
file.
<PropertyGroup>
<NoWarn>$(NoWarn);DAPR_CRYPTOGRAPHY</NoWarn>
</PropertyGroup>
You can include multiple diagnostic IDs separated by semicolons:
<PropertyGroup>
<NoWarn>$(NoWarn);DAPR_CONVERSATION;DAPR_JOBS;DAPR_DISTRIBUTEDLOCK;DAPR_CRYPTOGRAPHY</NoWarn>
</PropertyGroup>
This approach is particularly useful for test projects that need to use experimental APIs.
Option 3: Directory-level suppression
For suppressing warnings across multiple projects in a directory, add a Directory.Build.props
file:
<PropertyGroup>
<NoWarn>$(NoWarn);DAPR_CONVERSATION;DAPR_JOBS;DAPR_DISTRIBUTEDLOCK;DAPR_CRYPTOGRAPHY</NoWarn>
</PropertyGroup>
This file should be placed in the root directory of your test projects. You can learn more about using
Directory.Build.props
files in the
MSBuild documentation.
Lifecycle of Experimental APIs
As building blocks move through the certification lifecycle and reach the “Stable” stage, the [Experimental]
attribute will be removed. No migration or code changes will be required from users when this happens, except for the removal of any warning suppressions if they were added.
Conversely, the [Obsolete]
attribute will now be reserved exclusively for APIs that are truly deprecated and scheduled for removal. When you see a method or class marked with [Obsolete]
, you should plan to migrate away from it according to the migration guidance provided in the attribute message.
Best Practices
In application code:
- Be cautious when using experimental APIs, as they may change in future releases
- Consider isolating usage of experimental APIs to make future updates easier
- Document your use of experimental APIs for team awareness
In test code:
- Use project-level suppression to avoid cluttering test code with warning suppressions
- Regularly review which experimental APIs you’re using and check if they’ve been stabilized
When contributing to the SDK:
- Use
[Experimental]
for new building blocks that haven’t completed certification - Use
[Obsolete]
only for truly deprecated APIs - Provide clear documentation links in the
UrlFormat
parameter
Additional Resources
3 - Dapr source code analyzers and generators
Code analyzers and fixes for common Dapr issues
Dapr supports a growing collection of optional Roslyn analyzers and code fix providers that inspect your code for
code quality issues. Starting with the release of v1.16, developers have the opportunity to install additional projects
from NuGet alongside each of the standard capability packages to enable these analyzers in their solutions.
Note
A future release of the Dapr .NET SDK will include these analyzers by default without requiring a separate package
install.Rule violations will typically be marked as Info
or Warning
so that if the analyzer identifies an issue, it won’t
necessarily break builds. All code analysis violations appear with the prefix “DAPR” and are uniquely distinguished
by a number following this prefix.
Note
At this time, the first two digits of the diagnostic identifier map one-to-one to distinct Dapr packages, but this
is subject to change in the future as more analyzers are developed.The following packages will be available via NuGet following the v1.16 Dapr release:
- Dapr.Actors.Analyzers
- Dapr.Jobs.Analyzers
- Dapr.Workflow.Analyzers
Install each NuGet package on every project where you want the analyzers to run. The package will be installed as a
project dependency and analyzers will run as you write your code or as part of a CI/CD build. The analyzers will flag
issues in your existing code and warn you about new issues as you build your project.
Many of our analyzers have associated code fixes that can be applied to automatically correct the problem. If your IDE
supports this capability, any available code fixes will show up as an inline menu option in your code.
Further, most of our analyzers should also report a specific line and column number in your code of the syntax that’s
been identified as a key aspect of the rule. If your IDE supports it, double clicking any of the analyzer warnings
should jump directly to the part of your code responsible for the violating the analyzer’s rule.
Suppress specific analyzers
If you wish to keep an analyzer from firing against some particular piece of your project, their outputs can be
individually targeted for suppression through a number of ways. Read more about suppressing analyzers in projects
or files in the associated .NET documentation.
Disable all analyzers
If you wish to disable all analyzers in your project without removing any packages providing them, set
the EnableNETAnalyzers
property to false
in your csproj file.
Available Analyzers
Diagnostic ID | Dapr Package | Category | Severity | Version Added | Description | Code Fix Available |
---|
DAPR1301 | Dapr.Workflow | Usage | Warning | 1.16 | The workflow type is not registered with the dependency injection provider | Yes |
DAPR1302 | Dapr.Workflow | Usage | Warning | 1.16 | The workflow activity type is not registered with the dependency injection provider | Yes |
DAPR1401 | Dapr.Actors | Usage | Warning | 1.16 | Actor timer method invocations require the named callback method to exist on type | No |
DAPR1402 | Dapr.Actors | Usage | Warning | 1.16 | The actor type is not registered with dependency injection | Yes |
DAPR1403 | Dapr.Actors | Interoperability | Info | 1.16 | Set options.UseJsonSerialization to true to support interoperability with non-.NET actors | Yes |
DAPR1404 | Dapr.Actors | Usage | Warning | 1.16 | Call app.MapActorsHandlers to map endpoints for Dapr actors | Yes |
DAPR1501 | Dapr.Jobs | Usage | Warning | 1.16 | Job invocations require the MapDaprScheduledJobHandler to be set and configured for each anticipated job on IEndpointRouteBuilder | No |
Analyzer Categories
The following are each of the eligible categories that an analyzer can be assigned to and are modeled after the
standard categories used by the .NET analyzers:
- Design
- Documentation
- Globalization
- Interoperability
- Maintainability
- Naming
- Performance
- Reliability
- Security
- Usage