# .NET SDK

RudderStack's .NET SDK lets you track your customer event data from your .NET applications and send it to your specified destinations via RudderStack.

Refer to the SDK's [GitHub codebase](https://github.com/rudderlabs/rudder-sdk-.net) for the implementation-specific details.

{{< version-badge registry="nuget" package="rudderanalytics" fallback="2.0.1" href="https://www.nuget.org/packages/RudderAnalytics/" >}}

## SDK setup requirements

- Sign up for [RudderStack](https://app.rudderstack.com/signup).
- [Set up a .NET source]({{< ref "dashboard-guides/sources.md#adding-a-source" >}}) in your dashboard. Note the {{< glossary_tooltip "write-key" >}} for this source.
- You will also need the [data plane URL]({{< ref "dashboard-guides/_index.md#connections" >}}) associated with your RudderStack workspace.

## Installing the .NET SDK

You can use [NuGet](https://docs.microsoft.com/en-us/nuget/consume-packages/install-use-packages-powershell) to install the .NET SDK into your project.

```csharp
Install-Package RudderAnalytics -Version 2.0.0
```

{{< info >}}
The SDK uses the [Newton.JSON](https://www.newtonsoft.com/json) library for JSON processing.
{{< /info >}}

## Initializing the SDK

To initialize the SDK **asynchronously** (default behavior), run the following code snippet:

```csharp
using RudderStack;

RudderAnalytics.Initialize(
    WRITE_KEY,
    new RudderConfig(dataPlaneUrl: DATA_PLANE_URL)
);
```

To send events synchronously, initialize the SDK as shown:

```csharp
using RudderStack;

RudderAnalytics.Initialize(
    WRITE_KEY,
    new RudderConfig(dataPlaneUrl: DATA_PLANE_URL, async: false)
);
```

{{< info >}}
When initialized in synchronous mode, the .NET SDK sends each event as a single batch. In asynchronous mode, it groups events together and sends them to the backend as a single batch.
{{< /info >}}


## Gzipping requests

{{< success >}}
The Gzip feature is enabled by default in the .NET SDK from version `2.0.0`
{{< /success >}}

The .NET SDK automatically gzips requests. However, you can disable this by setting the `gzip` parameter of `RudderConfig` to `false` while initializing the SDK:

```csharp
using RudderStack;
RudderAnalytics.Initialize(
    WRITE_KEY,
    new RudderConfig(dataPlaneUrl: DATA_PLANE_URL, gzip: false)
);
```

{{< warning >}}
Gzip requires [rudder-server](https://github.com/rudderlabs/rudder-server) **v1.4 or higher**. Otherwise, your events might fail.
{{< /warning >}}

## Sending events

{{< warning >}}
**RudderStack does not store or persist the user state in any of the server-side SDKs**. <br /><br />Unlike the client-side SDKs that deal with only a single user at a given time, the server-side SDKs deal with multiple users simultaneously. Therefore, you must specify either `userId` or `anonymousId` every time while making any API calls supported by the .NET SDK.
{{< /warning >}}

## Identify

The [`identify`]({{< ref "event-spec/standard-events/identify.md" >}}) call lets you identify a visiting user and associate them to their actions. It also lets you record the traits about them like their name, email address, etc.

A sample `identify` call made using the .NET SDK is shown below:

```csharp
RudderAnalytics.Client.Identify(
    "1hKOmRA4GRlm",
    new Dictionary<string, object> { {"subscription", "inactive"}, }
);
```

The `identify` method parameters are as described below:

| **Field**      | **Type** |**Description**                 |
| :------------- | :------- | :---------------------- |
| `userId` <br/> <span style="color: #4D4DFF;font-size:12px;">Required, if <strong>anonymousId</strong> is absent.</span>     | String   | Unique identifier for a user in your database.      |
| `traits`       | Object   | An optional dictionary of the user's traits like `name` or `email`.     |
| `options`   | Object   |  Object containing `anonymousId`, `integrations`, `timestamp`, and `context`. |

See the [options parameter]({{< ref "#options-parameter" >}}) section for more information on the `options` object and its fields.

## Track

The [`track`]({{< ref "event-spec/standard-events/track.md" >}}) call lets you record the user actions along with their associated properties. Each user action is called an **event**.

A sample `track` call is shown below:

```csharp
RudderAnalytics.Client.Track(
    "1hKOmRA4GRlm",
    "CTA Clicked",
    new Dictionary<string, object> {  {"plan", "premium"}, }
);
```

The `track` method parameters are as described below:

| **Field**      | **Type** |  **Description**     |
| :------------- | :------- |  :---------------- |
| `userId` <br/> <span style="color: #4D4DFF;font-size:12px;">Required, if <strong>anonymousId</strong> is absent.</span>     | String   | Unique identifier for a user in your database.      |
| `event`  <br/> <span style="color: #4D4DFF;font-size:12px;">Required</span>      | String | Name of the event.           |
| `properties`   | Object | An optional dictionary of the properties associated with the event.   |
| `options`   | Object   |  Object containing `anonymousId`, `integrations`, `timestamp`, and `context`. |

See the [options parameter]({{< ref "#options-parameter" >}}) section for more information on the `options` object and its fields.

## Page

The [`page`]({{< ref "event-spec/standard-events/page.md" >}}) call lets you record the page views on your application along with the other relevant information about the page.

A sample `page` call is as shown:

```csharp
RudderAnalytics.Client.Page(
    "1hKOmRA4GRlm",
    "Sign Up",
    new Dictionary<string, object> { {"url", "https://wwww.example.com/sign-up"}, }
);
```

The `page` method parameters are as described below:

| **Field**      | **Type** |  **Description**     |
| :------------- | :------- |  :---------------- |
| `userId` <br/> <span style="color: #4D4DFF;font-size:12px;">Required, if <strong>anonymousId</strong> is absent.</span>     | String   | Unique identifier for a user in your database.      |
| `name`  <br/> <span style="color: #4D4DFF;font-size:12px;">Required</span>      | String | Name of the viewed page.           |
| `category` | String | Category of the viewed page. |
| `properties`   | Object | An optional dictionary of the properties associated with the viewed page, like `url` or `referrer`.   |
| `options`   | Object   |  Object containing `anonymousId`, `integrations`, `timestamp`, and `context`. |

See the [options parameter]({{< ref "#options-parameter" >}}) section for more information on the `options` object and its fields.

## Screen

The [`screen`]({{< ref "event-spec/standard-events/screen.md" >}}) call is the mobile equivalent of the [`page`]({{< ref "event-spec/standard-events/page.md" >}}) call. It allows you to record the screen views on your mobile app along with the other relevant information about the app screen.

A sample `screen` call is as shown:

```csharp
RudderAnalytics.Client.Screen(
    "1hKOmRA4GRlm",
    "Dashboard",
    new Dictionary<string, object> { {"name", "Paid Dashboard"}, }
);
```

The `screen` method parameters are as described below:

| **Field**      | **Type** |  **Description**     |
| :------------- | :------- |  :---------------- |
| `userId` <br/> <span style="color: #4D4DFF;font-size:12px;">Required, if <strong>anonymousId</strong> is absent.</span>     | String   | Unique identifier for a user in your database.      |
| `name`  <br/> <span style="color: #4D4DFF;font-size:12px;">Required</span>      | String | Name of the viewed screen.           |
| `category` | String | Category of the viewed screen. |
| `properties`   | Object | An optional dictionary of the properties associated with the viewed screen, like `url` or `referrer`.   |
| `options`   | Object   |  Object containing `anonymousId`, `integrations`, `timestamp`, and `context`. |

See the [options parameter]({{< ref "#options-parameter" >}}) section for more information on the `options` object and its fields.

## Group

The [`group`]({{< ref "event-spec/standard-events/group.md" >}}) call lets you link an identified user with a group, such as a company, organization, or an account. It also lets you record any custom traits or properties associated with that group.

A sample `group` call made using the .NET SDK is shown below:

```csharp
RudderAnalytics.Client.Group(
    "1hKOmRA4GRlm",
    "12",
    new Dictionary<string, object> { {"role", "Owner"}, }
);
```

The `group` method parameters are as follows:

| **Field**      | **Type** |  **Description**     |
| :------------- | :------- |  :---------------- |
| `userId` <br/> <span style="color: #4D4DFF;font-size:12px;">Required, if <strong>anonymousId</strong> is absent.</span>     | String   | Unique identifier for a user in your database.      |
| `groupId`<br/> <span style="color: #4D4DFF;font-size:12px;">Required</span>    | String   | Unique identifier of the group in your database.    |
| `traits`       | Object   | An optional dictionary of the group's traits like `name`or `email`.     |
| `options`   | Object   |  Object containing `anonymousId`, `integrations`, `timestamp`, and `context`. |

See the [options parameter]({{< ref "#options-parameter" >}}) section for more information on the `options` object and its fields.

## Alias

The [`alias`]({{< ref "event-spec/standard-events/alias.md" >}}) call lets you merge different identities of a known user. It is an advanced method that lets you change the tracked user's ID explicitly. You can use `alias` for managing the user's identity in some of the downstream destinations.

{{< warning >}}
RudderStack supports sending `alias` events only to select downstream destinations. Refer to the [destination-specific documentation]({{< ref "destinations/streaming-destinations/" >}}) for more details.
{{< /warning >}}

A sample `alias` call is as shown:

```csharp
RudderAnalytics.Client.Alias("1hKOmRA4GRlm", "12345");
```

The `alias` method parameters are as mentioned below:

| **Field**      | **Type** |  **Description**     |
| :------------- | :------- |  :---------------- |
| `previousId` <br/> <span style="color: #4D4DFF;font-size:12px;">Required</span>  | String   | The previous unique identifier of the user.        |
| `userId`<br/> <span style="color: #4D4DFF;font-size:12px;">Required, if <strong>anonymousId</strong> is absent.</span>     | String   | Unique identifier for a user in your database.      |
| `options`   | Object   |  Object containing `anonymousId`, `integrations`, `timestamp`, and `context`. |

See the [options parameter]({{< ref "#options-parameter" >}}) section for more information on the `options` object and its fields.

## Options parameter

The `options` object contains the following fields:

| **Field**      | **Type** |  **Description**     |
| :------------- | :------- |  :---------------- |
| `anonymousId`  <br/> <span style="color: #4D4DFF;font-size:12px;">Required, if <strong>userId</strong> is absent.</span> | String   |  Use this field to set an identifier in cases where there is no unique user identifier.  |
| `integrations` | Object | An optional dictionary containing the destinations to be either enabled or disabled. |
| `timestamp`    | Timestamp in ISO 8601 format     | The timestamp of the event's arrival.                |
| `context`      | Object   |  An optional dictionary of information that provides context about the event. It is not directly related to the API call.      |

## Flushing events

To make sure no events are left in the queue, you can flush the events explicitly by using the SDK's `flush()` method.

```csharp

RudderAnalytics.Client.Flush();
```

{{< warning >}}
You cannot call the `flush()` method again until all messages are flushed from the queue.
{{< /warning >}}

## Logging

The .NET SDK supports detailed logging. You can enable this feature as shown:

```csharp
using RudderStack;

Logger.Handlers += LoggingHandler;

static void LoggingHandler(Logger.Level level, string message, IDictionary<string, object> args)
{
    if (args != null)
    {
        foreach (string key in args.Keys)
        {
            message += String.Format(" {0}: {1},", "" + key, "" + args[key]);
        }
    }
    Console.WriteLine(String.Format("[RudderAnalytics] [{0}] {1}", level, message));
}
```

{{< info >}}
The logger must be on a minimum version of .NET Core 2.1.
{{< /info >}}

## FAQ

#### How does the .NET SDK handle events larger than 32KB?

If you are running the .NET SDK [asynchronously](#initializing-the-sdk), RudderStack drops any events greater than 32KB.

For synchronous initialization, the SDK accepts and sends each event greater than 32KB as a single batch and sends them to the RudderStack data plane (backend).

#### Does the .NET SDK support event ordering?

The .NET SDK does not support event ordering by default.

<br />
