For the complete documentation index, see llms.txt. This page is also available as Markdown.

.NET SDK

Learn how to set up the Harness FME .NET SDK to manage feature flags in C# and .NET backend environments.

This guide provides detailed information about our .NET SDK. All of our SDKs are open source. Go to our .NET SDK GitHub repository to learn more.

Before you begin

This SDK supports the following .NET platform versions:

  • .NET Framework 4.5 and later

  • .NET Core 2.x and 3.x

  • .NET 9 and .NET 8

RULE-BASED SEGMENTS SUPPORT

Rule-based segments are supported in SDK versions 7.11.0 and above. No changes are required to your SDK implementation, but updating to a supported version is required to ensure compatibility.

Older SDK versions will return the control treatment for flags using rule-based segments and log an impression with a special label for unsupported targeting rules.

Initialization

1. Import the SDK into your project

Use NuGet in the command line or the Package Manager UI in Visual Studio.

Install-Package Splitio -Version 7.13.0

2. Instantiate the SDK and create a new SDK factory client

When the SDK is instantiated, it starts background tasks to update an in-memory cache with small amounts of data fetched from Harness servers. This process can take up to a few hundred milliseconds depending on the size of data. If the SDK is asked to evaluate which treatment to show to a customer for a specific feature flag while its in this intermediate state, it may not have the data necessary to run the evaluation. In this case, the SDK does not fail, rather, it returns the control treatment.

To make sure the SDK is properly loaded before asking it for a treatment, block until the SDK is ready. This is done by using .BlockUntilReady(int milliseconds) method as part of the instantiation process of the SDK factory client as shown below. Do this all as a part of the startup sequence of your application. If SDK is not ready after the specified time, the SDK fails to initialize and throws a TimeoutException error.

We recommend instantiating the SDK factory once as a singleton and reusing it throughout your application.

Use the code snippet below with your own API key. Configure the SDK with the SDK key for the FME environment that you would like to access. In legacy Split (app.split.io) the SDK key is found on your Admin settings page, in the API keys section. Select a server-side SDK API key. See API keys to learn more.

Now you can start asking the SDK to evaluate treatments for your customers.

Use the SDK

Basic use

After you instantiate the SDK factory client, you can use the GetTreatment method of the SDK factory client to decide what version of your features your customers are served. The method requires the FEATURE_FLAG_NAME attribute that you want to ask for a treatment and a unique key attribute that corresponds to the end user that you are serving the feature to.

Then use an if-else-if block as shown below and insert the code for the different treatments that you defined in Harness FME. Remember the final else branch in your code to handle the client returning the control treatment.

Attribute syntax

To target based on custom attributes, the SDK's GetTreatment method needs to be passed an attribute map at runtime.

In the example below, we are rolling out a feature flag to users. The provided attributes plan_type, registered_date, permissions, paying_customer, and deal_size are passed to the GetTreatment call. These attributes are compared and evaluated against the attributes used in the Rollout plan as defined in Harness FME to decide whether to show the on or off treatment to this account.

The GetTreatment method supports five types of attributes: strings, numbers, dates, booleans, and sets. The proper data type and syntax for each are:

  • Strings: Use type String.

  • Numbers: Use type long or int.

  • Dates: Express the value for these attributes in milliseconds since epoch and as objects of class DateTime.

  • Booleans: Use type bool.

  • Sets: Use type List<string>.

Multiple evaluations at once

In some instances, you may want to evaluate treatments for multiple feature flags at once. Use the different variations of GetTreatments from the SDK factory client to do this.

  • GetTreatments: Pass a list of the feature flag names you want treatments for.

  • GetTreatmentsByFlagSet: Evaluate all flags that are part of the provided set name and are cached on the SDK instance.

  • GetTreatmentsByFlagSets: Evaluate all flags that are part of the provided set names and are cached on the SDK instance.

You can also use the Split Manager to get all of your treatments at once.

