diff --git a/src/Umbraco.Web/Editors/EntityController.cs b/src/Umbraco.Web/Editors/EntityController.cs
index b6bef3fd96..6617363418 100644
--- a/src/Umbraco.Web/Editors/EntityController.cs
+++ b/src/Umbraco.Web/Editors/EntityController.cs
@@ -235,6 +235,55 @@ namespace Umbraco.Web.Editors
return GetUrl(intId.Result, entityType, culture);
}
+ ///
+ /// Get entity URLs by UDIs
+ ///
+ ///
+ /// A list of UDIs to lookup items by
+ ///
+ /// The culture to fetch the URL for
+ /// Dictionary mapping Udi -> Url
+ ///
+ /// We allow for POST because there could be quite a lot of Ids.
+ ///
+ [HttpGet]
+ [HttpPost]
+ public IDictionary GetUrlsByUdis([FromJsonPath] Udi[] ids, string culture = null)
+ {
+ if (ids == null)
+ {
+ throw new HttpResponseException(HttpStatusCode.NotFound);
+ }
+
+ if (ids.Length == 0)
+ {
+ return new Dictionary();
+ }
+
+ // TODO: PMJ 2021-09-27 - Should GetUrl(Udi) exist as an extension method on UrlProvider/IUrlProvider (in v9)
+ string MediaOrDocumentUrl(Udi udi)
+ {
+ if (udi is not GuidUdi guidUdi)
+ {
+ return null;
+ }
+
+ return guidUdi.EntityType switch
+ {
+ Constants.UdiEntityType.Document => UmbracoContext.UrlProvider.GetUrl(guidUdi.Guid, culture: culture ?? ClientCulture()),
+ // NOTE: If culture is passed here we get an empty string rather than a media item URL WAT
+ Constants.UdiEntityType.Media => UmbracoContext.UrlProvider.GetMediaUrl(guidUdi.Guid, culture: null),
+ _ => null
+ };
+ }
+
+ return ids
+ .Select(udi => new {
+ Udi = udi,
+ Url = MediaOrDocumentUrl(udi)
+ }).ToDictionary(x => x.Udi, x => x.Url);
+ }
+
///
/// Gets the URL of an entity
///