Skip to content

Commit e36dd86

Browse files
Merge pull request #11207 from umbraco/v8/bugfix/mntp-performance
Combine GetUrl requests when loading a MNTP with many entries
2 parents 20b9db8 + 106f6dc commit e36dd86

File tree

4 files changed

+84
-24
lines changed

4 files changed

+84
-24
lines changed

src/Umbraco.Web.UI.Client/src/common/mocks/resources/entity.mocks.js

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,15 @@ angular.module('umbraco.mocks').
3434
return [200, nodes, null];
3535
}
3636

37+
function returnUrlsbyUdis(status, data, headers) {
38+
39+
if (!mocksUtils.checkAuth()) {
40+
return [401, null, null];
41+
}
42+
43+
return [200, {}, null];
44+
}
45+
3746
function returnEntitybyIdsPost(method, url, data, headers) {
3847

3948
if (!mocksUtils.checkAuth()) {
@@ -73,6 +82,10 @@ angular.module('umbraco.mocks').
7382
.whenPOST(mocksUtils.urlRegex('/umbraco/UmbracoApi/Entity/GetByIds'))
7483
.respond(returnEntitybyIdsPost);
7584

85+
$httpBackend
86+
.whenPOST(mocksUtils.urlRegex('/umbraco/UmbracoApi/Entity/GetUrlsByUdis'))
87+
.respond(returnUrlsbyUdis);
88+
7689
$httpBackend
7790
.whenGET(mocksUtils.urlRegex('/umbraco/UmbracoApi/Entity/GetAncestors'))
7891
.respond(returnEntitybyIds);

src/Umbraco.Web.UI.Client/src/common/resources/entity.resource.js

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,21 @@ function entityResource($q, $http, umbRequestHelper) {
127127
'Failed to retrieve url for id:' + id);
128128
},
129129

130+
getUrlsByUdis: function(udis, culture) {
131+
var query = "culture=" + (culture || "");
132+
133+
return umbRequestHelper.resourcePromise(
134+
$http.post(
135+
umbRequestHelper.getApiUrl(
136+
"entityApiBaseUrl",
137+
"GetUrlsByUdis",
138+
query),
139+
{
140+
udis: udis
141+
}),
142+
'Failed to retrieve url map for udis ' + udis);
143+
},
144+
130145
getUrlByUdi: function (udi, culture) {
131146

132147
if (!udi) {

src/Umbraco.Web.UI.Client/src/views/propertyeditors/contentpicker/contentpicker.controller.js

Lines changed: 12 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -413,16 +413,26 @@ function contentPickerController($scope, $q, $routeParams, $location, entityReso
413413
var missingIds = _.difference(valueIds, renderModelIds);
414414

415415
if (missingIds.length > 0) {
416-
return entityResource.getByIds(missingIds, entityType).then(function (data) {
417416

417+
var requests = [
418+
entityResource.getByIds(missingIds, entityType),
419+
entityResource.getUrlsByUdis(missingIds)
420+
];
421+
422+
return $q.all(requests).then(function ([data, urlMap]) {
418423
_.each(valueIds,
419424
function (id, i) {
420425
var entity = _.find(data, function (d) {
421426
return $scope.model.config.idType === "udi" ? (d.udi == id) : (d.id == id);
422427
});
423428

424429
if (entity) {
425-
addSelectedItem(entity);
430+
431+
entity.url = entity.trashed
432+
? vm.labels.general_recycleBin
433+
: urlMap[id];
434+
435+
addSelectedItem(entity);
426436
}
427437

428438
});
@@ -469,26 +479,6 @@ function contentPickerController($scope, $q, $routeParams, $location, entityReso
469479

470480
}
471481

472-
function setEntityUrl(entity) {
473-
474-
// get url for content and media items
475-
if (entityType !== "Member") {
476-
entityResource.getUrl(entity.id, entityType).then(function (data) {
477-
// update url
478-
$scope.renderModel.forEach(function (item) {
479-
if (item.id === entity.id) {
480-
if (entity.trashed) {
481-
item.url = vm.labels.general_recycleBin;
482-
} else {
483-
item.url = data;
484-
}
485-
}
486-
});
487-
});
488-
}
489-
490-
}
491-
492482
function addSelectedItem(item) {
493483

494484
// set icon
@@ -523,8 +513,6 @@ function contentPickerController($scope, $q, $routeParams, $location, entityReso
523513
"published": (item.metaData && item.metaData.IsPublished === false && entityType === "Document") ? false : true
524514
// only content supports published/unpublished content so we set everything else to published so the UI looks correct
525515
});
526-
527-
setEntityUrl(item);
528516
}
529517

530518
function setSortingState(items) {

src/Umbraco.Web/Editors/EntityController.cs

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -235,6 +235,50 @@ public HttpResponseMessage GetUrl(Udi udi, string culture = "*")
235235
return GetUrl(intId.Result, entityType, culture);
236236
}
237237

238+
/// <summary>
239+
/// Get entity URLs by UDIs
240+
/// </summary>
241+
/// <param name="udis">
242+
/// A list of UDIs to lookup items by
243+
/// </param>
244+
/// <param name="culture">The culture to fetch the URL for</param>
245+
/// <returns>Dictionary mapping Udi -> Url</returns>
246+
/// <remarks>
247+
/// We allow for POST because there could be quite a lot of Ids.
248+
/// </remarks>
249+
[HttpGet]
250+
[HttpPost]
251+
public IDictionary<Udi, string> GetUrlsByUdis([FromJsonPath] Udi[] udis, string culture = null)
252+
{
253+
if (udis == null || udis.Length == 0)
254+
{
255+
return new Dictionary<Udi, string>();
256+
}
257+
258+
// TODO: PMJ 2021-09-27 - Should GetUrl(Udi) exist as an extension method on UrlProvider/IUrlProvider (in v9)
259+
string MediaOrDocumentUrl(Udi udi)
260+
{
261+
if (udi is not GuidUdi guidUdi)
262+
{
263+
return null;
264+
}
265+
266+
return guidUdi.EntityType switch
267+
{
268+
Constants.UdiEntityType.Document => UmbracoContext.UrlProvider.GetUrl(guidUdi.Guid, culture: culture ?? ClientCulture()),
269+
// NOTE: If culture is passed here we get an empty string rather than a media item URL WAT
270+
Constants.UdiEntityType.Media => UmbracoContext.UrlProvider.GetMediaUrl(guidUdi.Guid, culture: null),
271+
_ => null
272+
};
273+
}
274+
275+
return udis
276+
.Select(udi => new {
277+
Udi = udi,
278+
Url = MediaOrDocumentUrl(udi)
279+
}).ToDictionary(x => x.Udi, x => x.Url);
280+
}
281+
238282
/// <summary>
239283
/// Gets the URL of an entity
240284
/// </summary>

0 commit comments

Comments
 (0)