---
title: "Link an asset to a product"
slug: "link-an-asset-to-a-product"
abstract: "Web script example that shows how to link an asset to a product using a filename format."
---
# Link an asset to a product

This action script example links an asset to a specified product when the filename of that asset changes to `{product number}_{name}`. The action executes in the *pre-commit* phase (in-process).

> [!note]
> *Pre-commit* means that the script executes before the triggering event. In that case, the script executes before the entity is modified.

> [!note]
> **Before you begin**
> -   Ensure the schema includes entities and relations for `M.Asset` and `M.Product`.
>
> -   Verify that the asset filenames match the requirements for linking, such as formatting or naming conventions.

## Script

```csharp
using System.Linq;
using System.Threading.Tasks;

var asset = Context.Target as IEntity;
if(asset == null) return;

var filename = asset.GetPropertyValue<string>("FileName");
if(string.IsNullOrEmpty(filename)) return;

var splitFilename = filename.Split('_');
if(splitFilename.Count()  2) return;

var productNumber = splitFilename[0];
var productId = await GetProductId(productNumber);

if(productId.HasValue){
  var productRelation = asset.GetRelation("PCMProductToAsset");
  productRelation.SetIds(new long[]{ productId.Value });
  MClient.Logger.Info($"Asset {asset.Id} is linked to product {productId.Value}.");
}
else{
  MClient.Logger.Warn($"No product found with product number {productNumber}!");
}

async Task<long?> GetProductId(string productNumber)
{
  var query = Query.CreateQuery(entities =>
    from e in entities
    where e.Property("ProductNumber") == productNumber
    && e.DefinitionName =="M.PCM.Product"
    select e);
  var productId = await MClient.Querying.SingleIdAsync(query);
  MClient.Logger.Info(productId.ToString());

  return productId;
}

```

## Script explanation

This section steps through the script in execution order, explaining each part. The numbered items describe the sequence, not instructions to perform.

1. Include the [libraries](https://doc.sitecore.com/ch/en/developers/cloud-dev/script-restriction.html "Script restriction") to use in the script.

    ```csharp
    using System.Linq;
    using System.Threading.Tasks;
    ```

2. Since the action executes during pre-commit, retrieve the `Target` object from the `Context` and cast it to `IEntity`. The `Target` is the asset involved in the creation or modification event. If the asset does not exist, the script exits:

    ```csharp
    var asset = Context.Target as IEntity;
    if(asset == null) return;
    ```

3. Using the `GetPropertyValue` method, retrieve the `FileName` from the asset. If the filename is null or empty, the script exits.

    ```csharp
    var filename = asset.GetPropertyValue<string>("FileName");
    if(string.IsNullOrEmpty(filename)) return;
    ```

4. If the filename is in the specified format, split it into two parts: `{productNumber}` and `{name}`. If not, the script exits.

    ```csharp
    var splittedFilename = filename.Split('_');
    if(splittedFilename.Count()  2) return;
    ```

5. Using the `GetProductId(productnumber)` method, lazy load the `productNumber`. The `productNumber` is the number specified on the `filename`:

    ```csharp
    var productNumber = splittedFilename[0];
    var productId = await GetProductId(productNumber);
    ```

6. If the `productId` has a value, using the `SetIds` method, link the asset to the `PCMProductToAsset` relation.

    ```csharp
    if(productId.HasValue){
      var productRelation = asset.GetRelation("PCMProductToAsset");
      productRelation.SetIds(new long[]{ productId.Value });
      MClient.Logger.Info($"Asset {asset.Id} is linked to product {productId.Value}.");
    }
    else{
      MClient.Logger.Warn($"No product found for product number {productNumber}!");
    }
    ```

7. Using the `GetProductId` method, use the `productNumber` parameter to return the `productId`.

    ```csharp
    async Task<long?> GetProductId(string productNumber)
    {
      var query = Query.CreateQuery(entities =>
        from e in entities
        where e.Property("ProductNumber") == productNumber
        && e.DefinitionName =="M.PCM.Product"
        select e);
      var productId = await MClient.Querying.SingleIdAsync(query);
      MClient.Logger.Info(productId.ToString());

      return productId;
    }
    ```

## Setup

To set up your asset, script, action, and trigger:

1. [Create an asset](https://doc.sitecore.com/ch/en/users/content-hub/upload-assets.html) (or edit an existing one) with a filename formatted as: `{productnumber}_{name}`.
2. [Create a script](https://doc.sitecore.com/ch/en/developers/cloud-dev/work-with-scripts.html "Work with scripts") of the *Action* type; publish it, and enable it.
3. [Create an action](https://doc.sitecore.com/ch/en/developers/cloud-dev/create-an-action.html "Create an action") of the *Action script* type, and link it to your script.
4. [Create a trigger](https://doc.sitecore.com/ch/en/developers/cloud-dev/create-a-trigger.html "Create a trigger"):
    - On the **General** tab, set the *Objective* to *Entity creation* and *Entity modification*.
    - On the **General** tab, set the *Execution type* to *In process*.
    - On the **Conditions** tab, add a condition for the *Asset(M.Asset)* entity definition.
    - In this condition, add a new condition for the *Filename(FileName)* entity definition, and set it to *Has changed*.
    - On the **Actions** tab, add the related action under *Pre-commit actions*.
    - Save, and activate the trigger.