---
id: scripting--csharp-shared-script
title: "C# shared script"
summary: "A code library for the flow: write C# classes, helpers or extension methods once and use them from every C# script (and other compiled code) in the same flow. The component has no pins and never processes messages."
audience: user
keywords: "script"
---
# C# shared script

A code library for the flow: write C# classes, helpers or extension methods once and use them from every C# script (and other compiled code) in the same flow. The component has no pins and never processes messages.

## Pins

None. Place the component anywhere on the canvas; it is not connected.

## Configuration

| Field | Type | Default | Description |
|---|---|---|---|
| `Script` | code (C#) | empty | A complete C# source file: `using` statements, namespace and one or more classes. Empty means the generated template is used. |

## Behaviour

- Unlike C# script, the code is compiled as written: nothing is wrapped around it. You write the full file.
- The template contains the usual `using` statements, the flow namespace (for example `viauser`) and an empty class `MySharedScript_<n>` marked with `[ViaScript("<componentId>")]`. Add as many classes as you like; anything public in the flow namespace can be used directly from C# scripts.
- Flow services: declare a **static** property of type `IFlowService`, either marked with `[ViaServices]` or named `Services`. After compiling, the component fills it with its flow services, so shared code can log (`Services.Log.Information(...)`) or read settings. The property is cleared when the flow stops.
- `Execute` does nothing; the component never emits data.

## Notes

- Only classes marked with this component's `[ViaScript("<componentId>")]` attribute get their `Services` property filled; keep the attribute on the class that holds it and reference it from your other classes.
- The `Services` property must be `public static`. A non-static property with that name or attribute makes the flow fail at start.
- Keep shared state thread-safe: static members are shared by all components that use them.
- The generated class name is based on the number of shared script components in the flow; if you copy a component, rename the class to avoid duplicate type names.

## Example

```csharp
using System;
using System.Linq;
using Viaducta.Plugin.Design;
using Viaducta.Plugin.Design.Scripting;

namespace viauser
{
    [ViaScript("3f1d...componentId...")]
    public class MySharedScript_1
    {
        [ViaServices]
        public static IFlowService Services { get; set; }

        public static string NormalizePhone(string phone)
        {
            var digits = new string((phone ?? "").Where(char.IsDigit).ToArray());
            Services?.Log.Verbose($"Normalized {phone} to {digits}");
            return digits;
        }
    }
}
```

Used in a C# script of the same flow: `output.Phone = MySharedScript_1.NormalizePhone(input.Phone);`
