---
id: scripting-cookbook
title: "Cookbook"
summary: "Short recipes in C#, Python and JavaScript - map a record, filter, split a list into records, read a setting, number records with a sequence, and call an HTTP API."
audience: user
keywords: "cookbook, recipes, examples, map, filter, split, sequence, settings, fetch, http"
---
# Cookbook

Short recipes for common steps. Each uses an input type `Order` and an output type `OrderDto`; replace them with your
own flow types.

## Map a record

::: code-group

```csharp [C#]
public override void Execute(IMetaData metaDataInstance, IViaType inputDataInstance)
{
    var metaData = (viauser.FlowMetaData)metaDataInstance;
    var order = (Order)inputDataInstance;
    var dto = new OrderDto { Id = order.Id, Total = order.Amount + order.Tax };
    Next(metaData, dto);
}
```

```python [Python]
def execute(metaData: FlowMetaData, inputData: Order):
    dto = OrderDto()
    dto.Id = inputData.Id
    dto.Total = inputData.Amount + inputData.Tax
    services.Next(metaData, dto)
```

```javascript [JavaScript]
async function execute(metaData, inputData) {
	const dto = new OrderDto();
	dto.Id = inputData.Id;
	dto.Total = inputData.Amount + inputData.Tax;
	services.Next(metaData, dto);
}
```

:::

## Filter records

Return without calling `Next` to drop a record.

::: code-group

```csharp [C#]
if (order.Status != "Paid") return;
Next(metaData, order);
```

```python [Python]
if inputData.Status != "Paid":
    return
services.Next(metaData, inputData)
```

```javascript [JavaScript]
if (inputData.Status !== "Paid") return;
services.Next(metaData, inputData);
```

:::

## Split a list into records

::: code-group

```csharp [C#]
foreach (var line in order.Lines)
    Next(metaData, new OrderLineDto { OrderId = order.Id, Sku = line.Sku, Quantity = line.Quantity });
```

```python [Python]
for line in inputData.Lines:
    dto = OrderLineDto()
    dto.OrderId = inputData.Id
    dto.Sku = line.Sku
    dto.Quantity = line.Quantity
    services.Next(metaData, dto)
```

```javascript [JavaScript]
for (const line of inputData.Lines) {
	const dto = new OrderLineDto();
	dto.OrderId = inputData.Id;
	dto.Sku = line.Sku;
	dto.Quantity = line.Quantity;
	services.Next(metaData, dto);
}
```

:::

When the consumer works in batches, send the lines in a [batch](./services#batches).

## Read a setting

::: code-group

```csharp [C#]
var threshold = Services.Settings.Get<decimal>("Orders", "ReviewThreshold");
if (order.Amount > threshold) Services.Log.Warning($"Order {order.Id} needs review", metaData, order);
```

```python [Python]
threshold = float(services.Settings.Get("Orders", "ReviewThreshold"))
if inputData.Amount > threshold:
    services.Log.Warning(f"Order {inputData.Id} needs review")
```

```javascript [JavaScript]
const threshold = Number(services.Settings.Get("Orders", "ReviewThreshold"));
if (inputData.Amount > threshold) services.Log.Warning(`Order ${inputData.Id} needs review`);
```

:::

## Number records

A sequence gives unique numbers that survive restarts.

::: code-group

```csharp [C#]
Services.Storage.Sequences.NewIfMissing("invoice");
dto.InvoiceNumber = $"INV-{Services.Storage.Sequences.Next("invoice"):D6}";
```

```python [Python]
services.Storage.Sequences.NewIfMissing("invoice")
dto.InvoiceNumber = f"INV-{services.Storage.Sequences.Next('invoice'):06d}"
```

```javascript [JavaScript]
services.Storage.Sequences.NewIfMissing("invoice");
dto.InvoiceNumber = "INV-" + String(services.Storage.Sequences.Next("invoice")).padStart(6, "0");
```

:::

## Call an HTTP API

For most calls the **Http client** plugin is the better choice. Inside a script:

::: code-group

```csharp [C#]
private static readonly HttpClient _http = new();

public override async Task ExecuteAsync(IMetaData metaDataInstance, IViaType inputDataInstance)
{
    var metaData = (viauser.FlowMetaData)metaDataInstance;
    var order = (Order)inputDataInstance;
    var url = Services.Settings.Get("Crm", "ApiUrl");
    var json = await _http.GetStringAsync($"{url}/customers/{order.CustomerId}", Services.CancellationToken);
    order.CustomerJson = json;
    await NextAsync(metaData, order);
}
```

```python [Python]
import urllib.request

def execute(metaData: FlowMetaData, inputData: Order):
    url = services.Settings.Get("Crm", "ApiUrl")
    with urllib.request.urlopen(f"{url}/customers/{inputData.CustomerId}") as response:
        inputData.CustomerJson = response.read().decode("utf-8")
    services.Next(metaData, inputData)
```

```javascript [JavaScript]
async function execute(metaData, inputData) {
	const url = services.Settings.Get("Crm", "ApiUrl");
	const response = await fetch(`${url}/customers/${inputData.CustomerId}`);
	if (!response.ok) throw new Error(`CRM answered ${response.status}`);
	inputData.CustomerJson = await response.text();
	services.Next(metaData, inputData);
}
```

:::

The C# version needs **Async/Await** switched on.