Get treatments with configurations

To leverage dynamic configurations with your treatments, you should use the GetTreatmentWithConfig method.

This method returns an object containing the treatment and associated configuration.

The config element is a stringified version of the configuration JSON defined in Harness FME. If there is no configuration defined for a treatment, the SDK returns null for the config parameter.

This method takes the exact same set of arguments as the standard GetTreatment method. See below for examples on proper usage:

If you need to get multiple evaluations at once, you can also use the GetTreatmentsWithConfig methods. These methods take the exact same arguments as the GetTreatments methods but return a mapping of feature flag names to SplitResult instead of strings. Example usage below:

If a flag cannot be evaluated, the SDK returns the fallback treatment value (default "control" unless overridden globally or per flag). For more information, see Fallback treatments.

Append properties to impressions

Impressions are generated by the SDK each time a getTreatment method is called. These impressions are periodically sent back to Harness servers for feature monitoring and experimentation.

You can append properties to an impression by passing an object of key-value pairs to the GetTreatment method. These properties are then included in the impression sent by the SDK and can provide useful context to the impression data.

Three types of properties are supported: strings, numbers, and booleans.

Shutdown

Call the .destroy() method before letting a process using the SDK exit, as this method gracefully shuts down the SDK by stopping all background threads, clearing caches, closing connections, and flushing the remaining unpublished impressions.

If a manual shutdown is required, call the client.Destroy() method.

Track

Use the track method to record any actions your customers perform. Each action is known as an event and corresponds to an event type. Calling track through one of our SDKs or via the API is the first step to and allows you to measure the impact of your feature flags on your users’ actions and metrics.

Learn more about using track events in feature flags.

In the examples below, you can see that the .track() method can take up to four arguments. The proper data type and syntax for each are:

  • key: The key variable used in the GetTreatment call and firing this track event. The expected data type is String.

  • TRAFFIC_TYPE: The traffic type of the key in the track call. The expected data type is String. You can only pass values that match the names of traffic types that you have defined in Harness FME.

  • EVENT_TYPE: The event type that this event should correspond to. The expected data type is String. Full requirements on this argument are:

    • Contains 63 characters or fewer.

    • Starts with a letter or number.

    • Contains only letters, numbers, hyphen, underscore, or period.

    • This is the regular expression we use to validate the value: [a-zA-Z0-9][-_\.a-zA-Z0-9]{0,62}

  • VALUE: (Optional) The value to be used in creating the metric. This field can be sent in as null or 0 if you intend to purely use the count function when creating a metric. The expected data type is Integer or Double.

  • PROPERTIES: (Optional) A map of key value pairs that can be used to filter your metrics. Learn more about event property capture in the Events guide. FME currently supports three types of properties: strings, numbers, and booleans.

The track method returns a boolean value of true or false to indicate whether or not the SDK can successfully queue the event to be sent back to Harness servers on the next event post. The SDK returns false if the current queue size is equal to the config set by eventsQueueSize or if an incorrect input to the track method has been provided.

In case a bad input is provided, refer to the Events guide for more information about our SDK's expected behavior.

Configuration

The SDK has a number of knobs for configuring performance. Each knob is tuned to a reasonable default. However, you can override the value while instantiating the SDK. The parameters available for configuration are shown below.

Configuration

Description

Default value

FeaturesRefreshRate

The SDK polls Harness servers for changes to feature flags at this rate (in seconds).

60 seconds

SegmentsRefreshRate

The SDK polls Harness servers for changes to segments at this rate (in seconds).

60 seconds

ImpressionsRefreshRate

The treatment log captures which customer saw what treatment (on, off, etc) at what time. This log is periodically flushed back to Harness servers. This configuration controls how quickly the cache expires after a write (in seconds).

300 seconds

MaxImpressionsLogSize

The SDK queues impressions locally before sending them to the Harness servers. This setting controls how many impressions are stored locally before sending them to the Harness servers.

