---
title: C# Tutorial
slug: c-tutorial
docTags: 
createdAt: 2023-03-22T17:15:11.000Z
---

*Author(s): Dhilip Marimuthu and Ian Brown, September 2022*

:::hint{type="warning"}
<u>**Developer Prerequisites:**</u>

- mTLS Certificate, Client ID and Client Secret Keys [(tutorial)](docId\:HRo4LnNgI79gn1Ww2Y-Ma)
- Visual Studio 2022 Community Edition
- Internet connection

**Get the&#xA0;**[complete source code](docId\:LcCFPr254t0-B8pObOsK9)
:::

:::hint{type="info"}
<u>**Data Schema:**</u>


Please read the [Data Schema Fundamentals](docId\:iRzm_O_CYHCgjw5aThv1_) document before using the API. **Database CRUD operations are performed via the API** and therefore it is important to think of each HTTP REST operation (POST/GET/DELETE) as a SQL transaction (UPSERT/SELECT/DELETE).
:::

:::hint{type="info"}
<u>**WellView® and OpenWells® Source Systems:**</u>


The API uses original source system IDs as key fields. For WellView and OpenWells [data schema documentation](docId\:iRzm_O_CYHCgjw5aThv1_) provides guidance as to which table/view and which column/value to use as the source system ID. Guidance is provided for the Well Header, Wellbore and all other Wellbore related data sets

*WellView is a registered trademark of Peloton Computer Enterprises Ltd. OpenWells is a registered trademark of Halliburton Landmark.*
:::

