This is the multi-page printable view of this section. Click here to print.

Return to the regular view of this page.

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.

Source tooling

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 RpcExceptions 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.

  1. RetryInfo

  2. DebugInfo

  3. QuotaFailure

  4. PreconditionFailure

  5. RequestInfo

  6. LocalizedMessage

  7. BadRequest

  8. ErrorInfo

  9. Help

  10. ResourceInfo

  11. 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:

  1. Experimental APIs - Features that are available but still evolving and have not yet been certified as stable according to the Dapr Component Certification Lifecycle.

  2. 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 block
  • DAPR_CRYPTOGRAPHY - For the Cryptography building block
  • DAPR_JOBS - For the Jobs building block
  • DAPR_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

  1. 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
  2. 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
  3. 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.

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.

Install and configure analyzers

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 IDDapr PackageCategorySeverityVersion AddedDescriptionCode Fix Available
DAPR1301Dapr.WorkflowUsageWarning1.16The workflow type is not registered with the dependency injection providerYes
DAPR1302Dapr.WorkflowUsageWarning1.16The workflow activity type is not registered with the dependency injection providerYes
DAPR1401Dapr.ActorsUsageWarning1.16Actor timer method invocations require the named callback method to exist on typeNo
DAPR1402Dapr.ActorsUsageWarning1.16The actor type is not registered with dependency injectionYes
DAPR1403Dapr.ActorsInteroperabilityInfo1.16Set options.UseJsonSerialization to true to support interoperability with non-.NET actorsYes
DAPR1404Dapr.ActorsUsageWarning1.16Call app.MapActorsHandlers to map endpoints for Dapr actorsYes
DAPR1501Dapr.JobsUsageWarning1.16Job invocations require the MapDaprScheduledJobHandler to be set and configured for each anticipated job on IEndpointRouteBuilderNo

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