From 84977abb9b4d8b063a2e4534b54d613e52bf0a6b Mon Sep 17 00:00:00 2001 From: OMpawar-21 Date: Thu, 12 Feb 2026 17:41:56 +0530 Subject: [PATCH 1/2] feat: add AssetFields() to support CDA asset_fields[] parameter Add AssetFields(params string[] fields) across Entry, Query, Asset, and AssetLibrary to support the Content Delivery API (CDA) asset_fields[] query parameter. This enables requesting specific asset-related metadata (user_defined_fields, embedded, ai_suggested, visual_markups) when fetching entries or assets. Changes: - Entry: AssetFields() before Fetch (single entry). - Query: AssetFields() before Find (entries). - Asset: AssetFields() before Fetch (single asset). - AssetLibrary: AssetFields() before FetchAll (assets). Behavior: when called with one or more fields, sets asset_fields[] in the request; when called with no arguments, null, or empty array, the parameter is not set. Method returns this for chaining. Tests: - Unit tests (Contentstack.Core.Unit.Tests): 24 tests across Entry, Query, Asset, AssetLibrary (single/multiple fields, chaining, no-args/null/empty-array). - API tests (Contentstack.Core.Tests): AssetFields request success, chaining with IncludeMetadata, and scenarios mirroring unit tests (single field, no args, null, empty array) for Entry, Query, Asset, and AssetLibrary. Version: 2.26.0 (Directory.Build.props, CHANGELOG.md). --- CHANGELOG.md | 10 ++ Contentstack.Core.Tests/AssetTest.cs | 158 +++++++++++++++++- .../Contentstack.Core.Tests.csproj | 1 + Contentstack.Core.Tests/EntryTest.cs | 94 ++++++++++- Contentstack.Core.Tests/QueryTest.cs | 12 ++ .../AssetLibraryUnitTests.cs | 113 +++++++++++++ .../AssetUnitTests.cs | 113 +++++++++++++ .../Contentstack.Core.Unit.Tests.csproj | 1 + .../EntryUnitTests.cs | 116 +++++++++++++ .../QueryUnitTests.cs | 113 +++++++++++++ Contentstack.Core/Contentstack.Core.csproj | 2 +- Contentstack.Core/Models/Asset.cs | 21 +++ Contentstack.Core/Models/AssetLibrary.cs | 20 +++ Contentstack.Core/Models/Entry.cs | 20 +++ Contentstack.Core/Models/Query.cs | 21 +++ Directory.Build.props | 2 +- 16 files changed, 813 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 776e063..ab098e2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,13 @@ +### Version: 2.26.0 +#### Date: Feb-10-2026 + +##### Feat: +- CDA / DAM 2.0 – AssetFields support + - Added `AssetFields(params string[] fields)` to request specific asset-related metadata via the CDA `asset_fields[]` query parameter + - Implemented on: Entry (single entry fetch), Query (entries find), Asset (single asset fetch), AssetLibrary (assets find) + - Supported asset field values: `user_defined_fields`, `embedded`, `ai_suggested`, `visual_markups` + - Method is chainable; when called with no arguments, the query parameter is not set + ### Version: 2.25.2 #### Date: Nov-13-2025 diff --git a/Contentstack.Core.Tests/AssetTest.cs b/Contentstack.Core.Tests/AssetTest.cs index 6f779da..61a80e3 100644 --- a/Contentstack.Core.Tests/AssetTest.cs +++ b/Contentstack.Core.Tests/AssetTest.cs @@ -1,4 +1,4 @@ -using System; +using System; using Xunit; using Contentstack.Core.Models; using System.Threading.Tasks; @@ -951,5 +951,161 @@ public void Where_WithSpecialCharacters_ShouldHandleCorrectly_Test() Assert.NotNull(result); Assert.IsType(result); } + + [Fact] + public async Task AssetFields_SingleAsset_RequestSucceeds() + { + string uid = await FetchAssetUID(); + Asset asset = client.Asset(uid); + + asset.AssetFields("user_defined_fields", "embedded_metadata", "ai_generated_metadata", "visual_markups"); + Asset result = await asset.Fetch(); + + if (result == null) + Assert.Fail("Asset.Fetch with AssetFields did not return a result."); + Assert.NotNull(result.Uid); + Assert.NotEmpty(result.FileName); + } + + [Fact] + public async Task AssetFields_AssetLibrary_RequestSucceeds() + { + AssetLibrary assetLibrary = client.AssetLibrary(); + assetLibrary.AssetFields("user_defined_fields", "ai_generated_metadata"); + ContentstackCollection assets = await assetLibrary.FetchAll(); + + if (assets == null) + Assert.Fail("AssetLibrary.FetchAll with AssetFields did not return a result."); + Assert.NotNull(assets.Items); + } + + [Fact] + public async Task AssetFields_ChainedWithIncludeMetadata_RequestSucceeds() + { + string uid = await FetchAssetUID(); + Asset result = await client.Asset(uid) + .AssetFields("user_defined_fields") + .IncludeMetadata() + .Fetch(); + + if (result == null) + Assert.Fail("Asset.Fetch with AssetFields and IncludeMetadata did not return a result."); + Assert.NotNull(result.Uid); + Assert.NotEmpty(result.FileName); + } + + [Fact] + public async Task AssetFields_AssetLibrary_ChainedWithIncludeMetadata_RequestSucceeds() + { + ContentstackCollection assets = await client.AssetLibrary() + .AssetFields("user_defined_fields") + .IncludeMetadata() + .FetchAll(); + + if (assets == null) + Assert.Fail("AssetLibrary.FetchAll with AssetFields and IncludeMetadata did not return a result."); + Assert.NotNull(assets.Items); + } + + [Fact] + public async Task AssetFields_SingleField_RequestSucceeds() + { + string uid = await FetchAssetUID(); + Asset asset = client.Asset(uid); + asset.AssetFields("user_defined_fields"); + Asset result = await asset.Fetch(); + + if (result == null) + Assert.Fail("Asset.Fetch with AssetFields single field did not return a result."); + Assert.NotNull(result.Uid); + Assert.NotEmpty(result.FileName); + } + + [Fact] + public async Task AssetFields_AssetLibrary_SingleField_RequestSucceeds() + { + AssetLibrary assetLibrary = client.AssetLibrary(); + assetLibrary.AssetFields("user_defined_fields"); + ContentstackCollection assets = await assetLibrary.FetchAll(); + + if (assets == null) + Assert.Fail("AssetLibrary.FetchAll with AssetFields single field did not return a result."); + Assert.NotNull(assets.Items); + } + + [Fact] + public async Task AssetFields_WithNoArguments_RequestSucceeds() + { + string uid = await FetchAssetUID(); + Asset asset = client.Asset(uid); + asset.AssetFields(); + Asset result = await asset.Fetch(); + + if (result == null) + Assert.Fail("Asset.Fetch with AssetFields() no arguments did not return a result."); + Assert.NotNull(result.Uid); + } + + [Fact] + public async Task AssetFields_AssetLibrary_WithNoArguments_RequestSucceeds() + { + AssetLibrary assetLibrary = client.AssetLibrary(); + assetLibrary.AssetFields(); + ContentstackCollection assets = await assetLibrary.FetchAll(); + + if (assets == null) + Assert.Fail("AssetLibrary.FetchAll with AssetFields() no arguments did not return a result."); + Assert.NotNull(assets.Items); + } + + [Fact] + public async Task AssetFields_WithNull_RequestSucceeds() + { + string uid = await FetchAssetUID(); + Asset asset = client.Asset(uid); + asset.AssetFields(null); + Asset result = await asset.Fetch(); + + if (result == null) + Assert.Fail("Asset.Fetch with AssetFields(null) did not return a result."); + Assert.NotNull(result.Uid); + } + + [Fact] + public async Task AssetFields_WithEmptyArray_RequestSucceeds() + { + string uid = await FetchAssetUID(); + Asset asset = client.Asset(uid); + asset.AssetFields(new string[0]); + Asset result = await asset.Fetch(); + + if (result == null) + Assert.Fail("Asset.Fetch with AssetFields(empty array) did not return a result."); + Assert.NotNull(result.Uid); + } + + [Fact] + public async Task AssetFields_AssetLibrary_WithNull_RequestSucceeds() + { + AssetLibrary assetLibrary = client.AssetLibrary(); + assetLibrary.AssetFields(null); + ContentstackCollection assets = await assetLibrary.FetchAll(); + + if (assets == null) + Assert.Fail("AssetLibrary.FetchAll with AssetFields(null) did not return a result."); + Assert.NotNull(assets.Items); + } + + [Fact] + public async Task AssetFields_AssetLibrary_WithEmptyArray_RequestSucceeds() + { + AssetLibrary assetLibrary = client.AssetLibrary(); + assetLibrary.AssetFields(new string[0]); + ContentstackCollection assets = await assetLibrary.FetchAll(); + + if (assets == null) + Assert.Fail("AssetLibrary.FetchAll with AssetFields(empty array) did not return a result."); + Assert.NotNull(assets.Items); + } } } \ No newline at end of file diff --git a/Contentstack.Core.Tests/Contentstack.Core.Tests.csproj b/Contentstack.Core.Tests/Contentstack.Core.Tests.csproj index c40482e..1a3233c 100644 --- a/Contentstack.Core.Tests/Contentstack.Core.Tests.csproj +++ b/Contentstack.Core.Tests/Contentstack.Core.Tests.csproj @@ -28,6 +28,7 @@ + diff --git a/Contentstack.Core.Tests/EntryTest.cs b/Contentstack.Core.Tests/EntryTest.cs index 73fc79a..0e7f554 100644 --- a/Contentstack.Core.Tests/EntryTest.cs +++ b/Contentstack.Core.Tests/EntryTest.cs @@ -1,4 +1,4 @@ -using System; +using System; using Xunit; using Contentstack.Core.Models; using System.Threading.Tasks; @@ -457,5 +457,97 @@ public async Task GetMetadata() Assert.True(true, "GetMetadata() returns a valid dictionary (may be empty)"); } } + + [Fact] + public async Task AssetFields_SingleEntry_RequestSucceeds() + { + ContentType contenttype = client.ContentType(source); + string uid = await GetUID("source1"); + Entry sourceEntry = contenttype.Entry(uid); + + sourceEntry.AssetFields("user_defined_fields", "visual_markups"); + var result = await sourceEntry.Fetch(); + + if (result == null) + Assert.Fail("Entry.Fetch with AssetFields did not return a result."); + Assert.NotNull(result.Uid); + } + + [Fact] + public async Task AssetFields_ChainedWithIncludeMetadata_RequestSucceeds() + { + ContentType contenttype = client.ContentType(source); + string uid = await GetUID("source1"); + Entry sourceEntry = contenttype.Entry(uid); + + var result = await sourceEntry + .AssetFields("user_defined_fields") + .IncludeMetadata() + .Fetch(); + + if (result == null) + Assert.Fail("Entry.Fetch with AssetFields and IncludeMetadata did not return a result."); + Assert.NotNull(result.Uid); + } + + [Fact] + public async Task AssetFields_SingleField_RequestSucceeds() + { + ContentType contenttype = client.ContentType(source); + string uid = await GetUID("source1"); + Entry sourceEntry = contenttype.Entry(uid); + + sourceEntry.AssetFields("user_defined_fields"); + var result = await sourceEntry.Fetch(); + + if (result == null) + Assert.Fail("Entry.Fetch with AssetFields single field did not return a result."); + Assert.NotNull(result.Uid); + } + + [Fact] + public async Task AssetFields_WithNoArguments_RequestSucceeds() + { + ContentType contenttype = client.ContentType(source); + string uid = await GetUID("source1"); + Entry sourceEntry = contenttype.Entry(uid); + + sourceEntry.AssetFields(); + var result = await sourceEntry.Fetch(); + + if (result == null) + Assert.Fail("Entry.Fetch with AssetFields() no arguments did not return a result."); + Assert.NotNull(result.Uid); + } + + [Fact] + public async Task AssetFields_WithNull_RequestSucceeds() + { + ContentType contenttype = client.ContentType(source); + string uid = await GetUID("source1"); + Entry sourceEntry = contenttype.Entry(uid); + + sourceEntry.AssetFields(null); + var result = await sourceEntry.Fetch(); + + if (result == null) + Assert.Fail("Entry.Fetch with AssetFields(null) did not return a result."); + Assert.NotNull(result.Uid); + } + + [Fact] + public async Task AssetFields_WithEmptyArray_RequestSucceeds() + { + ContentType contenttype = client.ContentType(source); + string uid = await GetUID("source1"); + Entry sourceEntry = contenttype.Entry(uid); + + sourceEntry.AssetFields(new string[0]); + var result = await sourceEntry.Fetch(); + + if (result == null) + Assert.Fail("Entry.Fetch with AssetFields(empty array) did not return a result."); + Assert.NotNull(result.Uid); + } } } diff --git a/Contentstack.Core.Tests/QueryTest.cs b/Contentstack.Core.Tests/QueryTest.cs index b677546..76b87a1 100644 --- a/Contentstack.Core.Tests/QueryTest.cs +++ b/Contentstack.Core.Tests/QueryTest.cs @@ -1619,6 +1619,18 @@ public async Task IncludeSchema() // The exact assertion depends on your data structure } } + + [Fact] + public async Task AssetFieldsQueryEntriesRequestSucceeds() + { + Query query = client.ContentType(source).Query(); + query.AssetFields("user_defined_fields", "visual_markups"); + var result = await query.Find(); + + if (result == null) + Assert.Fail("Query.Find with AssetFields did not return a result."); + Assert.NotNull(result.Items); + } } } diff --git a/Contentstack.Core.Unit.Tests/AssetLibraryUnitTests.cs b/Contentstack.Core.Unit.Tests/AssetLibraryUnitTests.cs index 1797d2b..9695e6d 100644 --- a/Contentstack.Core.Unit.Tests/AssetLibraryUnitTests.cs +++ b/Contentstack.Core.Unit.Tests/AssetLibraryUnitTests.cs @@ -171,6 +171,119 @@ public void IncludeMetadata_AddsQueryParameter() #endregion + #region AssetFields Tests + + [Fact] + public void AssetFields_WithSingleField_AddsQueryParameter() + { + // Arrange + var assetLibrary = CreateAssetLibrary(); + var field = "user_defined_fields"; + + // Act + AssetLibrary result = assetLibrary.AssetFields(field); + + // Assert + Assert.NotNull(result); + Assert.Equal(assetLibrary, result); + + var urlQueriesField = typeof(AssetLibrary).GetField("UrlQueries", + BindingFlags.NonPublic | BindingFlags.Instance); + var urlQueries = (Dictionary)urlQueriesField?.GetValue(assetLibrary); + + Assert.True(urlQueries?.ContainsKey("asset_fields[]") ?? false); + var fields = urlQueries?["asset_fields[]"] as string[]; + Assert.NotNull(fields); + Assert.Single(fields); + Assert.Equal("user_defined_fields", fields[0]); + } + + [Fact] + public void AssetFields_WithMultipleFields_AddsQueryParameter() + { + // Arrange + var assetLibrary = CreateAssetLibrary(); + var fields = new[] { "user_defined_fields", "embedded", "ai_suggested" }; + + // Act + AssetLibrary result = assetLibrary.AssetFields(fields); + + // Assert + Assert.NotNull(result); + Assert.Equal(assetLibrary, result); + + var urlQueriesField = typeof(AssetLibrary).GetField("UrlQueries", + BindingFlags.NonPublic | BindingFlags.Instance); + var urlQueries = (Dictionary)urlQueriesField?.GetValue(assetLibrary); + + Assert.True(urlQueries?.ContainsKey("asset_fields[]") ?? false); + Assert.Equal(fields, urlQueries?["asset_fields[]"]); + } + + [Fact] + public void AssetFields_ReturnsSameInstance_ForChaining() + { + // Arrange + var assetLibrary = CreateAssetLibrary(); + + // Act + AssetLibrary result = assetLibrary.AssetFields("embedded"); + + // Assert + Assert.NotNull(result); + Assert.Same(assetLibrary, result); + } + + [Fact] + public void AssetFields_WithNoArguments_DoesNotAddParameter() + { + // Arrange + var assetLibrary = CreateAssetLibrary(); + + // Act + AssetLibrary result = assetLibrary.AssetFields(); + + // Assert + var urlQueriesField = typeof(AssetLibrary).GetField("UrlQueries", + BindingFlags.NonPublic | BindingFlags.Instance); + var urlQueries = (Dictionary)urlQueriesField?.GetValue(assetLibrary); + Assert.False(urlQueries?.ContainsKey("asset_fields[]") ?? false); + } + + [Fact] + public void AssetFields_WithNull_DoesNotAddParameter() + { + // Arrange + var assetLibrary = CreateAssetLibrary(); + + // Act + AssetLibrary result = assetLibrary.AssetFields(null); + + // Assert + var urlQueriesField = typeof(AssetLibrary).GetField("UrlQueries", + BindingFlags.NonPublic | BindingFlags.Instance); + var urlQueries = (Dictionary)urlQueriesField?.GetValue(assetLibrary); + Assert.False(urlQueries?.ContainsKey("asset_fields[]") ?? false); + } + + [Fact] + public void AssetFields_WithEmptyArray_DoesNotAddParameter() + { + // Arrange + var assetLibrary = CreateAssetLibrary(); + + // Act + AssetLibrary result = assetLibrary.AssetFields(new string[0]); + + // Assert + var urlQueriesField = typeof(AssetLibrary).GetField("UrlQueries", + BindingFlags.NonPublic | BindingFlags.Instance); + var urlQueries = (Dictionary)urlQueriesField?.GetValue(assetLibrary); + Assert.False(urlQueries?.ContainsKey("asset_fields[]") ?? false); + } + + #endregion + #region IncludeBranch Tests [Fact] diff --git a/Contentstack.Core.Unit.Tests/AssetUnitTests.cs b/Contentstack.Core.Unit.Tests/AssetUnitTests.cs index f560c83..10c30e0 100644 --- a/Contentstack.Core.Unit.Tests/AssetUnitTests.cs +++ b/Contentstack.Core.Unit.Tests/AssetUnitTests.cs @@ -368,6 +368,119 @@ public void IncludeMetadata_AddsQueryParameter() #endregion + #region AssetFields Tests + + [Fact] + public void AssetFields_WithSingleField_AddsQueryParameter() + { + // Arrange + var asset = CreateAsset(); + var field = "user_defined_fields"; + + // Act + Asset result = asset.AssetFields(field); + + // Assert + Assert.NotNull(result); + Assert.Equal(asset, result); + + var urlQueriesField = typeof(Asset).GetField("UrlQueries", + BindingFlags.NonPublic | BindingFlags.Instance); + var urlQueries = (Dictionary)urlQueriesField?.GetValue(asset); + + Assert.True(urlQueries?.ContainsKey("asset_fields[]") ?? false); + var fields = urlQueries?["asset_fields[]"] as string[]; + Assert.NotNull(fields); + Assert.Single(fields); + Assert.Equal("user_defined_fields", fields[0]); + } + + [Fact] + public void AssetFields_WithMultipleFields_AddsQueryParameter() + { + // Arrange + var asset = CreateAsset(); + var fields = new[] { "embedded", "visual_markups" }; + + // Act + Asset result = asset.AssetFields(fields); + + // Assert + Assert.NotNull(result); + Assert.Equal(asset, result); + + var urlQueriesField = typeof(Asset).GetField("UrlQueries", + BindingFlags.NonPublic | BindingFlags.Instance); + var urlQueries = (Dictionary)urlQueriesField?.GetValue(asset); + + Assert.True(urlQueries?.ContainsKey("asset_fields[]") ?? false); + Assert.Equal(fields, urlQueries?["asset_fields[]"]); + } + + [Fact] + public void AssetFields_ReturnsSameInstance_ForChaining() + { + // Arrange + var asset = CreateAsset(); + + // Act + Asset result = asset.AssetFields("ai_suggested"); + + // Assert + Assert.NotNull(result); + Assert.Same(asset, result); + } + + [Fact] + public void AssetFields_WithNoArguments_DoesNotAddParameter() + { + // Arrange + var asset = CreateAsset(); + + // Act + Asset result = asset.AssetFields(); + + // Assert + var urlQueriesField = typeof(Asset).GetField("UrlQueries", + BindingFlags.NonPublic | BindingFlags.Instance); + var urlQueries = (Dictionary)urlQueriesField?.GetValue(asset); + Assert.False(urlQueries?.ContainsKey("asset_fields[]") ?? false); + } + + [Fact] + public void AssetFields_WithNull_DoesNotAddParameter() + { + // Arrange + var asset = CreateAsset(); + + // Act + Asset result = asset.AssetFields(null); + + // Assert + var urlQueriesField = typeof(Asset).GetField("UrlQueries", + BindingFlags.NonPublic | BindingFlags.Instance); + var urlQueries = (Dictionary)urlQueriesField?.GetValue(asset); + Assert.False(urlQueries?.ContainsKey("asset_fields[]") ?? false); + } + + [Fact] + public void AssetFields_WithEmptyArray_DoesNotAddParameter() + { + // Arrange + var asset = CreateAsset(); + + // Act + Asset result = asset.AssetFields(new string[0]); + + // Assert + var urlQueriesField = typeof(Asset).GetField("UrlQueries", + BindingFlags.NonPublic | BindingFlags.Instance); + var urlQueries = (Dictionary)urlQueriesField?.GetValue(asset); + Assert.False(urlQueries?.ContainsKey("asset_fields[]") ?? false); + } + + #endregion + #region IncludeBranch Tests [Fact] diff --git a/Contentstack.Core.Unit.Tests/Contentstack.Core.Unit.Tests.csproj b/Contentstack.Core.Unit.Tests/Contentstack.Core.Unit.Tests.csproj index 5284303..bb1056f 100644 --- a/Contentstack.Core.Unit.Tests/Contentstack.Core.Unit.Tests.csproj +++ b/Contentstack.Core.Unit.Tests/Contentstack.Core.Unit.Tests.csproj @@ -21,6 +21,7 @@ + diff --git a/Contentstack.Core.Unit.Tests/EntryUnitTests.cs b/Contentstack.Core.Unit.Tests/EntryUnitTests.cs index 15813c2..454f523 100644 --- a/Contentstack.Core.Unit.Tests/EntryUnitTests.cs +++ b/Contentstack.Core.Unit.Tests/EntryUnitTests.cs @@ -1338,6 +1338,122 @@ public void IncludeReference_WithEmptyArray_DoesNotAddParameter() #endregion + #region AssetFields Tests + + [Fact] + public void AssetFields_WithSingleField_AddsQueryParameter() + { + // Arrange + var entry = CreateEntry(); + var field = "user_defined_fields"; + + // Act + Entry result = entry.AssetFields(field); + + // Assert + Assert.NotNull(result); + Assert.Equal(entry, result); + + var urlQueriesField = typeof(Entry).GetField("UrlQueries", + BindingFlags.NonPublic | BindingFlags.Instance); + var urlQueries = (Dictionary)urlQueriesField?.GetValue(entry); + + Assert.True(urlQueries?.ContainsKey("asset_fields[]") ?? false); + var fields = urlQueries?["asset_fields[]"] as string[]; + Assert.NotNull(fields); + Assert.Single(fields); + Assert.Equal("user_defined_fields", fields[0]); + } + + [Fact] + public void AssetFields_WithMultipleFields_AddsQueryParameter() + { + // Arrange + var entry = CreateEntry(); + var fields = new[] { "user_defined_fields", "embedded", "ai_suggested" }; + + // Act + Entry result = entry.AssetFields(fields); + + // Assert + Assert.NotNull(result); + Assert.Equal(entry, result); + + var urlQueriesField = typeof(Entry).GetField("UrlQueries", + BindingFlags.NonPublic | BindingFlags.Instance); + var urlQueries = (Dictionary)urlQueriesField?.GetValue(entry); + + Assert.True(urlQueries?.ContainsKey("asset_fields[]") ?? false); + Assert.Equal(fields, urlQueries?["asset_fields[]"]); + } + + [Fact] + public void AssetFields_ReturnsSameInstance_ForChaining() + { + // Arrange + var entry = CreateEntry(); + + // Act + Entry result = entry.AssetFields("embedded"); + + // Assert + Assert.NotNull(result); + Assert.Same(entry, result); + } + + [Fact] + public void AssetFields_WithNoArguments_DoesNotAddParameter() + { + // Arrange + var entry = CreateEntry(); + + // Act + Entry result = entry.AssetFields(); + + // Assert + Assert.NotNull(result); + var urlQueriesField = typeof(Entry).GetField("UrlQueries", + BindingFlags.NonPublic | BindingFlags.Instance); + var urlQueries = (Dictionary)urlQueriesField?.GetValue(entry); + Assert.False(urlQueries?.ContainsKey("asset_fields[]") ?? false); + } + + [Fact] + public void AssetFields_WithNull_DoesNotAddParameter() + { + // Arrange + var entry = CreateEntry(); + + // Act + Entry result = entry.AssetFields(null); + + // Assert + Assert.NotNull(result); + var urlQueriesField = typeof(Entry).GetField("UrlQueries", + BindingFlags.NonPublic | BindingFlags.Instance); + var urlQueries = (Dictionary)urlQueriesField?.GetValue(entry); + Assert.False(urlQueries?.ContainsKey("asset_fields[]") ?? false); + } + + [Fact] + public void AssetFields_WithEmptyArray_DoesNotAddParameter() + { + // Arrange + var entry = CreateEntry(); + + // Act + Entry result = entry.AssetFields(new string[0]); + + // Assert + Assert.NotNull(result); + var urlQueriesField = typeof(Entry).GetField("UrlQueries", + BindingFlags.NonPublic | BindingFlags.Instance); + var urlQueries = (Dictionary)urlQueriesField?.GetValue(entry); + Assert.False(urlQueries?.ContainsKey("asset_fields[]") ?? false); + } + + #endregion + #region IncludeFallback Tests [Fact] diff --git a/Contentstack.Core.Unit.Tests/QueryUnitTests.cs b/Contentstack.Core.Unit.Tests/QueryUnitTests.cs index 316f19f..248b254 100644 --- a/Contentstack.Core.Unit.Tests/QueryUnitTests.cs +++ b/Contentstack.Core.Unit.Tests/QueryUnitTests.cs @@ -754,6 +754,119 @@ public void IncludeReference_WithArray_AddsQueryParameter() #endregion + #region AssetFields Tests + + [Fact] + public void AssetFields_WithSingleField_AddsQueryParameter() + { + // Arrange + var query = CreateQuery(); + var field = "user_defined_fields"; + + // Act + Query result = query.AssetFields(field); + + // Assert + Assert.NotNull(result); + Assert.Equal(query, result); + + var urlQueriesField = typeof(Query).GetField("UrlQueries", + BindingFlags.NonPublic | BindingFlags.Instance); + var urlQueries = (Dictionary)urlQueriesField?.GetValue(query); + + Assert.True(urlQueries?.ContainsKey("asset_fields[]") ?? false); + var fields = urlQueries?["asset_fields[]"] as string[]; + Assert.NotNull(fields); + Assert.Single(fields); + Assert.Equal("user_defined_fields", fields[0]); + } + + [Fact] + public void AssetFields_WithMultipleFields_AddsQueryParameter() + { + // Arrange + var query = CreateQuery(); + var fields = new[] { "user_defined_fields", "embedded" }; + + // Act + Query result = query.AssetFields(fields); + + // Assert + Assert.NotNull(result); + Assert.Equal(query, result); + + var urlQueriesField = typeof(Query).GetField("UrlQueries", + BindingFlags.NonPublic | BindingFlags.Instance); + var urlQueries = (Dictionary)urlQueriesField?.GetValue(query); + + Assert.True(urlQueries?.ContainsKey("asset_fields[]") ?? false); + Assert.Equal(fields, urlQueries?["asset_fields[]"]); + } + + [Fact] + public void AssetFields_ReturnsSameInstance_ForChaining() + { + // Arrange + var query = CreateQuery(); + + // Act + Query result = query.AssetFields("embedded"); + + // Assert + Assert.NotNull(result); + Assert.Same(query, result); + } + + [Fact] + public void AssetFields_WithNoArguments_DoesNotAddParameter() + { + // Arrange + var query = CreateQuery(); + + // Act + Query result = query.AssetFields(); + + // Assert + var urlQueriesField = typeof(Query).GetField("UrlQueries", + BindingFlags.NonPublic | BindingFlags.Instance); + var urlQueries = (Dictionary)urlQueriesField?.GetValue(query); + Assert.False(urlQueries?.ContainsKey("asset_fields[]") ?? false); + } + + [Fact] + public void AssetFields_WithNull_DoesNotAddParameter() + { + // Arrange + var query = CreateQuery(); + + // Act + Query result = query.AssetFields(null); + + // Assert + var urlQueriesField = typeof(Query).GetField("UrlQueries", + BindingFlags.NonPublic | BindingFlags.Instance); + var urlQueries = (Dictionary)urlQueriesField?.GetValue(query); + Assert.False(urlQueries?.ContainsKey("asset_fields[]") ?? false); + } + + [Fact] + public void AssetFields_WithEmptyArray_DoesNotAddParameter() + { + // Arrange + var query = CreateQuery(); + + // Act + Query result = query.AssetFields(new string[0]); + + // Assert + var urlQueriesField = typeof(Query).GetField("UrlQueries", + BindingFlags.NonPublic | BindingFlags.Instance); + var urlQueries = (Dictionary)urlQueriesField?.GetValue(query); + Assert.False(urlQueries?.ContainsKey("asset_fields[]") ?? false); + } + + #endregion + #region AddParam Tests [Fact] diff --git a/Contentstack.Core/Contentstack.Core.csproj b/Contentstack.Core/Contentstack.Core.csproj index 1d39949..d9b55f2 100644 --- a/Contentstack.Core/Contentstack.Core.csproj +++ b/Contentstack.Core/Contentstack.Core.csproj @@ -28,7 +28,7 @@ - + diff --git a/Contentstack.Core/Models/Asset.cs b/Contentstack.Core/Models/Asset.cs index 26a674b..13c2af1 100644 --- a/Contentstack.Core/Models/Asset.cs +++ b/Contentstack.Core/Models/Asset.cs @@ -299,6 +299,27 @@ public Asset AddParam(string key, string value) return this; } + /// + /// Request specific asset-related metadata in the response (CDA asset_fields[]). + /// Supported values include: user_defined_fields, embedded, ai_suggested, visual_markups. + /// + /// Asset field names to include. + /// Current instance of Asset for chaining. + /// + /// + /// stack.Asset(uid).AssetFields("user_defined_fields", "embedded").Fetch() + /// + /// + public Asset AssetFields(params string[] fields) + { + if (fields != null && fields.Length > 0) + { + this.UrlQueries.Add("asset_fields[]", fields); + } + return this; + } + + public void RemoveHeader(string key) { if (this._Headers.ContainsKey(key)) diff --git a/Contentstack.Core/Models/AssetLibrary.cs b/Contentstack.Core/Models/AssetLibrary.cs index 24c33f2..bdae936 100644 --- a/Contentstack.Core/Models/AssetLibrary.cs +++ b/Contentstack.Core/Models/AssetLibrary.cs @@ -245,6 +245,26 @@ public AssetLibrary AddParam(string key, string value) return this; } + /// + /// Request specific asset-related metadata in the response (CDA asset_fields[]). + /// Supported values include: user_defined_fields, embedded, ai_suggested, visual_markups. + /// + /// Asset field names to include. + /// Current instance of AssetLibrary for chaining. + /// + /// + /// stack.Asset().AssetFields("user_defined_fields").Find() + /// + /// + public AssetLibrary AssetFields(params string[] fields) + { + if (fields != null && fields.Length > 0) + { + UrlQueries.Add("asset_fields[]", fields); + } + return this; + } + /// /// Sets the locale. /// diff --git a/Contentstack.Core/Models/Entry.cs b/Contentstack.Core/Models/Entry.cs index 882a54c..c0ef9af 100644 --- a/Contentstack.Core/Models/Entry.cs +++ b/Contentstack.Core/Models/Entry.cs @@ -1181,6 +1181,26 @@ public Entry AddParam(string key, string value) return this; } + /// + /// Request specific asset-related metadata in the response (CDA asset_fields[]). + /// Supported values include: user_defined_fields, embedded, ai_suggested, visual_markups. + /// + /// Asset field names to include (e.g. "user_defined_fields", "embedded"). + /// Current instance of Entry for chaining. + /// + /// + /// stack.ContentType(uid).Entry(uid).AssetFields("user_defined_fields", "embedded").Fetch() + /// + /// + public Entry AssetFields(params string[] fields) + { + if (fields != null && fields.Length > 0) + { + UrlQueries.Add("asset_fields[]", fields); + } + return this; + } + /// /// Include branch for publish content. /// diff --git a/Contentstack.Core/Models/Query.cs b/Contentstack.Core/Models/Query.cs index ea92342..1b69b8d 100644 --- a/Contentstack.Core/Models/Query.cs +++ b/Contentstack.Core/Models/Query.cs @@ -1019,6 +1019,27 @@ public Query IncludeReference(String[] filed_uids) } + /// + /// Request specific asset-related metadata in the response (CDA asset_fields[]). + /// Supported values include: user_defined_fields, embedded, ai_suggested, visual_markups. + /// + /// Asset field names to include. + /// Current instance of Query for chaining. + /// + /// + /// stack.ContentType(uid).Entry().AssetFields("user_defined_fields").Find() + /// + /// + public Query AssetFields(params string[] fields) + { + if (fields != null && fields.Length > 0) + { + UrlQueries.Add("asset_fields[]", fields); + } + return this; + } + + /// /// Include tags with which to search entries. /// diff --git a/Directory.Build.props b/Directory.Build.props index 0e81c8f..0780fae 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -1,5 +1,5 @@ - 2.25.2 + 2.26.0 From ac2a06d539f0db6e8fc559e07502bf023ec513af Mon Sep 17 00:00:00 2001 From: OMpawar-21 Date: Fri, 13 Feb 2026 14:55:35 +0530 Subject: [PATCH 2/2] feat: add AssetFields() valid parameters Parameters are: 1. user_defined_fields 2. embedded_metadata 3. ai_generated_metadata 4. visual_markups --- CHANGELOG.md | 2 +- Contentstack.Core.Tests/AssetTest.cs | 26 +++++++ Contentstack.Core.Tests/EntryTest.cs | 17 ++++- Contentstack.Core.Tests/QueryTest.cs | 75 ++++++++++++++++++- .../AssetLibraryUnitTests.cs | 4 +- .../AssetUnitTests.cs | 4 +- .../EntryUnitTests.cs | 4 +- .../QueryUnitTests.cs | 4 +- Contentstack.Core/Models/Asset.cs | 6 +- Contentstack.Core/Models/AssetLibrary.cs | 4 +- Contentstack.Core/Models/Entry.cs | 8 +- Contentstack.Core/Models/Query.cs | 4 +- 12 files changed, 136 insertions(+), 22 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ab098e2..c6aef4d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,7 +5,7 @@ - CDA / DAM 2.0 – AssetFields support - Added `AssetFields(params string[] fields)` to request specific asset-related metadata via the CDA `asset_fields[]` query parameter - Implemented on: Entry (single entry fetch), Query (entries find), Asset (single asset fetch), AssetLibrary (assets find) - - Supported asset field values: `user_defined_fields`, `embedded`, `ai_suggested`, `visual_markups` + - Valid parameters: `user_defined_fields`, `embedded_metadata`, `ai_generated_metadata`, `visual_markups` - Method is chainable; when called with no arguments, the query parameter is not set ### Version: 2.25.2 diff --git a/Contentstack.Core.Tests/AssetTest.cs b/Contentstack.Core.Tests/AssetTest.cs index 61a80e3..37818ef 100644 --- a/Contentstack.Core.Tests/AssetTest.cs +++ b/Contentstack.Core.Tests/AssetTest.cs @@ -1021,6 +1021,20 @@ public async Task AssetFields_SingleField_RequestSucceeds() Assert.NotEmpty(result.FileName); } + [Fact] + public async Task AssetFields_WithMultipleFields_RequestSucceeds() + { + string uid = await FetchAssetUID(); + Asset asset = client.Asset(uid); + asset.AssetFields("user_defined_fields", "embedded_metadata", "visual_markups"); + Asset result = await asset.Fetch(); + + if (result == null) + Assert.Fail("Asset.Fetch with AssetFields multiple fields did not return a result."); + Assert.NotNull(result.Uid); + Assert.NotEmpty(result.FileName); + } + [Fact] public async Task AssetFields_AssetLibrary_SingleField_RequestSucceeds() { @@ -1033,6 +1047,18 @@ public async Task AssetFields_AssetLibrary_SingleField_RequestSucceeds() Assert.NotNull(assets.Items); } + [Fact] + public async Task AssetFields_AssetLibrary_WithMultipleFields_RequestSucceeds() + { + AssetLibrary assetLibrary = client.AssetLibrary(); + assetLibrary.AssetFields("user_defined_fields", "embedded_metadata", "ai_generated_metadata", "visual_markups"); + ContentstackCollection assets = await assetLibrary.FetchAll(); + + if (assets == null) + Assert.Fail("AssetLibrary.FetchAll with AssetFields multiple fields did not return a result."); + Assert.NotNull(assets.Items); + } + [Fact] public async Task AssetFields_WithNoArguments_RequestSucceeds() { diff --git a/Contentstack.Core.Tests/EntryTest.cs b/Contentstack.Core.Tests/EntryTest.cs index 0e7f554..16e14c5 100644 --- a/Contentstack.Core.Tests/EntryTest.cs +++ b/Contentstack.Core.Tests/EntryTest.cs @@ -465,7 +465,7 @@ public async Task AssetFields_SingleEntry_RequestSucceeds() string uid = await GetUID("source1"); Entry sourceEntry = contenttype.Entry(uid); - sourceEntry.AssetFields("user_defined_fields", "visual_markups"); + sourceEntry.AssetFields("user_defined_fields", "embedded_metadata", "ai_generated_metadata", "visual_markups"); var result = await sourceEntry.Fetch(); if (result == null) @@ -505,6 +505,21 @@ public async Task AssetFields_SingleField_RequestSucceeds() Assert.NotNull(result.Uid); } + [Fact] + public async Task AssetFields_WithMultipleFields_RequestSucceeds() + { + ContentType contenttype = client.ContentType(source); + string uid = await GetUID("source1"); + Entry sourceEntry = contenttype.Entry(uid); + + sourceEntry.AssetFields("user_defined_fields", "embedded_metadata", "visual_markups"); + var result = await sourceEntry.Fetch(); + + if (result == null) + Assert.Fail("Entry.Fetch with AssetFields multiple fields did not return a result."); + Assert.NotNull(result.Uid); + } + [Fact] public async Task AssetFields_WithNoArguments_RequestSucceeds() { diff --git a/Contentstack.Core.Tests/QueryTest.cs b/Contentstack.Core.Tests/QueryTest.cs index 76b87a1..5c367c2 100644 --- a/Contentstack.Core.Tests/QueryTest.cs +++ b/Contentstack.Core.Tests/QueryTest.cs @@ -1624,13 +1624,86 @@ public async Task IncludeSchema() public async Task AssetFieldsQueryEntriesRequestSucceeds() { Query query = client.ContentType(source).Query(); - query.AssetFields("user_defined_fields", "visual_markups"); + query.AssetFields("user_defined_fields", "embedded_metadata", "ai_generated_metadata", "visual_markups"); var result = await query.Find(); if (result == null) Assert.Fail("Query.Find with AssetFields did not return a result."); Assert.NotNull(result.Items); } + + [Fact] + public async Task AssetFields_ChainedWithIncludeMetadata_RequestSucceeds() + { + var result = await client.ContentType(source).Query() + .AssetFields("user_defined_fields") + .IncludeMetadata() + .Find(); + + if (result == null) + Assert.Fail("Query.Find with AssetFields and IncludeMetadata did not return a result."); + Assert.NotNull(result.Items); + } + + [Fact] + public async Task AssetFields_SingleField_RequestSucceeds() + { + Query query = client.ContentType(source).Query(); + query.AssetFields("user_defined_fields"); + var result = await query.Find(); + + if (result == null) + Assert.Fail("Query.Find with AssetFields single field did not return a result."); + Assert.NotNull(result.Items); + } + + [Fact] + public async Task AssetFields_WithMultipleFields_RequestSucceeds() + { + Query query = client.ContentType(source).Query(); + query.AssetFields("user_defined_fields", "embedded_metadata", "visual_markups"); + var result = await query.Find(); + + if (result == null) + Assert.Fail("Query.Find with AssetFields multiple fields did not return a result."); + Assert.NotNull(result.Items); + } + + [Fact] + public async Task AssetFields_WithNoArguments_RequestSucceeds() + { + Query query = client.ContentType(source).Query(); + query.AssetFields(); + var result = await query.Find(); + + if (result == null) + Assert.Fail("Query.Find with AssetFields() no arguments did not return a result."); + Assert.NotNull(result.Items); + } + + [Fact] + public async Task AssetFields_WithNull_RequestSucceeds() + { + Query query = client.ContentType(source).Query(); + query.AssetFields(null); + var result = await query.Find(); + + if (result == null) + Assert.Fail("Query.Find with AssetFields(null) did not return a result."); + Assert.NotNull(result.Items); + } + + [Fact] + public async Task AssetFields_WithEmptyArray_RequestSucceeds() + { + Query query = client.ContentType(source).Query(); + query.AssetFields(new string[0]); + var result = await query.Find(); + + if (result == null) + Assert.Fail("Query.Find with AssetFields(empty array) did not return a result."); + Assert.NotNull(result.Items); + } } } diff --git a/Contentstack.Core.Unit.Tests/AssetLibraryUnitTests.cs b/Contentstack.Core.Unit.Tests/AssetLibraryUnitTests.cs index 9695e6d..73b457b 100644 --- a/Contentstack.Core.Unit.Tests/AssetLibraryUnitTests.cs +++ b/Contentstack.Core.Unit.Tests/AssetLibraryUnitTests.cs @@ -203,7 +203,7 @@ public void AssetFields_WithMultipleFields_AddsQueryParameter() { // Arrange var assetLibrary = CreateAssetLibrary(); - var fields = new[] { "user_defined_fields", "embedded", "ai_suggested" }; + var fields = new[] { "user_defined_fields", "embedded_metadata", "ai_generated_metadata" }; // Act AssetLibrary result = assetLibrary.AssetFields(fields); @@ -227,7 +227,7 @@ public void AssetFields_ReturnsSameInstance_ForChaining() var assetLibrary = CreateAssetLibrary(); // Act - AssetLibrary result = assetLibrary.AssetFields("embedded"); + AssetLibrary result = assetLibrary.AssetFields("embedded_metadata"); // Assert Assert.NotNull(result); diff --git a/Contentstack.Core.Unit.Tests/AssetUnitTests.cs b/Contentstack.Core.Unit.Tests/AssetUnitTests.cs index 10c30e0..8baa357 100644 --- a/Contentstack.Core.Unit.Tests/AssetUnitTests.cs +++ b/Contentstack.Core.Unit.Tests/AssetUnitTests.cs @@ -400,7 +400,7 @@ public void AssetFields_WithMultipleFields_AddsQueryParameter() { // Arrange var asset = CreateAsset(); - var fields = new[] { "embedded", "visual_markups" }; + var fields = new[] { "embedded_metadata", "visual_markups" }; // Act Asset result = asset.AssetFields(fields); @@ -424,7 +424,7 @@ public void AssetFields_ReturnsSameInstance_ForChaining() var asset = CreateAsset(); // Act - Asset result = asset.AssetFields("ai_suggested"); + Asset result = asset.AssetFields("ai_generated_metadata"); // Assert Assert.NotNull(result); diff --git a/Contentstack.Core.Unit.Tests/EntryUnitTests.cs b/Contentstack.Core.Unit.Tests/EntryUnitTests.cs index 454f523..859cd06 100644 --- a/Contentstack.Core.Unit.Tests/EntryUnitTests.cs +++ b/Contentstack.Core.Unit.Tests/EntryUnitTests.cs @@ -1370,7 +1370,7 @@ public void AssetFields_WithMultipleFields_AddsQueryParameter() { // Arrange var entry = CreateEntry(); - var fields = new[] { "user_defined_fields", "embedded", "ai_suggested" }; + var fields = new[] { "user_defined_fields", "embedded_metadata", "ai_generated_metadata" }; // Act Entry result = entry.AssetFields(fields); @@ -1394,7 +1394,7 @@ public void AssetFields_ReturnsSameInstance_ForChaining() var entry = CreateEntry(); // Act - Entry result = entry.AssetFields("embedded"); + Entry result = entry.AssetFields("embedded_metadata"); // Assert Assert.NotNull(result); diff --git a/Contentstack.Core.Unit.Tests/QueryUnitTests.cs b/Contentstack.Core.Unit.Tests/QueryUnitTests.cs index 248b254..4e1c4ff 100644 --- a/Contentstack.Core.Unit.Tests/QueryUnitTests.cs +++ b/Contentstack.Core.Unit.Tests/QueryUnitTests.cs @@ -786,7 +786,7 @@ public void AssetFields_WithMultipleFields_AddsQueryParameter() { // Arrange var query = CreateQuery(); - var fields = new[] { "user_defined_fields", "embedded" }; + var fields = new[] { "user_defined_fields", "embedded_metadata" }; // Act Query result = query.AssetFields(fields); @@ -810,7 +810,7 @@ public void AssetFields_ReturnsSameInstance_ForChaining() var query = CreateQuery(); // Act - Query result = query.AssetFields("embedded"); + Query result = query.AssetFields("embedded_metadata"); // Assert Assert.NotNull(result); diff --git a/Contentstack.Core/Models/Asset.cs b/Contentstack.Core/Models/Asset.cs index 13c2af1..4174ec5 100644 --- a/Contentstack.Core/Models/Asset.cs +++ b/Contentstack.Core/Models/Asset.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; using System.IO; using System.Linq; @@ -301,13 +301,13 @@ public Asset AddParam(string key, string value) /// /// Request specific asset-related metadata in the response (CDA asset_fields[]). - /// Supported values include: user_defined_fields, embedded, ai_suggested, visual_markups. + /// Valid parameters: user_defined_fields, embedded_metadata, ai_generated_metadata, visual_markups. /// /// Asset field names to include. /// Current instance of Asset for chaining. /// /// - /// stack.Asset(uid).AssetFields("user_defined_fields", "embedded").Fetch() + /// stack.Asset(uid).AssetFields("user_defined_fields", "embedded_metadata").Fetch() /// /// public Asset AssetFields(params string[] fields) diff --git a/Contentstack.Core/Models/AssetLibrary.cs b/Contentstack.Core/Models/AssetLibrary.cs index bdae936..6a51f74 100644 --- a/Contentstack.Core/Models/AssetLibrary.cs +++ b/Contentstack.Core/Models/AssetLibrary.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; using System.IO; using System.Linq; @@ -247,7 +247,7 @@ public AssetLibrary AddParam(string key, string value) /// /// Request specific asset-related metadata in the response (CDA asset_fields[]). - /// Supported values include: user_defined_fields, embedded, ai_suggested, visual_markups. + /// Valid parameters: user_defined_fields, embedded_metadata, ai_generated_metadata, visual_markups. /// /// Asset field names to include. /// Current instance of AssetLibrary for chaining. diff --git a/Contentstack.Core/Models/Entry.cs b/Contentstack.Core/Models/Entry.cs index c0ef9af..d683ecd 100644 --- a/Contentstack.Core/Models/Entry.cs +++ b/Contentstack.Core/Models/Entry.cs @@ -1,4 +1,4 @@ -using Markdig; +using Markdig; using Newtonsoft.Json.Linq; using System; using System.Collections.Generic; @@ -1183,13 +1183,13 @@ public Entry AddParam(string key, string value) /// /// Request specific asset-related metadata in the response (CDA asset_fields[]). - /// Supported values include: user_defined_fields, embedded, ai_suggested, visual_markups. + /// Valid parameters: user_defined_fields, embedded_metadata, ai_generated_metadata, visual_markups. /// - /// Asset field names to include (e.g. "user_defined_fields", "embedded"). + /// Asset field names to include (e.g. "user_defined_fields", "embedded_metadata"). /// Current instance of Entry for chaining. /// /// - /// stack.ContentType(uid).Entry(uid).AssetFields("user_defined_fields", "embedded").Fetch() + /// stack.ContentType(uid).Entry(uid).AssetFields("user_defined_fields", "embedded_metadata").Fetch() /// /// public Entry AssetFields(params string[] fields) diff --git a/Contentstack.Core/Models/Query.cs b/Contentstack.Core/Models/Query.cs index 1b69b8d..c0d6ead 100644 --- a/Contentstack.Core/Models/Query.cs +++ b/Contentstack.Core/Models/Query.cs @@ -1,4 +1,4 @@ -using Newtonsoft.Json.Linq; +using Newtonsoft.Json.Linq; using System; using System.Collections.Generic; using System.IO; @@ -1021,7 +1021,7 @@ public Query IncludeReference(String[] filed_uids) /// /// Request specific asset-related metadata in the response (CDA asset_fields[]). - /// Supported values include: user_defined_fields, embedded, ai_suggested, visual_markups. + /// Valid parameters: user_defined_fields, embedded_metadata, ai_generated_metadata, visual_markups. /// /// Asset field names to include. /// Current instance of Query for chaining.