:::hint{type="success"}
<u>**Visualizing Data:**</u>
Data inserted or modified using this tutorial can be visualized using the web portal application(s) at [https://\<tenant>.app.onxecta.com](https://\<tenant>.app.onxecta.com/). The portal contains a [Model Quality](docId\:JxHsilA0EcXIFRjb4G-l6) tool where you can see what data is in the system, the validity of the data and when the data was last modified.
:::

# 1 Project Setup

## 1.1 Project Creation

### Create New Project

Open Visual Studio 2022 Community Edition and Create a new **C# Console Application**

Provide a name for the project e.g., **ConsoleApp1**

Choose .NET framework version **NET 6.0 or higher**

::Image[]{src="https://files.readme.io/ce4bc12-image.png" size="50" isUploading="false" showCaption="false"}

::Image[]{src="https://files.readme.io/70d8ad0-image.png" size="50" isUploading="false" showCaption="false"}

## 1.2 Xecta.Platform.Data.Client

On the project Dependencies tree -> Right Click ->**&#x20;Manage NuGet Packages...** Follow the stemps below to find and install the **Xecta.Platform.Data.Client** from NuGet package manager

::Image[]{src="https://files.readme.io/8495e85-image.png" size="50" isUploading="false" showCaption="false"}

On the NuGet Window -> **Browse&#x20;**-> **Search for Xecta.Platform.DataClient -> Select latest 2.X version.**

::Image[]{src="https://files.readme.io/4345981-image.png" size="50" isUploading="false" showCaption="false"}

# 2. Connect to API

To connect to the API, you will need:

- Your PEM File
- Your KEY File
- Client ID
- Client Secret

Open the **program.cs** - Delete the default Visual Studio "Hello World" code and replace it with the code snippet below

```text
```

# 3. Well Header Data

The code snippets in section 2 build on the code snippets used in section 2. The snippets assume you have successfully built and ran the code in Section 2. To read more about Well Headers and to see all of the properties.

## 3.1 UPSERT Well Headers

Put this code directly below the below the Section 2 code snippet

```csharp
// 3. 3.1 Add a new well to the well header table 

// Create and UPSERT 2 well headers
var wells = new List<WellInput>();
wells.Add(new WellInput(
        sourceId: "DB-ID-WELL-001",
        uwi: "00123456789120",
        name: "Example Producer Well 1",
        lat: 0,
        lon: 0,
        group1: "Bakken Operations",
        group2: "Route A",
        group3: "Example Well Pad",
        fluid: WellInput.FluidEnum.OIL,
        type: WellInput.TypeEnum.PRODUCER,
        liftType: WellInput.LiftTypeEnum.NATURALFLOW
    )
);

wells.Add(new WellInput(
        sourceId: "DB-ID-WELL-002",
        uwi: "00123456789121",
        name: "Example Producer Well 2",
        lat: 0,
        lon: 0,
        group1: "Bakken Operations",
        group2: "Route A",
        group3: "Example Well Pad",
        fluid: WellInput.FluidEnum.OIL,
        type: WellInput.TypeEnum.PRODUCER,
        liftType: WellInput.LiftTypeEnum.NATURALFLOW
    )
);

// UPSERT wells
var upsertedWells =
    await client.WellHeaderApi().UpsertWellsAsync(wells);

Console.WriteLine("Added: " + wells.Count + " wells");
foreach (var well in upsertedWells)
    Console.WriteLine(well.SourceId + " | " + well.Name);

```

## 3.2 GET Well Headers

```csharp
// 3. 3.2 Get all wells from well header table
try
{
    // GET a list of well headers 
    var wellList =
        await client.WellHeaderApi().GetWellsAsync();

    Console.WriteLine("Found: " + wellList.Count + " wells");
    foreach (var wellHeader in wellList)
        Console.WriteLine(wellHeader.Name);
}
catch (Exception ex)
{
    // Most likely an authentication error
    Console.WriteLine(ex.ToString());
    Environment.Exit(1);
}
```

## 3.3 DELETE Well Header

```csharp
// 3. 3.3 Delete a well from the well header table
try
{
    // DELETE well header
    const string wellSourceSystemId = "DB-ID-WELL-002";
    await client.WellHeaderApi().DeleteWellBySourceAsync(wellSourceSystemId);
    Console.WriteLine("Deleted well: " + wellSourceSystemId);
}
catch (Exception ex)
{
    Console.WriteLine(ex.ToString());
    Environment.Exit(1);
}
```

## 3.4 DELETE Well Headers

:::hint{type="danger"}
<font color="">**The snippet below will delete all wells from the database**</font>****
*Do not use this snippet unless you have a real-world use case*
:::

```text
```

# 4. Wellbore

The code snippets below use source Ids from the wells created by the code snippets in Section 3. The snippets assume you have successfully built and ran the code in Section 3. To read more about a Wellbore and to see all of the properties.

:::hint{type="warning"}
**A well must exist in the well header table before a wellbore can be added for that well. A well must have at least one wellbore**
:::

## 4.1 UPSERT Wellbore

```text
```

## 4.2 GET Wellbores

```csharp
// 4. 4.2 - Get wellbore(s)
try
{
    const string sourceWellId = "DB-ID-WELL-001"; //<-- Required. Well ID/Primary Key from your source database
    const string sourceBoreId = "DB-ID-WELL-001-BORE-0";
    var boresForWell = await client.WellboreApi().GetWellborBySourceAsync(sourceWellId, sourceBoreId);
    Console.WriteLine("Found " + boresForWell.Name + " wellbore for well " + sourceWellId);
}
catch (Exception ex)
{
    // Most likely the Well Source system Id did not exist in well header table
    Console.WriteLine(ex.ToString());
    Environment.Exit(1);
}
```

## 4.3 DELETE Wellbore

```text
```

# 5. Wellbore Formation

A wellbore must exist before the formation data for that wellbore can be created

### Wellbore Formation Terminology

Wellbore formation represents the rock properties and the fluid properties within the reservoir (formation) where the wellbore is producing the fluids from.

## 5.1 UPSERT Wellbore Formation

```csharp
// 5. 5.1 - Create wellbore formation info 
try
{
    const string defaultWellId = "DB-ID-WELL-001";
    const string defaultBoreId = "DB-ID-WELL-001-BORE-0"; //<-- Required. Bore ID/Primary Key from your source database
    var formationProperties = new List<FormationInput>();
    formationProperties.Add(new FormationInput(

        sourceWellId: defaultWellId,
        sourceWellboreId: defaultBoreId,
        name: defaultBoreId,
        allocationFactor: 1,
        compressibilityRock: 0.000006,
        depth: 7200,
        fluidComingledGOR: 7200,
        fluidGravityApi: 38,
        fluidGravityGas: 0.78,
        fluidMolarFracCO2: 0.002,
        fluidMolarFracH2S: 0.01,
        fluidMolarFracN2: 0.002,
        fluidSalinityWater: 50000,
        porosity: 0.08,
        pressureFormationInitialDatum: 5200,
        primaryFluidType: FormationInput.PrimaryFluidTypeEnum.OIL,
        rsi: 800,
        saturationGasInitial: 0.1,
        saturationOilInitial: 0.4,
        saturationWaterInitial: 0.5,
        temperatureFormationDatum: 218,
        thicknessFormation: 180,
        volumeAcquiferInitial: 0
    ));

    // UPSERT new wellbore formation info
    await client.WellboreFormationApi().UpsertFormationsAsync(formationProperties);
    Console.WriteLine("Wellbore Formation Info Updated: " + defaultBoreId);
}
catch (Exception ex)
{
    // Most likely the wellbore Id did not exist
    Console.WriteLine(ex.ToString());
    Environment.Exit(1);
}

```

## 5.2 GET Wellbore Formation

```csharp
// 5. 5.2 - Get wellbore formation info 
try
{
    const string sourceWellId = "DB-ID-WELL-001"; //<-- Required. Well ID/Primary Key from your source database
    const string sourceBoreId = "DB-ID-WELL-001-BORE-0"; //<-- Required.  Bore ID/Primary Key from your source database
    var formationProperties = await client.WellboreFormationApi()
        .GetFormationsByWellAsync(sourceWellId);
    if (formationProperties.Count > 0)
    Console.WriteLine("Found Formation Info for : " + formationProperties[0].Name);
    else
        Console.WriteLine("No formation Info found for: " + sourceWellId);

}
catch (Exception ex)
{
    // Most likely the wellbore Id did not exist
    Console.WriteLine(ex.ToString());
}

```

## 5.3 DELETE Wellbore Formation

```csharp
// 5. 5.3 - Delete wellbore formation info 
try
{
    const string sourceWellId = "DB-ID-WELL-001"; //<-- Required. Well ID/Primary Key from your source database
    const string sourceBoreId = "DB-ID-WELL-001-BORE-0"; //<-- Required.  Bore ID/Primary Key from your source database
    await client.WellboreFormationApi().DeleteFormationBySourceWellboreAsync(sourceWellId, sourceBoreId);
    Console.WriteLine("Deleted Formation Info for : " + sourceBoreId);
}
catch (Exception ex)
{
    // Most likely the wellbore Id did not exist
    Console.WriteLine(ex.ToString());
    Environment.Exit(1);
}
```

# 6. Wellbore Deviation Surveys

A wellbore must exist before survey data points can be created for that wellbore. To read more about a Deviation Survey and to see all of the properties.&#x20;

## 6.1 UPSERT Survey

```text
```

## 6.2 GET Survey

```csharp
// 6. 6.2 - Get a deviation survey
try
{
    // GET Deviation survey
    const string sourceWellId = "DB-ID-WELL-001"; //<-- Required. Well ID/Primary Key from your source database
    const string sourceBoreId = "DB-ID-WELL-001-BORE-0"; //<-- Required. Bore ID/Primary Key from your source database
    var survey = await client.DeviationSurveyApi()
        .GetDeviationSurveyBySourceWellboreAsync(sourceWellId, sourceBoreId);
    Console.WriteLine("Found deviation survey for : " + sourceBoreId + ". Found " + survey.Count +
                      " survey points");
}
catch (Exception ex)
{
    // Most likely the wellbore Id  did not exist
    Console.WriteLine(ex.ToString());
    Environment.Exit(1);
}
```

## 6.3 DELETE Survey

```csharp
// 6. 6.3 - Delete a deviation survey
try
{
    const string sourceWellId = "DB-ID-WELL-001"; //<-- Required. Well ID/Primary Key from your source database
    const string sourceBoreId = "DB-ID-WELL-001-BORE-0"; //<-- Required. Bore ID/Primary Key from your source database
    await client.DeviationSurveyApi()
        .DeleteDeviationSurveysBySourceWellboreAsync(sourceWellId, sourceBoreId);
    Console.WriteLine("Survey Deleted for " + sourceBoreId);
}
catch (Exception ex)
{
    // Most likely the wellbore Id  did not exist
    // If you delete a wellbore
    Console.WriteLine(ex.ToString());
    Environment.Exit(1);
}
```

# 7 Wellbore Casing

A wellbore must exist before the casing information can be created for that wellbore. To read more about a casing and to see all of the properties.

## 7.1 UPSERT Casing

```csharp
// 7. 7.1 - Add casing to the wellbore
try
{
    const string sourceWellId = "DB-ID-WELL-001"; //<-- Required. Well ID/Primary Key from your source database
    const string sourceBoreId = "DB-ID-WELL-001-BORE-0"; //<-- Required. Bore ID/Primary Key from your source database
    var wellBoreCasing = new List<CasingInput>();
    for (var i = 0; i < 10; i++)
    {
        wellBoreCasing.Add(new CasingInput(
                sourceWellId: sourceWellId, //<-- Required
                sourceWellboreId: sourceBoreId, //<-- Required
                sourceId: "DB-ID-WELL-001-BORE-0-CAS-" + i, //<-- Required. Must be unique
                topMd: i, //<-- Required
                bottomMd: i + 1, //<-- Required
                od: 5, // //<-- RequiredOuter diameter of the casing
                id: 3, // //<-- RequiredInner diameter of the casing
                roughness: i, //<-- Required. Friction. Use 0 if not available
                runDate: DateTime.Today //Installation date
            )
        );
    }

    // UPSERT Casing
    Console.WriteLine("Upserting the wellbore casing for: "
                      + sourceBoreId + ". This may take a few seconds.");
    await client.WellboreCasingApi().UpsertCasingAsync(wellBoreCasing);
    Console.WriteLine("Casing created for: " + sourceBoreId);
}
catch (Exception ex)
{
    // Most likely the wellbore Id  did not exist
    Console.WriteLine(ex.ToString());
    Environment.Exit(1);
}
```

## 7.2 GET Casing

```csharp
// 7. 7.2 - Get casing for the wellbore
try
{
    // GET Casing
    const string sourceWellId = "DB-ID-WELL-001"; //<-- Required. Well ID/Primary Key from your source database
    const string sourceBoreId = "DB-ID-WELL-001-BORE-0"; //<-- Required. Bore ID/Primary Key from your source database
    var wellboreCasing = await client.WellboreCasingApi()
        .GetCasingBySourceWellboreAsync(sourceWellId, sourceBoreId);
    Console.WriteLine("Found casing for : " + sourceBoreId + ". Found " + wellboreCasing.Count + " Records");
}
catch (Exception ex)
{
    // Most likely the wellbore Id  did not exist
    Console.WriteLine(ex.ToString());
    Environment.Exit(1);
}
```

## 7.3 DELETE Casing

```text
```

# 8. Wellbore Tubing

A wellbore must exist before the tubing information can be created for that wellbore. To read more about tubing and to see all of the properties.

## 8.1. UPSERT Tubing

```csharp
// 8. 8.1 - Add tubing to the wellbore
try
{
    const string sourceWellId = "DB-ID-WELL-001"; //<-- Required. Well ID/Primary Key from your source database
    const string sourceBoreId = "DB-ID-WELL-001-BORE-0"; //<-- Required. Bore ID/Primary Key from your source database
    var wellboreTubing = new List<TubingInput>();
    for (var i = 0; i < 10; i++)
    {
        wellboreTubing.Add(new TubingInput(
                sourceWellId: sourceWellId, //<-- Required
                sourceWellboreId: sourceBoreId, //<-- Required
                sourceId: "DB-ID-WELL-001-BORE-0-TUB-" + i, //<-- Required. Must be unique for each object
                topMd: i, //<-- Required
                bottomMd: i + 1, //<-- Required
                od: 4, // //<-- Required. Outer diameter of the tubing
                id: 2, // //<-- Required. Inner diameter of the tubing
                roughness: i, //<-- Required. Friction. Use 0 if not available
                runDate: DateTime.Today //Installation date
            )
        );
    }

    // UPSERT Tubing
    Console.WriteLine("Upserting the wellbore tubing for: "
                      + sourceBoreId + ". This may take a few seconds.");
    await client.WellboreTubingApi().UpsertTubingAsync(wellboreTubing);
    Console.WriteLine("Tubing created for: " + sourceBoreId);
}
catch (Exception ex)
{
    // Most likely the wellbore Id  did not exist
    Console.WriteLine(ex.ToString());
    Environment.Exit(1);
}
```

## 8.2 GET Tubing

```text
```

## 8.3 DELETE Tubing

```text
```

# 9 Daily Production Records

To read more about daily production records and to see all of the properties.

:::hint{type="warning"}
**The daily production is related to the well. Not the wellbore. The well UWI property from the well header is used as the primary key for daily production records**


See Section 3 for well header API details
:::

## 9.1 UPSERT Production Record (single record)

```text
```

## 9.2 UPSERT Production Records (multiple records)

```text
```

## 9.3 GET Production History

:::hint{type="info"}
<u>**Get Latest Production:**</u>



To get the most recent production record you have to get the history and then use the latest record. At the time of writing there is not an end point for Get Latest record.
:::

```text
```

## 9.4 DELETE Production Record (single record)

```text
```

## 9.5 DELETE Production History (multiple records)

```text
```

# 10. Import Data from Excel

The snippet below can run standalone without the other snippets above. The code reads a standard excel template and pushes the data from the excel template to the server. An example MS Excel template file called Excel-Import-Template.xlsx can be found in the Code Samples section.

```text
```

