logo
logo

Web script example

This is an example of an Action script that reads the aggregates data of an asset, it's related asset type and it's related tags. The script is designed to be executed using the Web API.

Use case

Asset metadata can be stored both in properties and relations. The relations link associated tags and asset-types to the asset. These related entities also have metadata of their own. The script allows users to retrieve all of this data in a single Web API call, eliminating the need to do multiple round trips to the web-server.

Script

using System.Linq;
using System.Net;
using Newtonsoft.Json.Linq;
using System.Globalization;

var enUsCulture = CultureInfo.GetCultureInfo("en-US");

var data = Context.Data as JObject;
var assetId = data?["assetId"]?.Value<long>();

if (assetId == null) 
{
    SetError(HttpStatusCode.BadRequest, "No asset-id has been specified."); // Bad request 
    return;  
}

var loadConfig = new EntityLoadConfiguration(
    CultureLoadOption.Default, 
    new PropertyLoadOption("Title", "FileName"), 
    new RelationLoadOption("TagToAsset", "AssetTypeToAsset"));

var asset = await MClient.Entities.GetAsync(assetId.Value, loadConfig);

if (asset == null)
{
    SetError(HttpStatusCode.NotFound, "Asset not found.");
    return;
}

var result = new JObject(
    new JProperty("title", asset.GetPropertyValue<string>("Title")),
    new JProperty("filename", asset.GetPropertyValue<string>("FileName"))
);

var tagIds = asset.GetRelation<IChildToManyParentsRelation>("TagToAsset").Parents;

if (tagIds.Any()) 
{
    var tags = await MClient.Entities.GetManyAsync(tagIds);
    var tagNames = tags.Select(t => t.GetPropertyValue<string>("TagName"));

    if (tagNames.Any())
    {
        result["tags"] = new JArray(tagNames);
    }
}

var typeId = asset.GetRelation<IChildToOneParentRelation>("AssetTypeToAsset").Parent;

if (typeId.HasValue) 
{
    var type = await MClient.Entities.GetAsync(typeId.Value);

    if (type != null) 
    {
        result["type"] = type.GetPropertyValue<string>("Label", enUsCulture);
    }
}

Context.Result = result;

void SetError(HttpStatusCode statusCode, string message)
{
    Context.StatusCode = statusCode;
    Context.Result = new JObject(new JProperty("error", message));
}

Script explanation

  1. Include the libraries to be used in the script.

    using System.Linq;
    using System.Net;
    using Newtonsoft.Json.Linq;
    using System.Globalization;
  2. Some of the properties are multi-language. This means they can have different values in different languages. For the purpose of this example, only their values in en-US will be loaded.

    var enUsCulture = CultureInfo.GetCultureInfo("en-US");
  3. Data from the request is specified in Context.Data, which is a JToken. The script expects it to be a JObject containing an assetId property. The property contains the id of the asset to get the data for. If the asset-id could not be extracted from the data, return http status-code 400 (bad request) together with a user-friendly error-message.

    var data = Context.Data as JObject;
    var assetId = data?["assetId"]?.Value<long>();
    
    if (assetId == null) 
    {
        SetError(HttpStatusCode.BadRequest, "No asset-id has been specified."); // Bad request 
        return;  
    }
  4. Load the asset with the specified id. Only the Title and ** FileName** properties, and, the TagToAsset and AssetTypeToAsset relations are of interest. If the asset could not be found, return http status-code 404 (not found) together with a user-friendly error-message.

    var loadConfig = new EntityLoadConfiguration(
        CultureLoadOption.Default, 
        new PropertyLoadOption("Title", "FileName"), 
        new RelationLoadOption("TagToAsset", "AssetTypeToAsset"));
    
    var asset = await MClient.Entities.GetAsync(assetId.Value, loadConfig);
    
    if (asset == null)
    {
        SetError(HttpStatusCode.NotFound, "Asset not found.");
        return;
    }
  5. Create a new JObject which will eventually be returned as a result of the script. Immediately add the values of properties Title and FileName.

    var result = new JObject(
        new JProperty("title", asset.GetPropertyValue<string>("Title")),
        new JProperty("filename", asset.GetPropertyValue<string>("FileName"))
    );
  6. Load the tags associated with the asset. Immediately extract the TagName property from the tags and put them in a JArray, which in turn, is added to the result.

    var tagIds = asset.GetRelation<IChildToManyParentsRelation>("TagToAsset").Parents;
    
    if (tagIds.Any()) 
    {
        var tags = await MClient.Entities.GetManyAsync(tagIds);
        var tagNames = tags.Select(t => t.GetPropertyValue<string>("TagName"));
    
        if (tagNames.Any())
        {
            result["tags"] = new JArray(tagNames);
        }
    }
  7. Load the asset-type associated with the asset. Immediatley extract the Label property from the asset-type and put it's value in teh result.

    Note

    Label is a multi-language property. Hence, specify the en-US culture to get it's value in the English language.

    var typeId = asset.GetRelation<IChildToOneParentRelation>("AssetTypeToAsset").Parent;
    
    if (typeId.HasValue) 
    {
        var type = await MClient.Entities.GetAsync(typeId.Value);
    
        if (type != null) 
        {
            result["type"] = type.GetPropertyValue<string>("Label", enUsCulture);
        }
    }
  8. Store the result object on the Context. This tells the script to return it to the user.

    Context.Result = result;
  9. SetError is a helper function which is used to return errors from the script. It stores the specified http status-code and error-message on the Context. This tells the script to return it to the user.

    void SetError(HttpStatusCode statusCode, string message)
    {
        Context.StatusCode = statusCode;
        Context.Result = new JObject(new JProperty("error", message));
    }

Setup

  1. Create, publish and enable an Action script.

  2. Execute an HTTP POST call to the following endpoint: https://my-url/api/scripts/my-script-identifier/execute. Make sure to replace my-url and my-script-identifier with the correct values.

    Make sure the Content-Type header is set to application/json.

    Use the following template as body for the script:

    {
      "assetId": my-asset-id
    }

Can we improve this article ? Provide feedback