30000

TelemetryRefreshRate

The SDK caches diagnostic data that it periodically sends to Harness servers. This configuration controls how frequently this data is sent back to Harness servers (in seconds).

3600 seconds

ConnectionTimeout

HTTP client connection timeout (in ms).

15000ms

ReadTimeout

HTTP socket read timeout (in ms).

15000ms

LabelsEnabled

Enable/disable labels from being sent to the Harness servers. Labels may contain sensitive information.

true

EventsFirstPushWindow

The SDK collects the events generated by the customer. This setting controls the number of seconds to wait for sending the events to the Harness servers (in seconds) after the SDK is built.

10 seconds

EventsPushRate

The SDK collects the events generated by the customer. This setting controls how frequently the events are sent to the Harness servers (in seconds) after the first push.

60 seconds

EventsQueueSize

The SDK collects the events generated by the customer. This setting controls how many events are stored locally before sending them to the Harness servers (for standalone mode only).

10000

IPAddressesEnabled

Disable machine IP and Hostname from being sent to Harness servers. IP and Hostname may contain sensitive information.

true

StreamingEnabled

Boolean flag to enable the streaming service as default synchronization mechanism. In the event of an issue with streaming, the SDK will fallback to the polling mechanism. If false, the SDK will poll for changes as usual without attempting to use streaming.

true

ImpressionsMode

Defines how impressions are queued on the SDK. Supported modes are OPTIMIZED, NONE, and DEBUG. In OPTIMIZED mode, only unique impressions are queued and posted to Harness; this is the recommended mode for experimentation use cases. In NONE mode, no impression is tracked in Harness FME and only minimum viable data to support usage stats is, so never use this mode if you are experimenting with that instance impressions. Use NONE when you want to optimize for feature flagging only use cases and reduce impressions network and storage load. In DEBUG mode, all impressions are queued and sent to Harness; this is useful for validations. Use DEBUG mode when you want every impression to be logged user interface when trying to debug your SDK setup. This setting does not impact the impression listener which receives all generated impressions locally.

Optimized

ProxyHost

The name of the proxy host.

string.empty

ProxyPort

The port number on Host to use.

0 (not set)

FlagSetsFilter

This setting allows the SDK to only synchronize the feature flags in the specified flag sets, avoiding unused or unwanted flags from being synced on the SDK instance, bringing all the benefits from a reduced payload.

null

To set each of the parameters above, use the following syntax:

Sharing state: Redis integration

Configuring this Redis integration section is optional for most setups. Read below to determine if it might be useful for your project

By default, the SDK factory client stores the state it needs to compute treatments (rollout plans, segments, and so on) in memory. As a result, it is easy to get set up with FME: instantiate a client and start using it.

This simplicity hides one important detail that is worth exploring. Because each SDK factory client downloads and stores state separately, a change in a feature flag is picked up by every client on its own schedule. If a customer issues back-to-back requests that are served by two different machines behind a load balancer, the customer can see different treatments for the same feature flag because one SDK factory client may not have picked up the latest change. This drift in clients is natural and usually ignorable as long as each client sets an aggressive value for FeaturesRefreshRate and SegmentsRefreshRate. You can learn more about setting these rates in the Configuration section below.

However, if your application requires a total guarantee that SDK clients across your entire infrastructure pick up a change in a feature flag at the exact same time, then the only way to ensure that is to externalize the state of the SDK factory client in a data store hosted on your infrastructure.

We currently support Redis for this external data store.

To use the .Net SDK with Redis, you need to set up the Split Synchronizer and instantiate the SDK in Consumer mode.

Producer

Refer to our Split Synchronizer documents and follow the steps there to get everything set to sync data to your Redis cache. After you do that, come back to set up the Consumer.

Consumer

First, import Splitio.Redis NuGet package into your project.

Use NuGet in the command line or the Package Manager UI in Visual Studio.

