Episerver ServiceAPI: Create a custom endpoint
In some cases, you uploaded an asset through Service API.
And then you want to update its properties later. You can create a custom endpoint to implement it and we want to reuse the authentication, routing of ServiceAPI:
using EPiServer.ServiceApi.Configuration;
using EPiServer.ServiceApi.Validation;
using EPiServer.ServiceApi.Commerce.Controllers.Catalog;
using ControllerBase = EPiServer.ServiceApi.Commerce.Controllers.Catalog.ControllerBase;
using AuthorizePermissionAttribute = EPiServer.ServiceApi.Configuration.AuthorizePermissionAttribute;
using EPiServer.ServiceApi.Commerce;
using Foundation.Features.Media;
using EPiServer.DataAccess;
using EPiServer.Security;
using System.Configuration.Provider;
namespace Foundation.Custom
{
[Route("episerverapi/commerce")]
[RequireHttpsOrClose]
[ValidateReadOnlyMode(AllowedVerbs = HttpVerbs.Get)]
[ExceptionHandling]
[RequestLogging]
[Authorize(Policy = "ServiceApiAuthorizationPolicy")]
public class ItemAssetController : ControllerBase
{
private readonly IdentityMappingService _identityMappingService;
private readonly ReferenceConverter _referenceConverter;
private readonly IContentRepository _contentRepository;
public ItemAssetController(
IdentityMappingService identityMappingService,
ReferenceConverter referenceConverter,
IContentRepository contentRepository,
IContentLoader contentLoader,
IContentVersionRepository contentVersionRepository) : base(contentLoader, contentVersionRepository)
{
_identityMappingService = identityMappingService;
_referenceConverter = referenceConverter;
_contentRepository = contentRepository;
}
[Route("entries/{entryCode}/assets/{assetKey:guid}/properties/categories", Name = "SetAssetCategoriesByEntry")]
[HttpPut]
[AuthorizePermission("EPiServerServiceApi", "WriteAccess")]
public virtual IActionResult SetAssetCategoriesByEntry([FromEntryCode("entryCode")] string entryCode, Guid assetKey, [FromBody] string[] categories)
{
var mappedIdentity = _identityMappingService.Get(assetKey);
//mappedIdentity = _identityMappingService.Get(MappedIdentity.ConstructExternalIdentifier(providerName, integrationId));
if (mappedIdentity == null)
return NotFound($"No mapping found for asset with ID {assetKey} on entry {entryCode}");
var contentLink = _referenceConverter.GetContentLink(entryCode);
var entryContentBase = _contentLoader.Get<EntryContentBase>(contentLink);
var commerceMedia =
entryContentBase.CommerceMediaCollection.FirstOrDefault(media => media.AssetLink.ID == mappedIdentity.ContentLink.ID);
if (commerceMedia == null || !_contentRepository.TryGet<ImageMediaData>(commerceMedia.AssetLink, out var genericMedia))
return NotFound();
genericMedia = (ImageMediaData) genericMedia.CreateWritableClone();
genericMedia.ImageCategories = categories;
_contentRepository.Save(genericMedia, SaveAction.Publish, AccessLevel.NoAccess);
return Ok();
}
}
}
For the background, you could look at the table tblMappedIdentity, we can retrieve the content link from asset key (or integrationId):
Time to test our API, I prefer to use the CURL format that can be imported to postman:
curl --location --request PUT 'https://localhost:5001/episerverapi/commerce/entries/P-39813617/assets/24D74AD3-4E22-4AD3-9AD5-A88153DE2CA5/properties/categories' \
--header 'Content-Type: application/json' \
--header 'Authorization: bearer {token}' \
--header 'Accept: application/json' \
--header 'Cookie: EPiServer_Commerce_AnonymousId=c6e42968-1bfc-4310-af77-2ca9e4af5eed; EPiStateMarker=true; Language=en' \
--data ' ["cat1", "cat2"]'
If you don't know how to get a token, please refer to this post: https://khanhpham2411.blogspot.com/2023/12/serviceapi-example-of-how-to-properly.html
For the idea of next endpoint, you can use the provider name and intergrationId.
Comments
Post a Comment