Read asset metadata

This is an example of an Action web script that reads the aggregated data of an asset, its related asset type, and its related tags. The script is designed to be executed using the Web API.

Asset metadata can be stored in both 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 make repeated calls to the web server.

Before you begin
  • Verify the required API endpoints are active and accessible for the script's logic.

  • Ensure the schema includes properties and relations referenced in the script, such as asset metadata or identifiers.

Script

RequestResponse
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

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 to be used in the script.

    RequestResponse
    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.

    RequestResponse
    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 asset Id property. The property contains the ID of the asset to get the data for. If the assetid could not be extracted from the data, return HTTP 400 status code (bad request) together with a user-friendly error message.

    RequestResponse
    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.

    RequestResponse
    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. The script then creates a new JObject that will eventually be returned as a result of the script, and then adds the values of the Title and FileName properties to the new JObject.

    RequestResponse
    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.

    RequestResponse
    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. Immediately extract the Label property from the asset type and put its value in the result.

    Note

    Label is a multi-language property, which means that you need to specify en-US to get its value in English.

    RequestResponse
    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.

    RequestResponse
    Context.Result = result;
    
  9. SetError is a helper function that 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.

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

Setup

  1. Create a script of the Action type, publish it, and enable it.

  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:

    RequestResponse
    {
     "assetId": <MY_ASSET_ID>
    }
    

Do you have some feedback for us?

If you have suggestions for improving this article,