To initiate an SDK with support for Redis as consumer mode, use the following code snippet:

Available modes are standalone (default, for in-memory cache) and consumer (for Redis cache).

SSL support for Redis connections

This is a basic snippet to set it up

There are two more functions that you can optionally set up, for an advanced use case, that we provide to the library underneath if set:

  • If you want to be responsible for validating the certificate supplied by the remote party, you should define the CertificateValidationFunc. Doc

  • If you want to be responsible for selecting the certificate used for authentication, you should define CertificateSelectionFunc. Doc

Redis cluster support

The FME .NET SDK version 7.11.0 and above supports Redis with Cluster.

To initiate the SDK with support for Redis Cluster, use the following code snippet:

Localhost mode

For testing, a developer can put code behind feature flags on their development machine without the SDK requiring network connectivity. To achieve this, the SDK can be started in localhost mode (aka off-the-grid mode). In this mode, the SDK neither polls nor updates Harness servers. Instead, it uses an in-memory data structure to determine what treatments to show to the logged in customer for each of the feature flags.

To use the SDK in localhost mode, replace the SDK Key with "localhost", as shown in the example below:

Since version 4.1.2, our SDK supports a new type of localhost feature flag definition file, using the YAML format. This new format allows the user to map different keys to different treatments within a single feature flag, and also add configurations to them. The new format is a list of single-key maps (one per mapping feature_flag-keys-config), defined as follows:

In the example above, we have four entries:

  • The first entry defines that for feature flag my_feature, the key key returns the treatment on and the on treatment is tied to the configuration {"desc" : "this applies only to ON treatment"}.

  • The second entry defines that the feature flag some_other_feature always returns the off treatment and no configuration.

  • The third entry defines that my_feature always returns off for all keys that don't match another entry (in this case, any key other than key).

  • The fourth entry shows how an example to override a treatment for a set of keys.

Once you've defined your yaml file, you can instantiate the SDK in localhost mode as detailed below:

The SDK maintains backward compatibility by the legacy file (.split), now deprecated.

In this mode, the SDK loads a mapping of feature flag name to treatment from a file at $HOME/.split. For a given feature flag, the treatment specified in the file is returned for every customer.

GetTreatment calls for a feature flag only return the one treatment that you defined in the file. You can then change the treatment as necessary for your testing in the file. Any feature flag that is not provided in the features map returns the control treatment if the SDK is asked to evaluate them.

The format of this file is two columns separated by a whitespace. The left column is the feature flag name, and the right column is the treatment name. Here is a sample .split file.

Manager

Use the Split Manager to get a list of feature flags available to the SDK factory client.

To instantiate a Manager in your code base, use the same factory that you used for your client.

The Manager has the following methods available.

The SplitView object that you see referenced above has the following structure.

Listener

FME SDKs send impression data back to Harness servers periodically and as a result of evaluating feature flags. To additionally send this information to a location of your choice, define and attach an impression listener.

The SDK sends the generated impressions to the impression listener right away.

To create an impression listener, you need to implement an IImpressionListener interface.

Then add a configuration to attach to it.

Proxy

If you need to use a proxy, you can configure proxies by setting the environment variables HTTP_PROXY and HTTPS_PROXY. The SDK reads those variables and uses them to perform the server request. Documentation

Also you can configure proxies by setting the ProxyHost and ProxyPort properties in the SDK configuration (refer Configuration section for more information). The SDK uses those properties, with higher precedence than environment variables, to perform the server request. Documentation

Logging

SDK logging

The .NET SDK uses Common Logging for logging. It allows you to configure different adapters such as log4net or NLog, and you can also write your own adapter by implementing an ILoggerFactoryAdapter interface.

The following is an example of how to configure NLog and its adapter.

The .NET Core SDK uses Microsoft.Extensions.Logging that works well with a variety of built-in and third-party logging providers.

The following example shows how to include the SDK logs in only one line by updating your Startup class.

In the following example we use Serilog to configure text file logging. Of course you can use the tool of your preference.

Enable debug logging using Log4net library in ASP .NET Core App

The following is an example that enables debug logging using the Log4net library in the ASP .NET Core app.

Environment

log4net 2.0.12

.NET Core 3.1

To use this example, do the following:

  1. Download the project and open the project from Visual Studio.

  2. Open the SplitInitializer.cs file and replace the "SDK API KEY" text with the server-side SDK KEY.

  3. Optionally edit the log4net.config file to change the log file path, name or format.

Enable debug logging using Log4net library

The following is an example that enables debug logging using the Log4net library in .NET framework console app.

Environment

log4net 2.0.8

.NET Framework 4.8

To use this example, do the following:

  1. Download the project and open the project from Visual Studio.

  2. Open the Program.cs file and update the apikey variable with the server-side SDK KEY.

  3. Optionally edit the log4net.config file to change the log file path, name, or format.

Custom logging

To use a custom logger, implement the interface ISplitLogger which is defined as follows:

The following is an example of how config the customer logger in the SDK:

NOTE

It's the developer's responsibility to ensure that the following logger methods don't crash, and can handle logging levels if a custom logger is used.

Configure fallback treatments

Fallback treatments let you define a treatment value (and optional configuration) to be returned when a flag cannot be evaluated. By default, the SDK returns control, but you can override this globally or for individual flags at the SDK level.

This is useful when you want to:

  • Maintain a predictable user experience during outages or evaluation failures (avoid unexpected control in production)

  • Protect critical user flows by returning a safe, stable treatment (for example, forcing off during an incident)

  • Customize behavior per flag so each evaluation inherits appropriate safe defaults if something goes wrong

Global fallback treatment

Set a global fallback treatment when initializing the SDK factory. This value is returned whenever any flag cannot be evaluated.

Flag-level fallback treatment

You can set a fallback treatment per flag in the SDK options. When a flag evaluation fails, the SDK returns the corresponding fallback treatment defined for that flag. This flag-level fallback always takes precedence over the global fallback treatment, so if both are defined, the SDK will return the flag-level value when that flag cannot be evaluated.

For more information, see Fallback treatments.

Advanced use cases

This section describes advanced use cases and features provided by the SDK.

Subscribe to events

SUPPORTED SDK VERSIONS

SDK events and event metadata are supported in the .NET SDK version 7.13.0 or later.

You can listen for four different events from the SDK.

  • SDK_READY. This event fires once the SDK is ready to evaluate treatments using the most up-to-date version of your rollout plan, downloaded from Harness servers.

  • SDK_UPDATE. This event fires whenever your rollout plan is changed. Listen for this event to refresh your app whenever a feature flag or segment is changed in Harness FME.

These events provide hooks to run custom logic whenever the SDK state changes.

Include metadata

metadata provides additional context for events:

  • SDK_READY: No metadata is included.

  • SDK_UPDATE: Includes the type (SdkEventType.FlagsUpdate or SdkEventType.SegmentsUpdate) and names (list of impacted flags; empty for segment-only updates).

Troubleshooting

Which API Key to use with .NET Xamarin projects

A .NET development environment provides a Xamarin project that allows .NET code to run on both iOS and Android platforms within a container app. Which API Key should be used with the FME .NET or .NET Core SDK when developing a Xamarin project?

Use a server-side SDK API key.

Build Error: "Split 3.4.2.0 cannot be loaded since it needs a strongly-named assembly"

In a .NET project with assembly signing enabled, adding the FME .NET SDK and building the project produces this warning:

At runtime, you may get this exception:

SDK versions earlier than 3.4.4 include dependencies packaged without strong naming (unsigned assemblies). To build a signed SDK DLL, all dependencies must also be strongly named.

Upgrade to the latest version of the FME .NET SDK, which includes signed dependencies.

Last updated

Was this helpful?