diff --git a/src/Umbraco.Core/TypeExtensions.cs b/src/Umbraco.Core/TypeExtensions.cs
index 15f3e56924..70639d7ff1 100644
--- a/src/Umbraco.Core/TypeExtensions.cs
+++ b/src/Umbraco.Core/TypeExtensions.cs
@@ -398,7 +398,7 @@ namespace Umbraco.Core
///
/// the source type
///
- internal static Type GetEnumeratedType(this Type type)
+ public static Type GetEnumeratedType(this Type type)
{
if (typeof(IEnumerable).IsAssignableFrom(type) == false)
return null;
diff --git a/src/Umbraco.ModelsBuilder.Embedded/Building/TextBuilder.cs b/src/Umbraco.ModelsBuilder.Embedded/Building/TextBuilder.cs
index 43771eb46a..8328afb822 100644
--- a/src/Umbraco.ModelsBuilder.Embedded/Building/TextBuilder.cs
+++ b/src/Umbraco.ModelsBuilder.Embedded/Building/TextBuilder.cs
@@ -3,7 +3,6 @@ using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
-using Umbraco.Core.Configuration;
using Umbraco.Core.Configuration.Models;
namespace Umbraco.ModelsBuilder.Embedded.Building
@@ -254,7 +253,7 @@ namespace Umbraco.ModelsBuilder.Embedded.Building
sb.AppendFormat(" {0} => ",
property.ClrName);
WriteNonGenericClrType(sb, GetModelsNamespace() + "." + mixinClrName);
- sb.AppendFormat(".{0}(this);\n",
+ sb.AppendFormat(".{0}(this, _publishedValueFallback);\n",
MixinStaticGetterName(property.ClrName));
}
@@ -311,7 +310,7 @@ namespace Umbraco.ModelsBuilder.Embedded.Building
{
sb.Append("\t\tpublic ");
WriteClrType(sb, property.ClrTypeName);
- sb.AppendFormat(" {0} => {1}(this);\n",
+ sb.AppendFormat(" {0} => {1}(this, _publishedValueFallback);\n",
property.ClrName, MixinStaticGetterName(property.ClrName));
}
else
@@ -351,7 +350,7 @@ namespace Umbraco.ModelsBuilder.Embedded.Building
WriteGeneratedCodeAttribute(sb, "\t\t");
sb.Append("\t\tpublic static ");
WriteClrType(sb, property.ClrTypeName);
- sb.AppendFormat(" {0}(I{1} that) => that.Value",
+ sb.AppendFormat(" {0}(I{1} that, IPublishedValueFallback publishedValueFallback) => that.Value",
mixinStaticGetterName, mixinClrName);
if (property.ModelClrType != typeof(object))
{
@@ -359,7 +358,7 @@ namespace Umbraco.ModelsBuilder.Embedded.Building
WriteClrType(sb, property.ClrTypeName);
sb.Append(">");
}
- sb.AppendFormat("(\"{0}\");\n",
+ sb.AppendFormat("(publishedValueFallback, \"{0}\");\n",
property.Alias);
}
diff --git a/src/Umbraco.ModelsBuilder.Embedded/RoslynCompiler.cs b/src/Umbraco.ModelsBuilder.Embedded/RoslynCompiler.cs
index 1321078f98..37aeb75b35 100644
--- a/src/Umbraco.ModelsBuilder.Embedded/RoslynCompiler.cs
+++ b/src/Umbraco.ModelsBuilder.Embedded/RoslynCompiler.cs
@@ -69,8 +69,13 @@ namespace Umbraco.ModelsBuilder.Embedded
// Not entirely certain that assemblyIdentityComparer is nececary?
assemblyIdentityComparer: DesktopAssemblyIdentityComparer.Default));
- compilation.Emit(savePath);
+ var emitResult = compilation.Emit(savePath);
+ if (!emitResult.Success)
+ {
+ throw new InvalidOperationException("Roslyn compiler could not create ModelsBuilder dll:\n" +
+ string.Join("\n", emitResult.Diagnostics.Select(x=>x.GetMessage())));
+ }
}
}
}
diff --git a/src/Umbraco.Web.BackOffice/Controllers/ContentController.cs b/src/Umbraco.Web.BackOffice/Controllers/ContentController.cs
index eb7cf7e411..895f2f76b5 100644
--- a/src/Umbraco.Web.BackOffice/Controllers/ContentController.cs
+++ b/src/Umbraco.Web.BackOffice/Controllers/ContentController.cs
@@ -45,6 +45,8 @@ namespace Umbraco.Web.BackOffice.Controllers
///
[PluginController(Constants.Web.Mvc.BackOfficeApiArea)]
[Authorize(Policy = AuthorizationPolicies.TreeAccessDocuments)]
+ [ParameterSwapControllerActionSelector(nameof(GetById), "id", typeof(int), typeof(Guid), typeof(Udi))]
+ [ParameterSwapControllerActionSelector(nameof(GetNiceUrl), "id", typeof(int), typeof(Guid), typeof(Udi))]
public class ContentController : ContentControllerBase
{
private readonly PropertyEditorCollection _propertyEditors;
@@ -332,7 +334,6 @@ namespace Umbraco.Web.BackOffice.Controllers
///
[OutgoingEditorModelEvent]
[Authorize(Policy = AuthorizationPolicies.ContentPermissionBrowseById)]
- [DetermineAmbiguousActionByPassingParameters]
public ActionResult GetById(int id)
{
var foundContent = GetObjectFromRequest(() => _contentService.GetById(id));
@@ -351,7 +352,6 @@ namespace Umbraco.Web.BackOffice.Controllers
///
[OutgoingEditorModelEvent]
[Authorize(Policy = AuthorizationPolicies.ContentPermissionBrowseById)]
- [DetermineAmbiguousActionByPassingParameters]
public ActionResult GetById(Guid id)
{
var foundContent = GetObjectFromRequest(() => _contentService.GetById(id));
@@ -371,7 +371,6 @@ namespace Umbraco.Web.BackOffice.Controllers
///
[OutgoingEditorModelEvent]
[Authorize(Policy = AuthorizationPolicies.ContentPermissionBrowseById)]
- [DetermineAmbiguousActionByPassingParameters]
public ActionResult GetById(Udi id)
{
var guidUdi = id as GuidUdi;
@@ -389,7 +388,6 @@ namespace Umbraco.Web.BackOffice.Controllers
///
///
[OutgoingEditorModelEvent]
- [DetermineAmbiguousActionByPassingParameters]
public ActionResult GetEmpty(string contentTypeAlias, int parentId)
{
var contentType = _contentTypeService.Get(contentTypeAlias);
@@ -398,7 +396,7 @@ namespace Umbraco.Web.BackOffice.Controllers
return NotFound();
}
- return GetEmpty(contentType, parentId);
+ return GetEmptyInner(contentType, parentId);
}
@@ -416,10 +414,10 @@ namespace Umbraco.Web.BackOffice.Controllers
return NotFound();
}
- return GetEmpty(contentType, parentId);
+ return GetEmptyInner(contentType, parentId);
}
- private ContentItemDisplay GetEmpty(IContentType contentType, int parentId)
+ private ContentItemDisplay GetEmptyInner(IContentType contentType, int parentId)
{
var emptyContent = _contentService.Create("", parentId, contentType.Alias, _backofficeSecurityAccessor.BackOfficeSecurity.GetUserId().ResultOr(0));
var mapped = MapToDisplay(emptyContent);
@@ -436,8 +434,7 @@ namespace Umbraco.Web.BackOffice.Controllers
}
[OutgoingEditorModelEvent]
- [DetermineAmbiguousActionByPassingParameters]
- public ActionResult GetEmpty(int blueprintId, int parentId)
+ public ActionResult GetEmptyBlueprint(int blueprintId, int parentId)
{
var blueprint = _contentService.GetBlueprintById(blueprintId);
if (blueprint == null)
@@ -462,7 +459,6 @@ namespace Umbraco.Web.BackOffice.Controllers
///
///
///
- [DetermineAmbiguousActionByPassingParameters]
public IActionResult GetNiceUrl(int id)
{
var url = _publishedUrlProvider.GetUrl(id);
@@ -474,7 +470,6 @@ namespace Umbraco.Web.BackOffice.Controllers
///
///
///
- [DetermineAmbiguousActionByPassingParameters]
public IActionResult GetNiceUrl(Guid id)
{
var url = _publishedUrlProvider.GetUrl(id);
@@ -486,7 +481,6 @@ namespace Umbraco.Web.BackOffice.Controllers
///
///
///
- [DetermineAmbiguousActionByPassingParameters]
public IActionResult GetNiceUrl(Udi id)
{
var guidUdi = id as GuidUdi;
@@ -504,7 +498,6 @@ namespace Umbraco.Web.BackOffice.Controllers
///
///
[FilterAllowedOutgoingContent(typeof(IEnumerable>), "Items")]
- [DetermineAmbiguousActionByPassingParameters]
public PagedResult> GetChildren(
int id,
string includeProperties,
@@ -1641,7 +1634,7 @@ namespace Umbraco.Web.BackOffice.Controllers
}
var toMoveResult = ValidateMoveOrCopy(move);
- if (!(toMoveResult is null))
+ if (!(toMoveResult.Result is null))
{
return toMoveResult.Result;
}
diff --git a/src/Umbraco.Web.BackOffice/Controllers/ContentTypeController.cs b/src/Umbraco.Web.BackOffice/Controllers/ContentTypeController.cs
index ea34005a87..e3437cbd11 100644
--- a/src/Umbraco.Web.BackOffice/Controllers/ContentTypeController.cs
+++ b/src/Umbraco.Web.BackOffice/Controllers/ContentTypeController.cs
@@ -34,6 +34,7 @@ namespace Umbraco.Web.BackOffice.Controllers
/// An API controller used for dealing with content types
///
[PluginController(Constants.Web.Mvc.BackOfficeApiArea)]
+ [ParameterSwapControllerActionSelector(nameof(GetById), "id", typeof(int), typeof(Guid), typeof(Udi))]
public class ContentTypeController : ContentTypeControllerBase
{
// TODO: Split this controller apart so that authz is consistent, currently we need to authz each action individually.
@@ -113,7 +114,6 @@ namespace Umbraco.Web.BackOffice.Controllers
///
/// Gets the document type a given id
///
- [DetermineAmbiguousActionByPassingParameters]
[Authorize(Policy = AuthorizationPolicies.TreeAccessDocumentTypes)]
public ActionResult GetById(int id)
{
@@ -130,7 +130,6 @@ namespace Umbraco.Web.BackOffice.Controllers
///
/// Gets the document type a given guid
///
- [DetermineAmbiguousActionByPassingParameters]
[Authorize(Policy = AuthorizationPolicies.TreeAccessDocumentTypes)]
public ActionResult GetById(Guid id)
{
@@ -147,7 +146,6 @@ namespace Umbraco.Web.BackOffice.Controllers
///
/// Gets the document type a given udi
///
- [DetermineAmbiguousActionByPassingParameters]
[Authorize(Policy = AuthorizationPolicies.TreeAccessDocumentTypes)]
public ActionResult GetById(Udi id)
{
diff --git a/src/Umbraco.Web.BackOffice/Controllers/DataTypeController.cs b/src/Umbraco.Web.BackOffice/Controllers/DataTypeController.cs
index 4cc1f80f9e..eb47b7457e 100644
--- a/src/Umbraco.Web.BackOffice/Controllers/DataTypeController.cs
+++ b/src/Umbraco.Web.BackOffice/Controllers/DataTypeController.cs
@@ -21,7 +21,6 @@ using Umbraco.Web.Common.ActionsResults;
using Umbraco.Web.Common.Attributes;
using Umbraco.Web.Common.Authorization;
using Umbraco.Web.Models.ContentEditing;
-using Constants = Umbraco.Core.Constants;
namespace Umbraco.Web.BackOffice.Controllers
{
@@ -34,6 +33,7 @@ namespace Umbraco.Web.BackOffice.Controllers
///
[PluginController(Constants.Web.Mvc.BackOfficeApiArea)]
[Authorize(Policy = AuthorizationPolicies.TreeAccessDocumentsOrDocumentTypes)]
+ [ParameterSwapControllerActionSelector(nameof(GetById), "id", typeof(int), typeof(Guid), typeof(Udi))]
public class DataTypeController : BackOfficeNotificationsController
{
private readonly PropertyEditorCollection _propertyEditors;
@@ -90,7 +90,6 @@ namespace Umbraco.Web.BackOffice.Controllers
///
///
///
- [DetermineAmbiguousActionByPassingParameters]
public ActionResult GetById(int id)
{
var dataType = _dataTypeService.GetDataType(id);
@@ -107,7 +106,6 @@ namespace Umbraco.Web.BackOffice.Controllers
///
///
///
- [DetermineAmbiguousActionByPassingParameters]
public ActionResult GetById(Guid id)
{
var dataType = _dataTypeService.GetDataType(id);
@@ -124,7 +122,6 @@ namespace Umbraco.Web.BackOffice.Controllers
///
///
///
- [DetermineAmbiguousActionByPassingParameters]
public ActionResult GetById(Udi id)
{
var guidUdi = id as GuidUdi;
diff --git a/src/Umbraco.Web.BackOffice/Controllers/DetermineAmbiguousActionByPassingParameters.cs b/src/Umbraco.Web.BackOffice/Controllers/DetermineAmbiguousActionByPassingParameters.cs
deleted file mode 100644
index fc6c3b6814..0000000000
--- a/src/Umbraco.Web.BackOffice/Controllers/DetermineAmbiguousActionByPassingParameters.cs
+++ /dev/null
@@ -1,129 +0,0 @@
-using System;
-using System.Collections;
-using System.Collections.Generic;
-using System.Linq;
-using System.Net.Http;
-using System.Threading.Tasks;
-using Microsoft.AspNetCore.Http;
-using Microsoft.AspNetCore.Mvc.Abstractions;
-using Microsoft.AspNetCore.Mvc.ActionConstraints;
-using Microsoft.AspNetCore.Routing;
-using Newtonsoft.Json;
-using Newtonsoft.Json.Linq;
-using Umbraco.Core;
-using Umbraco.Extensions;
-using Umbraco.Web.BackOffice.ModelBinders;
-
-namespace Umbraco.Web.BackOffice.Controllers
-{
- ///
- /// This method determine ambiguous controller actions by making a tryparse of the string (from request) into the type of the argument.
- ///
- ///
- /// By using this methods you are allowed to to have multiple controller actions named equally. E.g. GetById(Guid id), GetById(int id),...
- ///
- public class DetermineAmbiguousActionByPassingParameters : ActionMethodSelectorAttribute
- {
- private string _requestBody = null;
-
- public override bool IsValidForRequest(RouteContext routeContext, ActionDescriptor action)
- {
- var parameters = action.Parameters;
- if (parameters.Any())
- {
- var canUse = true;
- foreach (var parameterDescriptor in parameters)
- {
- var values = GetValue(parameterDescriptor, routeContext);
-
- var type = parameterDescriptor.ParameterType;
-
- if(typeof(IEnumerable).IsAssignableFrom(type) && typeof(string) != type)
- {
- type = type.GetElementType();
- }
-
- if (values is null )
- {
- canUse &= Nullable.GetUnderlyingType(type) != null;
- }
- else
- {
- foreach (var value in values)
- {
- if (type == typeof(Udi))
- {
- canUse &= UdiParser.TryParse(value.ToString(), out _);
- }
- else if (type == typeof(int))
- {
- canUse &= int.TryParse(value.ToString(), out _);
- }
- else if (type == typeof(Guid))
- {
- canUse &= Guid.TryParse(value.ToString(), out _);
- }
- else if (type == typeof(string))
- {
- canUse &= true;
- }
- else if (type == typeof(bool))
- {
- canUse &= bool.TryParse(value, out _);
- }
- else if (type == typeof(Direction))
- {
- canUse &= Enum.TryParse(value, out _);
- }
- else
- {
- canUse &= true;
- }
- }
- }
-
- }
-
- return canUse;
- }
-
-
- return true;
- }
-
- private IEnumerable GetValue(ParameterDescriptor descriptor, RouteContext routeContext)
- {
- if (routeContext.HttpContext.Request.Query.ContainsKey(descriptor.Name))
- {
- return routeContext.HttpContext.Request.Query[descriptor.Name];
- }
-
- if (descriptor.BindingInfo.BinderType == typeof(FromJsonPathAttribute.JsonPathBinder))
- {
- // IMPORTANT: Ensure the requestBody can be read multiple times.
- routeContext.HttpContext.Request.EnableBuffering();
-
- // We need to use the asynchronous method here if synchronous IO is not allowed (it may or may not be, depending
- // on configuration in UmbracoBackOfficeServiceCollectionExtensions.AddUmbraco()).
- // We can't use async/await due to the need to override IsValidForRequest, which doesn't have an async override, so going with
- // this, which seems to be the least worst option for "sync to async" (https://stackoverflow.com/a/32429753/489433).
- var body = _requestBody ??= Task.Run(() => routeContext.HttpContext.Request.GetRawBodyStringAsync()).GetAwaiter().GetResult();
-
- var jToken = JsonConvert.DeserializeObject(body);
-
- return jToken[descriptor.Name].Values();
- }
-
- if (routeContext.HttpContext.Request.Method.InvariantEquals(HttpMethod.Post.ToString()) && routeContext.HttpContext.Request.Form.ContainsKey(descriptor.Name))
- {
- return routeContext.HttpContext.Request.Form[descriptor.Name];
- }
-
- return null;
-
- }
- }
-
-}
-
-
diff --git a/src/Umbraco.Web.BackOffice/Controllers/DictionaryController.cs b/src/Umbraco.Web.BackOffice/Controllers/DictionaryController.cs
index 6a03c6ef89..519dcc6c6a 100644
--- a/src/Umbraco.Web.BackOffice/Controllers/DictionaryController.cs
+++ b/src/Umbraco.Web.BackOffice/Controllers/DictionaryController.cs
@@ -2,22 +2,21 @@ using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
+using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging;
+using Microsoft.Extensions.Options;
using Umbraco.Core;
+using Umbraco.Core.Configuration.Models;
using Umbraco.Core.Mapping;
using Umbraco.Core.Models;
using Umbraco.Core.Security;
using Umbraco.Core.Services;
-using Umbraco.Web.Common.Attributes;
-using Umbraco.Web.Models.ContentEditing;
-using Constants = Umbraco.Core.Constants;
-using Umbraco.Core.Configuration.Models;
-using Microsoft.Extensions.Options;
-using Microsoft.AspNetCore.Authorization;
using Umbraco.Extensions;
using Umbraco.Web.Common.ActionsResults;
+using Umbraco.Web.Common.Attributes;
using Umbraco.Web.Common.Authorization;
+using Umbraco.Web.Models.ContentEditing;
namespace Umbraco.Web.BackOffice.Controllers
{
@@ -31,6 +30,7 @@ namespace Umbraco.Web.BackOffice.Controllers
///
[PluginController(Constants.Web.Mvc.BackOfficeApiArea)]
[Authorize(Policy = AuthorizationPolicies.TreeAccessDictionary)]
+ [ParameterSwapControllerActionSelector(nameof(GetById), "id", typeof(int), typeof(Guid), typeof(Udi))]
public class DictionaryController : BackOfficeNotificationsController
{
private readonly ILogger _logger;
@@ -141,8 +141,7 @@ namespace Umbraco.Web.BackOffice.Controllers
///
/// The . Returns a not found response when dictionary item does not exist
///
- [DetermineAmbiguousActionByPassingParameters]
- public ActionResult GetById(int id)
+ public ActionResult GetById(int id)
{
var dictionary = _localizationService.GetDictionaryItemById(id);
if (dictionary == null)
@@ -160,7 +159,6 @@ namespace Umbraco.Web.BackOffice.Controllers
///
/// The . Returns a not found response when dictionary item does not exist
///
- [DetermineAmbiguousActionByPassingParameters]
public ActionResult GetById(Guid id)
{
var dictionary = _localizationService.GetDictionaryItemById(id);
@@ -179,7 +177,6 @@ namespace Umbraco.Web.BackOffice.Controllers
///
/// The . Returns a not found response when dictionary item does not exist
///
- [DetermineAmbiguousActionByPassingParameters]
public ActionResult GetById(Udi id)
{
var guidUdi = id as GuidUdi;
diff --git a/src/Umbraco.Web.BackOffice/Controllers/EntityController.cs b/src/Umbraco.Web.BackOffice/Controllers/EntityController.cs
index 13ef66fa15..bf15621fae 100644
--- a/src/Umbraco.Web.BackOffice/Controllers/EntityController.cs
+++ b/src/Umbraco.Web.BackOffice/Controllers/EntityController.cs
@@ -43,6 +43,12 @@ namespace Umbraco.Web.BackOffice.Controllers
/// Some objects such as macros are not based on CMSNode
///
[PluginController(Constants.Web.Mvc.BackOfficeApiArea)]
+ [ParameterSwapControllerActionSelector(nameof(GetPagedChildren), "id", typeof(int), typeof(string))]
+ [ParameterSwapControllerActionSelector(nameof(GetPath), "id", typeof(int), typeof(Guid), typeof(Udi))]
+ [ParameterSwapControllerActionSelector(nameof(GetUrlAndAnchors), "id", typeof(int), typeof(Guid), typeof(Udi))]
+ [ParameterSwapControllerActionSelector(nameof(GetById), "id", typeof(int), typeof(Guid), typeof(Udi))]
+ [ParameterSwapControllerActionSelector(nameof(GetByIds), "ids", typeof(int[]), typeof(Guid[]), typeof(Udi[]))]
+ [ParameterSwapControllerActionSelector(nameof(GetUrl), "id", typeof(int), typeof(Udi))]
public class EntityController : UmbracoAuthorizedJsonController
{
private readonly ITreeService _treeService;
@@ -201,7 +207,6 @@ namespace Umbraco.Web.BackOffice.Controllers
///
///
///
- [DetermineAmbiguousActionByPassingParameters]
public IConvertToActionResult GetPath(int id, UmbracoEntityTypes type)
{
var foundContentResult = GetResultForId(id, type);
@@ -220,7 +225,6 @@ namespace Umbraco.Web.BackOffice.Controllers
///
///
///
- [DetermineAmbiguousActionByPassingParameters]
public IConvertToActionResult GetPath(Guid id, UmbracoEntityTypes type)
{
var foundContentResult = GetResultForKey(id, type);
@@ -239,7 +243,6 @@ namespace Umbraco.Web.BackOffice.Controllers
///
///
///
- [DetermineAmbiguousActionByPassingParameters]
public IActionResult GetPath(Udi id, UmbracoEntityTypes type)
{
var guidUdi = id as GuidUdi;
@@ -257,7 +260,6 @@ namespace Umbraco.Web.BackOffice.Controllers
/// UDI of the entity to fetch URL for
/// The culture to fetch the URL for
/// The URL or path to the item
- [DetermineAmbiguousActionByPassingParameters]
public IActionResult GetUrl(Udi udi, string culture = "*")
{
var intId = _entityService.GetId(udi);
@@ -291,7 +293,6 @@ namespace Umbraco.Web.BackOffice.Controllers
///
/// We are not restricting this with security because there is no sensitive data
///
- [DetermineAmbiguousActionByPassingParameters]
public IActionResult GetUrl(int id, UmbracoEntityTypes type, string culture = null)
{
culture = culture ?? ClientCulture();
@@ -363,7 +364,6 @@ namespace Umbraco.Web.BackOffice.Controllers
}
[HttpGet]
- [DetermineAmbiguousActionByPassingParameters]
public ActionResult GetUrlAndAnchors(Udi id, string culture = "*")
{
var intId = _entityService.GetId(id);
@@ -373,7 +373,6 @@ namespace Umbraco.Web.BackOffice.Controllers
return GetUrlAndAnchors(intId.Result, culture);
}
[HttpGet]
- [DetermineAmbiguousActionByPassingParameters]
public UrlAndAnchors GetUrlAndAnchors(int id, string culture = "*")
{
culture = culture ?? ClientCulture();
@@ -400,7 +399,6 @@ namespace Umbraco.Web.BackOffice.Controllers
///
///
///
- [DetermineAmbiguousActionByPassingParameters]
public ActionResult GetById(int id, UmbracoEntityTypes type)
{
return GetResultForId(id, type);
@@ -412,7 +410,6 @@ namespace Umbraco.Web.BackOffice.Controllers
///
///
///
- [DetermineAmbiguousActionByPassingParameters]
public ActionResult GetById(Guid id, UmbracoEntityTypes type)
{
return GetResultForKey(id, type);
@@ -424,7 +421,6 @@ namespace Umbraco.Web.BackOffice.Controllers
///
///
///
- [DetermineAmbiguousActionByPassingParameters]
public ActionResult GetById(Udi id, UmbracoEntityTypes type)
{
var guidUdi = id as GuidUdi;
@@ -449,8 +445,7 @@ namespace Umbraco.Web.BackOffice.Controllers
///
[HttpGet]
[HttpPost]
- [DetermineAmbiguousActionByPassingParameters]
- public ActionResult> GetByIds([FromJsonPath]int[] ids, UmbracoEntityTypes type)
+ public ActionResult> GetByIds([FromJsonPath]int[] ids, [FromQuery]UmbracoEntityTypes type)
{
if (ids == null)
{
@@ -471,8 +466,7 @@ namespace Umbraco.Web.BackOffice.Controllers
///
[HttpGet]
[HttpPost]
- [DetermineAmbiguousActionByPassingParameters]
- public ActionResult> GetByIds([FromJsonPath]Guid[] ids, UmbracoEntityTypes type)
+ public ActionResult> GetByIds([FromJsonPath]Guid[] ids, [FromQuery]UmbracoEntityTypes type)
{
if (ids == null)
{
@@ -495,7 +489,6 @@ namespace Umbraco.Web.BackOffice.Controllers
///
[HttpGet]
[HttpPost]
- [DetermineAmbiguousActionByPassingParameters]
public ActionResult> GetByIds([FromJsonPath]Udi[] ids, [FromQuery]UmbracoEntityTypes type)
{
if (ids == null)
@@ -572,7 +565,6 @@ namespace Umbraco.Web.BackOffice.Controllers
///
///
///
- [DetermineAmbiguousActionByPassingParameters]
public ActionResult> GetPagedChildren(
string id,
UmbracoEntityTypes type,
@@ -634,7 +626,6 @@ namespace Umbraco.Web.BackOffice.Controllers
///
///
///
- [DetermineAmbiguousActionByPassingParameters]
public ActionResult> GetPagedChildren(
int id,
UmbracoEntityTypes type,
diff --git a/src/Umbraco.Web.BackOffice/Controllers/IconController.cs b/src/Umbraco.Web.BackOffice/Controllers/IconController.cs
index a856306118..2d481b627f 100644
--- a/src/Umbraco.Web.BackOffice/Controllers/IconController.cs
+++ b/src/Umbraco.Web.BackOffice/Controllers/IconController.cs
@@ -20,7 +20,6 @@ namespace Umbraco.Web.BackOffice.Controllers
///
///
///
- [DetermineAmbiguousActionByPassingParameters]
public IconModel GetIcon(string iconName)
{
return _iconService.GetIcon(iconName);
diff --git a/src/Umbraco.Web.BackOffice/Controllers/MacrosController.cs b/src/Umbraco.Web.BackOffice/Controllers/MacrosController.cs
index 1ad7442289..c8a943d92a 100644
--- a/src/Umbraco.Web.BackOffice/Controllers/MacrosController.cs
+++ b/src/Umbraco.Web.BackOffice/Controllers/MacrosController.cs
@@ -1,24 +1,23 @@
-using Umbraco.Core.Services;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net.Http;
+using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging;
-using Umbraco.Core.Hosting;
-using Umbraco.Core.Models;
-using Umbraco.Core.Strings;
-using Umbraco.Web.Models.ContentEditing;
-using Constants = Umbraco.Core.Constants;
-using Umbraco.Core.PropertyEditors;
-using Umbraco.Web.Common.Attributes;
using Umbraco.Core;
+using Umbraco.Core.Hosting;
using Umbraco.Core.Mapping;
+using Umbraco.Core.Models;
+using Umbraco.Core.PropertyEditors;
using Umbraco.Core.Security;
-using Microsoft.AspNetCore.Authorization;
+using Umbraco.Core.Services;
+using Umbraco.Core.Strings;
using Umbraco.Web.Common.ActionsResults;
+using Umbraco.Web.Common.Attributes;
using Umbraco.Web.Common.Authorization;
+using Umbraco.Web.Models.ContentEditing;
namespace Umbraco.Web.BackOffice.Controllers
{
@@ -28,6 +27,7 @@ namespace Umbraco.Web.BackOffice.Controllers
///
[PluginController(Constants.Web.Mvc.BackOfficeApiArea)]
[Authorize(Policy = AuthorizationPolicies.TreeAccessMacros)]
+ [ParameterSwapControllerActionSelector(nameof(GetById), "id", typeof(int), typeof(Guid), typeof(Udi))]
public class MacrosController : BackOfficeNotificationsController
{
private readonly ParameterEditorCollection _parameterEditorCollection;
@@ -109,7 +109,6 @@ namespace Umbraco.Web.BackOffice.Controllers
}
[HttpGet]
- [DetermineAmbiguousActionByPassingParameters]
public ActionResult GetById(int id)
{
var macro = _macroService.GetById(id);
@@ -125,7 +124,6 @@ namespace Umbraco.Web.BackOffice.Controllers
}
[HttpGet]
- [DetermineAmbiguousActionByPassingParameters]
public ActionResult GetById(Guid id)
{
var macro = _macroService.GetById(id);
@@ -141,7 +139,6 @@ namespace Umbraco.Web.BackOffice.Controllers
}
[HttpGet]
- [DetermineAmbiguousActionByPassingParameters]
public ActionResult GetById(Udi id)
{
var guidUdi = id as GuidUdi;
diff --git a/src/Umbraco.Web.BackOffice/Controllers/MediaController.cs b/src/Umbraco.Web.BackOffice/Controllers/MediaController.cs
index e822e7df84..b230664b28 100644
--- a/src/Umbraco.Web.BackOffice/Controllers/MediaController.cs
+++ b/src/Umbraco.Web.BackOffice/Controllers/MediaController.cs
@@ -50,6 +50,8 @@ namespace Umbraco.Web.BackOffice.Controllers
///
[PluginController(Constants.Web.Mvc.BackOfficeApiArea)]
[Authorize(Policy = AuthorizationPolicies.SectionAccessMedia)]
+ [ParameterSwapControllerActionSelector(nameof(GetById), "id", typeof(int), typeof(Guid), typeof(Udi))]
+ [ParameterSwapControllerActionSelector(nameof(GetChildren), "id", typeof(int), typeof(Guid), typeof(Udi))]
public class MediaController : ContentControllerBase
{
private readonly IShortStringHelper _shortStringHelper;
@@ -170,7 +172,6 @@ namespace Umbraco.Web.BackOffice.Controllers
///
[OutgoingEditorModelEvent]
[Authorize(Policy = AuthorizationPolicies.MediaPermissionPathById)]
- [DetermineAmbiguousActionByPassingParameters]
public MediaItemDisplay GetById(int id)
{
var foundMedia = GetObjectFromRequest(() => _mediaService.GetById(id));
@@ -191,7 +192,6 @@ namespace Umbraco.Web.BackOffice.Controllers
///
[OutgoingEditorModelEvent]
[Authorize(Policy = AuthorizationPolicies.MediaPermissionPathById)]
- [DetermineAmbiguousActionByPassingParameters]
public MediaItemDisplay GetById(Guid id)
{
var foundMedia = GetObjectFromRequest(() => _mediaService.GetById(id));
@@ -212,7 +212,6 @@ namespace Umbraco.Web.BackOffice.Controllers
///
[OutgoingEditorModelEvent]
[Authorize(Policy = AuthorizationPolicies.MediaPermissionPathById)]
- [DetermineAmbiguousActionByPassingParameters]
public ActionResult GetById(Udi id)
{
var guidUdi = id as GuidUdi;
@@ -299,7 +298,6 @@ namespace Umbraco.Web.BackOffice.Controllers
/// Returns the child media objects - using the entity INT id
///
[FilterAllowedOutgoingMedia(typeof(IEnumerable>), "Items")]
- [DetermineAmbiguousActionByPassingParameters]
public PagedResult> GetChildren(int id,
int pageNumber = 0,
int pageSize = 0,
@@ -377,7 +375,6 @@ namespace Umbraco.Web.BackOffice.Controllers
///
///
[FilterAllowedOutgoingMedia(typeof(IEnumerable>), "Items")]
- [DetermineAmbiguousActionByPassingParameters]
public ActionResult>> GetChildren(Guid id,
int pageNumber = 0,
int pageSize = 0,
@@ -407,7 +404,6 @@ namespace Umbraco.Web.BackOffice.Controllers
///
///
[FilterAllowedOutgoingMedia(typeof(IEnumerable>), "Items")]
- [DetermineAmbiguousActionByPassingParameters]
public ActionResult>> GetChildren(Udi id,
int pageNumber = 0,
int pageSize = 0,
diff --git a/src/Umbraco.Web.BackOffice/Controllers/MediaTypeController.cs b/src/Umbraco.Web.BackOffice/Controllers/MediaTypeController.cs
index b8952e580f..769bac0868 100644
--- a/src/Umbraco.Web.BackOffice/Controllers/MediaTypeController.cs
+++ b/src/Umbraco.Web.BackOffice/Controllers/MediaTypeController.cs
@@ -22,6 +22,8 @@ namespace Umbraco.Web.BackOffice.Controllers
/// An API controller used for dealing with content types
///
[PluginController(Constants.Web.Mvc.BackOfficeApiArea)]
+ [ParameterSwapControllerActionSelector(nameof(GetById), "id", typeof(int), typeof(Guid), typeof(Udi))]
+ [ParameterSwapControllerActionSelector(nameof(GetAllowedChildren), "contentId", typeof(int), typeof(Guid), typeof(Udi))]
public class MediaTypeController : ContentTypeControllerBase
{
// TODO: Split this controller apart so that authz is consistent, currently we need to authz each action individually.
@@ -74,7 +76,6 @@ namespace Umbraco.Web.BackOffice.Controllers
///
///
///
- [DetermineAmbiguousActionByPassingParameters]
[Authorize(Policy = AuthorizationPolicies.TreeAccessMediaOrMediaTypes)]
public ActionResult GetById(int id)
{
@@ -93,7 +94,6 @@ namespace Umbraco.Web.BackOffice.Controllers
///
///
///
- [DetermineAmbiguousActionByPassingParameters]
[Authorize(Policy = AuthorizationPolicies.TreeAccessMediaOrMediaTypes)]
public ActionResult GetById(Guid id)
{
@@ -112,7 +112,6 @@ namespace Umbraco.Web.BackOffice.Controllers
///
///
///
- [DetermineAmbiguousActionByPassingParameters]
[Authorize(Policy = AuthorizationPolicies.TreeAccessMediaOrMediaTypes)]
public ActionResult GetById(Udi id)
{
@@ -338,7 +337,6 @@ namespace Umbraco.Web.BackOffice.Controllers
///
///
[Authorize(Policy = AuthorizationPolicies.TreeAccessMediaOrMediaTypes)]
- [DetermineAmbiguousActionByPassingParameters]
public IEnumerable GetAllowedChildren(int contentId)
{
if (contentId == Constants.System.RecycleBinContent)
@@ -385,7 +383,6 @@ namespace Umbraco.Web.BackOffice.Controllers
///
///
[Authorize(Policy = AuthorizationPolicies.TreeAccessMediaOrMediaTypes)]
- [DetermineAmbiguousActionByPassingParameters]
public ActionResult> GetAllowedChildren(Guid contentId)
{
var entity = _entityService.Get(contentId);
@@ -402,7 +399,6 @@ namespace Umbraco.Web.BackOffice.Controllers
///
///
[Authorize(Policy = AuthorizationPolicies.TreeAccessMediaOrMediaTypes)]
- [DetermineAmbiguousActionByPassingParameters]
public ActionResult> GetAllowedChildren(Udi contentId)
{
var guidUdi = contentId as GuidUdi;
diff --git a/src/Umbraco.Web.BackOffice/Controllers/MemberGroupController.cs b/src/Umbraco.Web.BackOffice/Controllers/MemberGroupController.cs
index 43df969ef5..c7d64c550d 100644
--- a/src/Umbraco.Web.BackOffice/Controllers/MemberGroupController.cs
+++ b/src/Umbraco.Web.BackOffice/Controllers/MemberGroupController.cs
@@ -10,7 +10,6 @@ using Umbraco.Core.Services;
using Umbraco.Web.Common.Attributes;
using Umbraco.Web.Common.Authorization;
using Umbraco.Web.Models.ContentEditing;
-using Constants = Umbraco.Core.Constants;
namespace Umbraco.Web.BackOffice.Controllers
{
@@ -19,6 +18,7 @@ namespace Umbraco.Web.BackOffice.Controllers
///
[PluginController(Constants.Web.Mvc.BackOfficeApiArea)]
[Authorize(Policy = AuthorizationPolicies.TreeAccessMemberGroups)]
+ [ParameterSwapControllerActionSelector(nameof(GetById), "id", typeof(int), typeof(Guid), typeof(Udi))]
public class MemberGroupController : UmbracoAuthorizedJsonController
{
private readonly IMemberGroupService _memberGroupService;
@@ -42,7 +42,6 @@ namespace Umbraco.Web.BackOffice.Controllers
///
///
///
- [DetermineAmbiguousActionByPassingParameters]
public ActionResult GetById(int id)
{
var memberGroup = _memberGroupService.GetById(id);
@@ -61,7 +60,6 @@ namespace Umbraco.Web.BackOffice.Controllers
///
///
///
- [DetermineAmbiguousActionByPassingParameters]
public ActionResult GetById(Guid id)
{
var memberGroup = _memberGroupService.GetById(id);
@@ -78,7 +76,6 @@ namespace Umbraco.Web.BackOffice.Controllers
///
///
///
- [DetermineAmbiguousActionByPassingParameters]
public ActionResult GetById(Udi id)
{
var guidUdi = id as GuidUdi;
diff --git a/src/Umbraco.Web.BackOffice/Controllers/MemberTypeController.cs b/src/Umbraco.Web.BackOffice/Controllers/MemberTypeController.cs
index 7944da1f0a..728245e042 100644
--- a/src/Umbraco.Web.BackOffice/Controllers/MemberTypeController.cs
+++ b/src/Umbraco.Web.BackOffice/Controllers/MemberTypeController.cs
@@ -22,6 +22,7 @@ namespace Umbraco.Web.BackOffice.Controllers
///
[PluginController(Constants.Web.Mvc.BackOfficeApiArea)]
[Authorize(Policy = AuthorizationPolicies.TreeAccessMemberTypes)]
+ [ParameterSwapControllerActionSelector(nameof(GetById), "id", typeof(int), typeof(Guid), typeof(Udi))]
public class MemberTypeController : ContentTypeControllerBase
{
private readonly IMemberTypeService _memberTypeService;
@@ -61,7 +62,6 @@ namespace Umbraco.Web.BackOffice.Controllers
///
///
///
- [DetermineAmbiguousActionByPassingParameters]
public ActionResult GetById(int id)
{
var mt = _memberTypeService.Get(id);
@@ -79,7 +79,6 @@ namespace Umbraco.Web.BackOffice.Controllers
///
///
///
- [DetermineAmbiguousActionByPassingParameters]
public ActionResult GetById(Guid id)
{
var memberType = _memberTypeService.Get(id);
@@ -97,7 +96,6 @@ namespace Umbraco.Web.BackOffice.Controllers
///
///
///
- [DetermineAmbiguousActionByPassingParameters]
public ActionResult GetById(Udi id)
{
var guidUdi = id as GuidUdi;
diff --git a/src/Umbraco.Web.BackOffice/Controllers/ParameterSwapControllerActionSelectorAttribute.cs b/src/Umbraco.Web.BackOffice/Controllers/ParameterSwapControllerActionSelectorAttribute.cs
new file mode 100644
index 0000000000..5e423af270
--- /dev/null
+++ b/src/Umbraco.Web.BackOffice/Controllers/ParameterSwapControllerActionSelectorAttribute.cs
@@ -0,0 +1,176 @@
+using System;
+using System.Linq;
+using System.Net.Http;
+using System.Threading.Tasks;
+using Microsoft.AspNetCore.Mvc.ActionConstraints;
+using Microsoft.AspNetCore.Mvc.Controllers;
+using Newtonsoft.Json;
+using Newtonsoft.Json.Linq;
+using Umbraco.Core;
+using Umbraco.Extensions;
+
+namespace Umbraco.Web.BackOffice.Controllers
+{
+ [AttributeUsage(AttributeTargets.Class, AllowMultiple = true, Inherited = true)]
+ internal class ParameterSwapControllerActionSelectorAttribute : Attribute, IActionConstraint
+ {
+ private readonly string _actionName;
+ private readonly string _parameterName;
+ private readonly Type[] _supportedTypes;
+ private string _requestBody;
+
+ public ParameterSwapControllerActionSelectorAttribute(string actionName, string parameterName, params Type[] supportedTypes)
+ {
+ _actionName = actionName;
+ _parameterName = parameterName;
+ _supportedTypes = supportedTypes;
+ }
+
+ ///
+ public int Order { get; set; } = 101;
+
+ ///
+ public bool Accept(ActionConstraintContext context)
+ {
+ if (!IsValidCandidate(context.CurrentCandidate))
+ {
+ return true;
+ }
+
+ var chosenCandidate = SelectAction(context);
+
+ var found = context.CurrentCandidate.Equals(chosenCandidate);
+ return found;
+ }
+
+ private ActionSelectorCandidate? SelectAction(ActionConstraintContext context)
+ {
+ if (TryBindFromUri(context, out var candidate))
+ {
+ return candidate;
+ }
+
+ //if it's a post we can try to read from the body and bind from the json value
+ if (context.RouteContext.HttpContext.Request.Method == HttpMethod.Post.ToString())
+ {
+ // We need to use the asynchronous method here if synchronous IO is not allowed (it may or may not be, depending
+ // on configuration in UmbracoBackOfficeServiceCollectionExtensions.AddUmbraco()).
+ // We can't use async/await due to the need to override IsValidForRequest, which doesn't have an async override, so going with
+ // this, which seems to be the least worst option for "sync to async" (https://stackoverflow.com/a/32429753/489433).
+ var strJson = _requestBody ??= Task.Run(() => context.RouteContext.HttpContext.Request.GetRawBodyStringAsync()).GetAwaiter().GetResult();
+
+ var json = JsonConvert.DeserializeObject(strJson);
+
+ if (json == null)
+ {
+ return null;
+ }
+
+ var requestParam = json[_parameterName];
+
+ if (requestParam != null)
+ {
+ var paramTypes = _supportedTypes;
+
+ foreach (var paramType in paramTypes)
+ {
+ try
+ {
+ var converted = requestParam.ToObject(paramType);
+ if (converted != null)
+ {
+ var foundCandidate = MatchByType(paramType, context);
+ if (foundCandidate.HasValue)
+ {
+ return foundCandidate;
+ }
+ }
+ }
+ catch (JsonReaderException)
+ {
+ //can't convert
+ }
+ catch (JsonSerializationException)
+ {
+ //can't convert
+ }
+ }
+ }
+ }
+
+ return null;
+ }
+
+ private bool TryBindFromUri(ActionConstraintContext context, out ActionSelectorCandidate? foundCandidate)
+ {
+
+ string requestParam = null;
+ if (context.RouteContext.HttpContext.Request.Query.TryGetValue(_parameterName, out var stringValues))
+ {
+ requestParam = stringValues.ToString();
+ }
+
+ if (requestParam == string.Empty && _supportedTypes.Length > 0)
+ {
+ //if it's empty then in theory we can select any of the actions since they'll all need to deal with empty or null parameters
+ //so we'll try to use the first one available
+ foundCandidate = MatchByType(_supportedTypes[0], context);
+ if (foundCandidate.HasValue)
+ {
+ return true;
+ }
+
+ }
+
+ if (requestParam != null)
+ {
+ foreach (var paramType in _supportedTypes)
+ {
+ //check if this is IEnumerable and if so this will get it's type
+ //we need to know this since the requestParam will always just be a string
+ var enumType = paramType.GetEnumeratedType();
+
+ var converted = requestParam.TryConvertTo(enumType ?? paramType);
+ if (converted)
+ {
+ foundCandidate = MatchByType(paramType, context);
+ if (foundCandidate.HasValue)
+ {
+ return true;
+ }
+ }
+ }
+ }
+
+ foundCandidate = null;
+ return false;
+ }
+
+ private ActionSelectorCandidate? MatchByType(Type idType, ActionConstraintContext context)
+ {
+ if (context.Candidates.Count() > 1)
+ {
+ //choose the one that has the parameter with the T type
+ var candidate = context.Candidates.FirstOrDefault(x => x.Action.Parameters.FirstOrDefault(p => p.Name == _parameterName && p.ParameterType == idType) != null);
+
+ return candidate;
+ }
+ return null;
+ }
+
+ private bool IsValidCandidate(ActionSelectorCandidate candidate)
+ {
+ if (!(candidate.Action is ControllerActionDescriptor controllerActionDescriptor))
+ {
+ return false;
+ }
+
+ if (controllerActionDescriptor.ActionName != _actionName)
+ {
+ return false;
+ }
+
+ return true;
+ }
+ }
+}
diff --git a/src/Umbraco.Web.BackOffice/Controllers/RelationTypeController.cs b/src/Umbraco.Web.BackOffice/Controllers/RelationTypeController.cs
index 0a6d174bdd..8ef1a24951 100644
--- a/src/Umbraco.Web.BackOffice/Controllers/RelationTypeController.cs
+++ b/src/Umbraco.Web.BackOffice/Controllers/RelationTypeController.cs
@@ -2,19 +2,18 @@ using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
+using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging;
using Umbraco.Core;
+using Umbraco.Core.Mapping;
using Umbraco.Core.Models;
using Umbraco.Core.Services;
using Umbraco.Core.Strings;
-using Umbraco.Web.Models.ContentEditing;
-using Constants = Umbraco.Core.Constants;
-using Umbraco.Core.Mapping;
-using Umbraco.Web.Common.Attributes;
-using Microsoft.AspNetCore.Authorization;
using Umbraco.Web.Common.ActionsResults;
+using Umbraco.Web.Common.Attributes;
using Umbraco.Web.Common.Authorization;
+using Umbraco.Web.Models.ContentEditing;
namespace Umbraco.Web.BackOffice.Controllers
{
@@ -23,6 +22,7 @@ namespace Umbraco.Web.BackOffice.Controllers
///
[PluginController(Constants.Web.Mvc.BackOfficeApiArea)]
[Authorize(Policy = AuthorizationPolicies.TreeAccessRelationTypes)]
+ [ParameterSwapControllerActionSelector(nameof(GetById), "id", typeof(int), typeof(Guid), typeof(Udi))]
public class RelationTypeController : BackOfficeNotificationsController
{
private readonly ILogger _logger;
@@ -47,7 +47,6 @@ namespace Umbraco.Web.BackOffice.Controllers
///
/// The relation type ID.
/// Returns the .
- [DetermineAmbiguousActionByPassingParameters]
public ActionResult GetById(int id)
{
var relationType = _relationService.GetRelationTypeById(id);
@@ -66,7 +65,6 @@ namespace Umbraco.Web.BackOffice.Controllers
///
/// The relation type ID.
/// Returns the .
- [DetermineAmbiguousActionByPassingParameters]
public ActionResult GetById(Guid id)
{
var relationType = _relationService.GetRelationTypeById(id);
@@ -82,7 +80,6 @@ namespace Umbraco.Web.BackOffice.Controllers
///
/// The relation type ID.
/// Returns the .
- [DetermineAmbiguousActionByPassingParameters]
public ActionResult GetById(Udi id)
{
var guidUdi = id as GuidUdi;
diff --git a/src/Umbraco.Web.BackOffice/Controllers/TemplateController.cs b/src/Umbraco.Web.BackOffice/Controllers/TemplateController.cs
index 560e3bc78c..5b85c381c4 100644
--- a/src/Umbraco.Web.BackOffice/Controllers/TemplateController.cs
+++ b/src/Umbraco.Web.BackOffice/Controllers/TemplateController.cs
@@ -12,12 +12,12 @@ using Umbraco.Core.Strings;
using Umbraco.Web.Common.Attributes;
using Umbraco.Web.Common.Authorization;
using Umbraco.Web.Models.ContentEditing;
-using Constants = Umbraco.Core.Constants;
namespace Umbraco.Web.BackOffice.Controllers
{
[PluginController(Constants.Web.Mvc.BackOfficeApiArea)]
[Authorize(Policy = AuthorizationPolicies.TreeAccessTemplates)]
+ [ParameterSwapControllerActionSelector(nameof(GetById), "id", typeof(int), typeof(Guid), typeof(Udi))]
public class TemplateController : BackOfficeNotificationsController
{
private readonly IFileService _fileService;
@@ -59,7 +59,6 @@ namespace Umbraco.Web.BackOffice.Controllers
///
///
///
- [DetermineAmbiguousActionByPassingParameters]
public ActionResult GetById(int id)
{
var template = _fileService.GetTemplate(id);
@@ -75,7 +74,6 @@ namespace Umbraco.Web.BackOffice.Controllers
///
///
///
- [DetermineAmbiguousActionByPassingParameters]
public ActionResult GetById(Guid id)
{
var template = _fileService.GetTemplate(id);
@@ -90,7 +88,6 @@ namespace Umbraco.Web.BackOffice.Controllers
///
///
///
- [DetermineAmbiguousActionByPassingParameters]
public ActionResult GetById(Udi id)
{
var guidUdi = id as GuidUdi;
diff --git a/src/Umbraco.Web.BackOffice/Filters/CheckIfUserTicketDataIsStaleAttribute.cs b/src/Umbraco.Web.BackOffice/Filters/CheckIfUserTicketDataIsStaleAttribute.cs
index 6e14468a2a..e6e2d579b5 100644
--- a/src/Umbraco.Web.BackOffice/Filters/CheckIfUserTicketDataIsStaleAttribute.cs
+++ b/src/Umbraco.Web.BackOffice/Filters/CheckIfUserTicketDataIsStaleAttribute.cs
@@ -13,6 +13,7 @@ using Umbraco.Core.Configuration.Models;
using Umbraco.Core.Mapping;
using Umbraco.Core.Models;
using Umbraco.Core.Models.Membership;
+using Umbraco.Core.Scoping;
using Umbraco.Core.Security;
using Umbraco.Core.Services;
using Umbraco.Extensions;
@@ -22,7 +23,7 @@ using Umbraco.Web.Common.Security;
namespace Umbraco.Web.BackOffice.Filters
{
///
- ///
+ ///
///
internal sealed class CheckIfUserTicketDataIsStaleAttribute : TypeFilterAttribute
{
@@ -41,6 +42,7 @@ namespace Umbraco.Web.BackOffice.Filters
private readonly IOptions _globalSettings;
private readonly IBackOfficeSignInManager _backOfficeSignInManager;
private readonly IBackOfficeAntiforgery _backOfficeAntiforgery;
+ private readonly IScopeProvider _scopeProvider;
public CheckIfUserTicketDataIsStaleFilter(
IRequestCache requestCache,
@@ -50,7 +52,8 @@ namespace Umbraco.Web.BackOffice.Filters
ILocalizedTextService localizedTextService,
IOptions globalSettings,
IBackOfficeSignInManager backOfficeSignInManager,
- IBackOfficeAntiforgery backOfficeAntiforgery)
+ IBackOfficeAntiforgery backOfficeAntiforgery,
+ IScopeProvider scopeProvider)
{
_requestCache = requestCache;
_umbracoMapper = umbracoMapper;
@@ -60,6 +63,7 @@ namespace Umbraco.Web.BackOffice.Filters
_globalSettings = globalSettings;
_backOfficeSignInManager = backOfficeSignInManager;
_backOfficeAntiforgery = backOfficeAntiforgery;
+ _scopeProvider = scopeProvider;
}
@@ -95,7 +99,9 @@ namespace Umbraco.Web.BackOffice.Filters
private async Task CheckStaleData(ActionExecutingContext actionContext)
{
- if (actionContext?.HttpContext.Request == null || actionContext.HttpContext.User?.Identity == null)
+ using (var scope = _scopeProvider.CreateScope(autoComplete: true))
+ {
+ if (actionContext?.HttpContext.Request == null || actionContext.HttpContext.User?.Identity == null)
{
return;
}
@@ -151,6 +157,7 @@ namespace Umbraco.Web.BackOffice.Filters
{
await ReSync(user, actionContext);
}
+ }
}
///
diff --git a/src/Umbraco.Web.Common/AspNetCore/UmbracoViewPage.cs b/src/Umbraco.Web.Common/AspNetCore/UmbracoViewPage.cs
index cd429ec458..74b40403f0 100644
--- a/src/Umbraco.Web.Common/AspNetCore/UmbracoViewPage.cs
+++ b/src/Umbraco.Web.Common/AspNetCore/UmbracoViewPage.cs
@@ -1,6 +1,5 @@
using System;
using Microsoft.AspNetCore.Html;
-using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Http.Extensions;
using Microsoft.AspNetCore.Mvc.ModelBinding;
using Microsoft.AspNetCore.Mvc.Razor;
@@ -11,7 +10,6 @@ using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Options;
using Umbraco.Core;
using Umbraco.Core.Configuration.Models;
-using Umbraco.Core.Events;
using Umbraco.Core.IO;
using Umbraco.Core.Logging;
using Umbraco.Core.Models.PublishedContent;
@@ -19,6 +17,7 @@ using Umbraco.Core.Strings;
using Umbraco.Extensions;
using Umbraco.Web.Common.ModelBinders;
using Umbraco.Web.Models;
+using Umbraco.Web.Website;
namespace Umbraco.Web.Common.AspNetCore
{
@@ -32,6 +31,7 @@ namespace Umbraco.Web.Common.AspNetCore
public abstract class UmbracoViewPage : RazorPage
{
private IUmbracoContext _umbracoContext;
+ private UmbracoHelper _helper;
private IUmbracoContextAccessor UmbracoContextAccessor => Context.RequestServices.GetRequiredService();
@@ -43,6 +43,29 @@ namespace Umbraco.Web.Common.AspNetCore
private IIOHelper IOHelper => Context.RequestServices.GetRequiredService();
+
+ ///
+ /// Gets the Umbraco helper.
+ ///
+ public UmbracoHelper Umbraco
+ {
+ get
+ {
+ if (_helper != null) return _helper;
+
+ var model = ViewData.Model;
+ var content = model as IPublishedContent;
+ if (content == null && model is IContentModel)
+ content = ((IContentModel) model).Content;
+
+ _helper = Context.RequestServices.GetRequiredService();
+
+ if (content != null)
+ _helper.AssignedContentItem = content;
+
+ return _helper;
+ }
+ }
///
/// Gets the
///
@@ -190,7 +213,7 @@ namespace Umbraco.Web.Common.AspNetCore
// need to check whether that is possible
Type viewDataModelType = viewDataType.GenericTypeArguments[0];
- if (viewDataModelType.IsAssignableFrom(modelType))
+ if (viewDataModelType != typeof(object) && viewDataModelType.IsAssignableFrom(modelType))
{
return viewData;
}
diff --git a/src/Umbraco.Web.Common/DependencyInjection/UmbracoBuilderExtensions.cs b/src/Umbraco.Web.Common/DependencyInjection/UmbracoBuilderExtensions.cs
index 4b9953edf7..b81b0382aa 100644
--- a/src/Umbraco.Web.Common/DependencyInjection/UmbracoBuilderExtensions.cs
+++ b/src/Umbraco.Web.Common/DependencyInjection/UmbracoBuilderExtensions.cs
@@ -52,6 +52,7 @@ using Umbraco.Web.Macros;
using Umbraco.Web.Security;
using Umbraco.Web.Telemetry;
using Umbraco.Web.Templates;
+using Umbraco.Web.Website;
using IHostingEnvironment = Umbraco.Core.Hosting.IHostingEnvironment;
namespace Umbraco.Web.Common.DependencyInjection
@@ -275,6 +276,8 @@ namespace Umbraco.Web.Common.DependencyInjection
builder.Services.AddSingleton();
+ builder.Services.AddScoped();
+
builder.AddHttpClients();
// TODO: Does this belong in web components??
diff --git a/src/Umbraco.Web.Common/Extensions/HttpRequestExtensions.cs b/src/Umbraco.Web.Common/Extensions/HttpRequestExtensions.cs
index 31e65edf65..29c178e655 100644
--- a/src/Umbraco.Web.Common/Extensions/HttpRequestExtensions.cs
+++ b/src/Umbraco.Web.Common/Extensions/HttpRequestExtensions.cs
@@ -1,4 +1,4 @@
-using System.IO;
+using System.IO;
using System.Net;
using System.Text;
using System.Threading.Tasks;
@@ -74,24 +74,36 @@ namespace Umbraco.Extensions
public static string GetRawBodyString(this HttpRequest request, Encoding encoding = null)
{
- request.Body.Seek(0, SeekOrigin.Begin);
+ if (request.Body.CanSeek)
+ {
+ request.Body.Seek(0, SeekOrigin.Begin);
+ }
using (var reader = new StreamReader(request.Body, encoding ?? Encoding.UTF8, leaveOpen: true))
{
var result = reader.ReadToEnd();
- request.Body.Seek(0, SeekOrigin.Begin);
+ if (request.Body.CanSeek)
+ {
+ request.Body.Seek(0, SeekOrigin.Begin);
+ }
return result;
}
}
public static async Task GetRawBodyStringAsync(this HttpRequest request, Encoding encoding = null)
{
+ if (!request.Body.CanSeek)
+ {
+ request.EnableBuffering();
+ }
+
request.Body.Seek(0, SeekOrigin.Begin);
using (var reader = new StreamReader(request.Body, encoding ?? Encoding.UTF8, leaveOpen: true))
{
var result = await reader.ReadToEndAsync();
request.Body.Seek(0, SeekOrigin.Begin);
+
return result;
}
}
diff --git a/src/Umbraco.Web.Common/Extensions/UrlHelperExtensions.cs b/src/Umbraco.Web.Common/Extensions/UrlHelperExtensions.cs
index 03329547bc..22c4f5fc6a 100644
--- a/src/Umbraco.Web.Common/Extensions/UrlHelperExtensions.cs
+++ b/src/Umbraco.Web.Common/Extensions/UrlHelperExtensions.cs
@@ -1,16 +1,15 @@
using System;
+using System.Globalization;
using System.Linq;
using System.Linq.Expressions;
using Microsoft.AspNetCore.Mvc;
+using Microsoft.AspNetCore.Routing;
using Umbraco.Core;
+using Umbraco.Core.Configuration;
+using Umbraco.Core.Hosting;
+using Umbraco.Core.WebAssets;
using Umbraco.Web.Common.Controllers;
using Umbraco.Web.WebApi;
-using Umbraco.Web.Common.Install;
-using Microsoft.AspNetCore.Routing;
-using Umbraco.Core.Hosting;
-using System.Globalization;
-using Umbraco.Core.Configuration;
-using Umbraco.Core.WebAssets;
namespace Umbraco.Extensions
{
@@ -18,7 +17,7 @@ namespace Umbraco.Extensions
public static class UrlHelperExtensions
{
-
+
///
/// Return the back office url if the back office is installed
diff --git a/src/Umbraco.Web.Website/UmbracoHelper.cs b/src/Umbraco.Web.Common/UmbracoHelper.cs
similarity index 99%
rename from src/Umbraco.Web.Website/UmbracoHelper.cs
rename to src/Umbraco.Web.Common/UmbracoHelper.cs
index ed6d5d36b0..54aeda6b09 100644
--- a/src/Umbraco.Web.Website/UmbracoHelper.cs
+++ b/src/Umbraco.Web.Common/UmbracoHelper.cs
@@ -1,13 +1,13 @@
using System;
using System.Collections.Generic;
+using System.Threading.Tasks;
using System.Xml.XPath;
using Umbraco.Core;
using Umbraco.Core.Dictionary;
using Umbraco.Core.Models.PublishedContent;
-using Umbraco.Core.Templates;
using Umbraco.Core.Strings;
+using Umbraco.Core.Templates;
using Umbraco.Core.Xml;
-using System.Threading.Tasks;
namespace Umbraco.Web.Website
{
@@ -36,15 +36,13 @@ namespace Umbraco.Web.Website
///
///
/// Sets the current page to the context's published content request's content item.
- public UmbracoHelper(IPublishedContent currentPage,
- ICultureDictionaryFactory cultureDictionary,
+ public UmbracoHelper(ICultureDictionaryFactory cultureDictionary,
IUmbracoComponentRenderer componentRenderer,
IPublishedContentQuery publishedContentQuery)
{
_cultureDictionaryFactory = cultureDictionary ?? throw new ArgumentNullException(nameof(cultureDictionary));
_componentRenderer = componentRenderer ?? throw new ArgumentNullException(nameof(componentRenderer));
_publishedContentQuery = publishedContentQuery ?? throw new ArgumentNullException(nameof(publishedContentQuery));
- _currentPage = currentPage;
}
///
diff --git a/src/Umbraco.Web.UI.Client/package-lock.json b/src/Umbraco.Web.UI.Client/package-lock.json
index 452b5c2071..dea27a0d69 100644
--- a/src/Umbraco.Web.UI.Client/package-lock.json
+++ b/src/Umbraco.Web.UI.Client/package-lock.json
@@ -1842,7 +1842,8 @@
"version": "1.5.1",
"resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz",
"integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==",
- "dev": true
+ "dev": true,
+ "optional": true
},
"base64id": {
"version": "1.0.0",
@@ -2051,7 +2052,8 @@
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz",
"integrity": "sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ=",
- "dev": true
+ "dev": true,
+ "optional": true
},
"got": {
"version": "8.3.2",
@@ -2129,6 +2131,7 @@
"resolved": "https://registry.npmjs.org/p-timeout/-/p-timeout-2.0.1.tgz",
"integrity": "sha1-2N0ZeVldLcATnh/ka4tkbLPN8Dg=",
"dev": true,
+ "optional": true,
"requires": {
"p-finally": "^1.0.0"
}
@@ -2170,6 +2173,7 @@
"resolved": "https://registry.npmjs.org/bl/-/bl-1.2.3.tgz",
"integrity": "sha512-pvcNpa0UU69UT341rO6AYy4FVAIkUHuZXRIWbq+zHnsVcRzDDjIAhGuuYoi0d//cwIwtt4pkpKycWEfjdV+vww==",
"dev": true,
+ "optional": true,
"requires": {
"readable-stream": "^2.3.5",
"safe-buffer": "^5.1.1"
@@ -2179,13 +2183,15 @@
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
"integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=",
- "dev": true
+ "dev": true,
+ "optional": true
},
"readable-stream": {
"version": "2.3.7",
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz",
"integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==",
"dev": true,
+ "optional": true,
"requires": {
"core-util-is": "~1.0.0",
"inherits": "~2.0.3",
@@ -2201,6 +2207,7 @@
"resolved": "http://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
"integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==",
"dev": true,
+ "optional": true,
"requires": {
"safe-buffer": "~5.1.0"
}
@@ -2341,6 +2348,7 @@
"resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz",
"integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==",
"dev": true,
+ "optional": true,
"requires": {
"base64-js": "^1.3.1",
"ieee754": "^1.1.13"
@@ -2366,7 +2374,8 @@
"version": "0.2.13",
"resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz",
"integrity": "sha1-DTM+PwDqxQqhRUq9MO+MKl2ackI=",
- "dev": true
+ "dev": true,
+ "optional": true
},
"buffer-equal": {
"version": "1.0.0",
@@ -2563,6 +2572,7 @@
"resolved": "https://registry.npmjs.org/caw/-/caw-2.0.1.tgz",
"integrity": "sha1-bDygcfwZRyCIPC3F2psHS/x+npU=",
"dev": true,
+ "optional": true,
"requires": {
"get-proxy": "^2.0.0",
"isurl": "^1.0.0-alpha5",
@@ -2994,7 +3004,8 @@
"version": "2.20.3",
"resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz",
"integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==",
- "dev": true
+ "dev": true,
+ "optional": true
},
"component-bind": {
"version": "1.0.0",
@@ -3086,6 +3097,7 @@
"resolved": "https://registry.npmjs.org/config-chain/-/config-chain-1.1.12.tgz",
"integrity": "sha1-D96NCRIA616AjK8l/mGMAvSOTvo=",
"dev": true,
+ "optional": true,
"requires": {
"ini": "^1.3.4",
"proto-list": "~1.2.1"
@@ -3141,6 +3153,7 @@
"resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.3.tgz",
"integrity": "sha1-4TDK9+cnkIfFYWwgB9BIVpiYT70=",
"dev": true,
+ "optional": true,
"requires": {
"safe-buffer": "5.1.2"
}
@@ -3582,6 +3595,7 @@
"resolved": "https://registry.npmjs.org/decompress/-/decompress-4.2.1.tgz",
"integrity": "sha512-e48kc2IjU+2Zw8cTb6VZcJQ3lgVbS4uuB1TfCHbiZIP/haNXm+SVyhu+87jts5/3ROpd82GSVCoNs/z8l4ZOaQ==",
"dev": true,
+ "optional": true,
"requires": {
"decompress-tar": "^4.0.0",
"decompress-tarbz2": "^4.0.0",
@@ -3598,6 +3612,7 @@
"resolved": "https://registry.npmjs.org/make-dir/-/make-dir-1.3.0.tgz",
"integrity": "sha1-ecEDO4BRW9bSTsmTPoYMp17ifww=",
"dev": true,
+ "optional": true,
"requires": {
"pify": "^3.0.0"
},
@@ -3606,7 +3621,8 @@
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz",
"integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=",
- "dev": true
+ "dev": true,
+ "optional": true
}
}
}
@@ -3617,6 +3633,7 @@
"resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-3.3.0.tgz",
"integrity": "sha1-gKTdMjdIOEv6JICDYirt7Jgq3/M=",
"dev": true,
+ "optional": true,
"requires": {
"mimic-response": "^1.0.0"
}
@@ -3626,6 +3643,7 @@
"resolved": "https://registry.npmjs.org/decompress-tar/-/decompress-tar-4.1.1.tgz",
"integrity": "sha1-cYy9P8sWIJcW5womuE57pFkuWvE=",
"dev": true,
+ "optional": true,
"requires": {
"file-type": "^5.2.0",
"is-stream": "^1.1.0",
@@ -3636,7 +3654,8 @@
"version": "5.2.0",
"resolved": "https://registry.npmjs.org/file-type/-/file-type-5.2.0.tgz",
"integrity": "sha1-LdvqfHP/42No365J3DOMBYwritY=",
- "dev": true
+ "dev": true,
+ "optional": true
}
}
},
@@ -3645,6 +3664,7 @@
"resolved": "https://registry.npmjs.org/decompress-tarbz2/-/decompress-tarbz2-4.1.1.tgz",
"integrity": "sha1-MIKluIDqQEOBY0nzeLVsUWvho5s=",
"dev": true,
+ "optional": true,
"requires": {
"decompress-tar": "^4.1.0",
"file-type": "^6.1.0",
@@ -3657,7 +3677,8 @@
"version": "6.2.0",
"resolved": "https://registry.npmjs.org/file-type/-/file-type-6.2.0.tgz",
"integrity": "sha1-5QzXXTVv/tTjBtxPW89Sp5kDqRk=",
- "dev": true
+ "dev": true,
+ "optional": true
}
}
},
@@ -3666,6 +3687,7 @@
"resolved": "https://registry.npmjs.org/decompress-targz/-/decompress-targz-4.1.1.tgz",
"integrity": "sha1-wJvDXE0R894J8tLaU+neI+fOHu4=",
"dev": true,
+ "optional": true,
"requires": {
"decompress-tar": "^4.1.1",
"file-type": "^5.2.0",
@@ -3676,7 +3698,8 @@
"version": "5.2.0",
"resolved": "https://registry.npmjs.org/file-type/-/file-type-5.2.0.tgz",
"integrity": "sha1-LdvqfHP/42No365J3DOMBYwritY=",
- "dev": true
+ "dev": true,
+ "optional": true
}
}
},
@@ -3685,6 +3708,7 @@
"resolved": "https://registry.npmjs.org/decompress-unzip/-/decompress-unzip-4.0.1.tgz",
"integrity": "sha1-3qrM39FK6vhVePczroIQ+bSEj2k=",
"dev": true,
+ "optional": true,
"requires": {
"file-type": "^3.8.0",
"get-stream": "^2.2.0",
@@ -3696,13 +3720,15 @@
"version": "3.9.0",
"resolved": "https://registry.npmjs.org/file-type/-/file-type-3.9.0.tgz",
"integrity": "sha1-JXoHg4TR24CHvESdEH1SpSZyuek=",
- "dev": true
+ "dev": true,
+ "optional": true
},
"get-stream": {
"version": "2.3.1",
"resolved": "https://registry.npmjs.org/get-stream/-/get-stream-2.3.1.tgz",
"integrity": "sha1-Xzj5PzRgCWZu4BUKBUFn+Rvdld4=",
"dev": true,
+ "optional": true,
"requires": {
"object-assign": "^4.0.1",
"pinkie-promise": "^2.0.0"
@@ -3712,7 +3738,8 @@
"version": "4.1.1",
"resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
"integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=",
- "dev": true
+ "dev": true,
+ "optional": true
}
}
},
@@ -4000,7 +4027,8 @@
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz",
"integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=",
- "dev": true
+ "dev": true,
+ "optional": true
}
}
},
@@ -4017,7 +4045,8 @@
"version": "0.1.4",
"resolved": "https://registry.npmjs.org/duplexer3/-/duplexer3-0.1.4.tgz",
"integrity": "sha1-7gHdHKwO08vH/b6jfcCo8c4ALOI=",
- "dev": true
+ "dev": true,
+ "optional": true
},
"duplexify": {
"version": "3.7.1",
@@ -4662,6 +4691,7 @@
"resolved": "https://registry.npmjs.org/execa/-/execa-1.0.0.tgz",
"integrity": "sha512-adbxcyWV46qiHyvSp50TKt05tB4tK3HcmF7/nxfAdhnox83seTDbwnaqKO4sXRy7roHAIFqJP/Rw/AuEbX61LA==",
"dev": true,
+ "optional": true,
"requires": {
"cross-spawn": "^6.0.0",
"get-stream": "^4.0.0",
@@ -4803,6 +4833,7 @@
"resolved": "https://registry.npmjs.org/ext-list/-/ext-list-2.2.2.tgz",
"integrity": "sha1-C5jmTtgvWs8PKTG6v2khLvUt3Tc=",
"dev": true,
+ "optional": true,
"requires": {
"mime-db": "^1.28.0"
}
@@ -4812,6 +4843,7 @@
"resolved": "https://registry.npmjs.org/ext-name/-/ext-name-5.0.0.tgz",
"integrity": "sha1-cHgZgdGD7hXROZPIgiBFxQbI8KY=",
"dev": true,
+ "optional": true,
"requires": {
"ext-list": "^2.0.0",
"sort-keys-length": "^1.0.0"
@@ -5049,6 +5081,7 @@
"resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.1.0.tgz",
"integrity": "sha1-JcfInLH5B3+IkbvmHY85Dq4lbx4=",
"dev": true,
+ "optional": true,
"requires": {
"pend": "~1.2.0"
}
@@ -5087,13 +5120,15 @@
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/filename-reserved-regex/-/filename-reserved-regex-2.0.0.tgz",
"integrity": "sha1-q/c9+rc10EVECr/qLZHzieu/oik=",
- "dev": true
+ "dev": true,
+ "optional": true
},
"filenamify": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/filenamify/-/filenamify-2.1.0.tgz",
"integrity": "sha1-iPr0lfsbR6v9YSMAACoWIoxnfuk=",
"dev": true,
+ "optional": true,
"requires": {
"filename-reserved-regex": "^2.0.0",
"strip-outer": "^1.0.0",
@@ -5442,7 +5477,8 @@
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz",
"integrity": "sha1-a+Dem+mYzhavivwkSXue6bfM2a0=",
- "dev": true
+ "dev": true,
+ "optional": true
},
"fs-mkdirp-stream": {
"version": "1.0.0",
@@ -5489,7 +5525,8 @@
"ansi-regex": {
"version": "2.1.1",
"bundled": true,
- "dev": true
+ "dev": true,
+ "optional": true
},
"aproba": {
"version": "1.2.0",
@@ -5510,12 +5547,14 @@
"balanced-match": {
"version": "1.0.0",
"bundled": true,
- "dev": true
+ "dev": true,
+ "optional": true
},
"brace-expansion": {
"version": "1.1.11",
"bundled": true,
"dev": true,
+ "optional": true,
"requires": {
"balanced-match": "^1.0.0",
"concat-map": "0.0.1"
@@ -5530,17 +5569,20 @@
"code-point-at": {
"version": "1.1.0",
"bundled": true,
- "dev": true
+ "dev": true,
+ "optional": true
},
"concat-map": {
"version": "0.0.1",
"bundled": true,
- "dev": true
+ "dev": true,
+ "optional": true
},
"console-control-strings": {
"version": "1.1.0",
"bundled": true,
- "dev": true
+ "dev": true,
+ "optional": true
},
"core-util-is": {
"version": "1.0.2",
@@ -5657,7 +5699,8 @@
"inherits": {
"version": "2.0.3",
"bundled": true,
- "dev": true
+ "dev": true,
+ "optional": true
},
"ini": {
"version": "1.3.5",
@@ -5669,6 +5712,7 @@
"version": "1.0.0",
"bundled": true,
"dev": true,
+ "optional": true,
"requires": {
"number-is-nan": "^1.0.0"
}
@@ -5683,6 +5727,7 @@
"version": "3.0.4",
"bundled": true,
"dev": true,
+ "optional": true,
"requires": {
"brace-expansion": "^1.1.7"
}
@@ -5690,12 +5735,14 @@
"minimist": {
"version": "0.0.8",
"bundled": true,
- "dev": true
+ "dev": true,
+ "optional": true
},
"minipass": {
"version": "2.3.5",
"bundled": true,
"dev": true,
+ "optional": true,
"requires": {
"safe-buffer": "^5.1.2",
"yallist": "^3.0.0"
@@ -5714,6 +5761,7 @@
"version": "0.5.1",
"bundled": true,
"dev": true,
+ "optional": true,
"requires": {
"minimist": "0.0.8"
}
@@ -5794,7 +5842,8 @@
"number-is-nan": {
"version": "1.0.1",
"bundled": true,
- "dev": true
+ "dev": true,
+ "optional": true
},
"object-assign": {
"version": "4.1.1",
@@ -5806,6 +5855,7 @@
"version": "1.4.0",
"bundled": true,
"dev": true,
+ "optional": true,
"requires": {
"wrappy": "1"
}
@@ -5891,7 +5941,8 @@
"safe-buffer": {
"version": "5.1.2",
"bundled": true,
- "dev": true
+ "dev": true,
+ "optional": true
},
"safer-buffer": {
"version": "2.1.2",
@@ -5927,6 +5978,7 @@
"version": "1.0.2",
"bundled": true,
"dev": true,
+ "optional": true,
"requires": {
"code-point-at": "^1.0.0",
"is-fullwidth-code-point": "^1.0.0",
@@ -5946,6 +5998,7 @@
"version": "3.0.1",
"bundled": true,
"dev": true,
+ "optional": true,
"requires": {
"ansi-regex": "^2.0.0"
}
@@ -5989,12 +6042,14 @@
"wrappy": {
"version": "1.0.2",
"bundled": true,
- "dev": true
+ "dev": true,
+ "optional": true
},
"yallist": {
"version": "3.0.3",
"bundled": true,
- "dev": true
+ "dev": true,
+ "optional": true
}
}
},
@@ -6021,6 +6076,7 @@
"resolved": "https://registry.npmjs.org/get-proxy/-/get-proxy-2.1.0.tgz",
"integrity": "sha1-NJ8rTZHUTE1NTpy6KtkBQ/rF75M=",
"dev": true,
+ "optional": true,
"requires": {
"npm-conf": "^1.1.0"
}
@@ -6029,13 +6085,15 @@
"version": "4.0.1",
"resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-4.0.1.tgz",
"integrity": "sha1-uWjGsKBDhDJJAui/Gl3zJXmkUP4=",
- "dev": true
+ "dev": true,
+ "optional": true
},
"get-stream": {
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz",
"integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==",
"dev": true,
+ "optional": true,
"requires": {
"pump": "^3.0.0"
},
@@ -6045,6 +6103,7 @@
"resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz",
"integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==",
"dev": true,
+ "optional": true,
"requires": {
"end-of-stream": "^1.1.0",
"once": "^1.3.1"
@@ -6157,7 +6216,8 @@
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz",
"integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==",
- "dev": true
+ "dev": true,
+ "optional": true
},
"pump": {
"version": "3.0.0",
@@ -7262,7 +7322,8 @@
"version": "1.4.2",
"resolved": "https://registry.npmjs.org/has-symbol-support-x/-/has-symbol-support-x-1.4.2.tgz",
"integrity": "sha1-FAn5i8ACR9pF2mfO4KNvKC/yZFU=",
- "dev": true
+ "dev": true,
+ "optional": true
},
"has-symbols": {
"version": "1.0.0",
@@ -7275,6 +7336,7 @@
"resolved": "https://registry.npmjs.org/has-to-string-tag-x/-/has-to-string-tag-x-1.4.1.tgz",
"integrity": "sha1-oEWrOD17SyASoAFIqwql8pAETU0=",
"dev": true,
+ "optional": true,
"requires": {
"has-symbol-support-x": "^1.4.1"
}
@@ -7480,7 +7542,8 @@
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz",
"integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==",
- "dev": true
+ "dev": true,
+ "optional": true
},
"ignore": {
"version": "4.0.6",
@@ -7620,7 +7683,8 @@
"version": "0.6.1",
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
"integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
- "dev": true
+ "dev": true,
+ "optional": true
},
"svgo": {
"version": "1.3.2",
@@ -7692,6 +7756,7 @@
"resolved": "https://registry.npmjs.org/indent-string/-/indent-string-2.1.0.tgz",
"integrity": "sha1-ji1INIdCEhtKghi3oTfppSBJ3IA=",
"dev": true,
+ "optional": true,
"requires": {
"repeating": "^2.0.0"
}
@@ -8018,7 +8083,8 @@
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/is-finite/-/is-finite-1.1.0.tgz",
"integrity": "sha512-cdyMtqX/BOqqNBBiKlIVkytNHm49MtMlYyn1zxzvJKWmFMlGzm+ry5BBfYyeY9YmNKbRSo/o7OX9w9ale0wg3w==",
- "dev": true
+ "dev": true,
+ "optional": true
},
"is-fullwidth-code-point": {
"version": "1.0.0",
@@ -8068,7 +8134,8 @@
"version": "4.0.1",
"resolved": "https://registry.npmjs.org/is-natural-number/-/is-natural-number-4.0.1.tgz",
"integrity": "sha1-q5124dtM7VHjXeDHLr7PCfc0zeg=",
- "dev": true
+ "dev": true,
+ "optional": true
},
"is-negated-glob": {
"version": "1.0.0",
@@ -8106,13 +8173,15 @@
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/is-object/-/is-object-1.0.2.tgz",
"integrity": "sha512-2rRIahhZr2UWb45fIOuvZGpFtz0TyOZLf32KxBbSoUCeZR495zCKlWUKKUByk3geS2eAs7ZAABt0Y/Rx0GiQGA==",
- "dev": true
+ "dev": true,
+ "optional": true
},
"is-plain-obj": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-1.1.0.tgz",
"integrity": "sha1-caUMhCnfync8kqOQpKA7OfzVHT4=",
- "dev": true
+ "dev": true,
+ "optional": true
},
"is-plain-object": {
"version": "2.0.4",
@@ -8182,13 +8251,15 @@
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/is-retry-allowed/-/is-retry-allowed-1.2.0.tgz",
"integrity": "sha1-13hIi9CkZmo76KFIK58rqv7eqLQ=",
- "dev": true
+ "dev": true,
+ "optional": true
},
"is-stream": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz",
"integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=",
- "dev": true
+ "dev": true,
+ "optional": true
},
"is-svg": {
"version": "3.0.0",
@@ -8283,6 +8354,7 @@
"resolved": "https://registry.npmjs.org/isurl/-/isurl-1.0.0.tgz",
"integrity": "sha1-sn9PSfPNqj6kSgpbfzRi5u3DnWc=",
"dev": true,
+ "optional": true,
"requires": {
"has-to-string-tag-x": "^1.2.0",
"is-object": "^1.0.1"
@@ -9178,7 +9250,8 @@
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-1.0.1.tgz",
"integrity": "sha1-b54wtHCE2XGnyCD/FabFFnt0wm8=",
- "dev": true
+ "dev": true,
+ "optional": true
},
"lpad-align": {
"version": "1.1.2",
@@ -9248,7 +9321,8 @@
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/map-obj/-/map-obj-1.0.1.tgz",
"integrity": "sha1-2TPOuSBdgr3PSIb2dCvcK03qFG0=",
- "dev": true
+ "dev": true,
+ "optional": true
},
"map-visit": {
"version": "1.0.0",
@@ -9416,7 +9490,8 @@
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-1.0.1.tgz",
"integrity": "sha1-SSNTiHju9CBjy4o+OweYeBSHqxs=",
- "dev": true
+ "dev": true,
+ "optional": true
},
"minimatch": {
"version": "3.0.4",
@@ -12763,6 +12838,7 @@
"resolved": "https://registry.npmjs.org/npm-conf/-/npm-conf-1.1.3.tgz",
"integrity": "sha1-JWzEe9DiGMJZxOlVC/QTvCGSr/k=",
"dev": true,
+ "optional": true,
"requires": {
"config-chain": "^1.1.11",
"pify": "^3.0.0"
@@ -12772,7 +12848,8 @@
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz",
"integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=",
- "dev": true
+ "dev": true,
+ "optional": true
}
}
},
@@ -12781,6 +12858,7 @@
"resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz",
"integrity": "sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8=",
"dev": true,
+ "optional": true,
"requires": {
"path-key": "^2.0.0"
}
@@ -13149,7 +13227,8 @@
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz",
"integrity": "sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4=",
- "dev": true
+ "dev": true,
+ "optional": true
},
"p-is-promise": {
"version": "1.1.0",
@@ -13186,6 +13265,7 @@
"resolved": "https://registry.npmjs.org/p-timeout/-/p-timeout-1.2.1.tgz",
"integrity": "sha1-XrOzU7f86Z8QGhA4iAuwVOu+o4Y=",
"dev": true,
+ "optional": true,
"requires": {
"p-finally": "^1.0.0"
}
@@ -13376,7 +13456,8 @@
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz",
"integrity": "sha1-elfrVQpng/kRUzH89GY9XI4AelA=",
- "dev": true
+ "dev": true,
+ "optional": true
},
"performance-now": {
"version": "2.1.0",
@@ -13883,7 +13964,8 @@
"version": "1.2.4",
"resolved": "https://registry.npmjs.org/proto-list/-/proto-list-1.2.4.tgz",
"integrity": "sha1-IS1b/hMYMGpCD2QCuOJv85ZHqEk=",
- "dev": true
+ "dev": true,
+ "optional": true
},
"prr": {
"version": "1.0.1",
@@ -14241,6 +14323,7 @@
"resolved": "https://registry.npmjs.org/repeating/-/repeating-2.0.1.tgz",
"integrity": "sha1-UhTFOpJtNVJwdSf7q0FdvAjQbdo=",
"dev": true,
+ "optional": true,
"requires": {
"is-finite": "^1.0.0"
}
@@ -14595,6 +14678,7 @@
"resolved": "https://registry.npmjs.org/seek-bzip/-/seek-bzip-1.0.6.tgz",
"integrity": "sha512-e1QtP3YL5tWww8uKaOCQ18UxIT2laNBXHjV/S2WYCiK4udiv8lkG89KRIoCjUagnAmCBurjF4zEVX2ByBbnCjQ==",
"dev": true,
+ "optional": true,
"requires": {
"commander": "^2.8.1"
}
@@ -14989,6 +15073,7 @@
"resolved": "https://registry.npmjs.org/sort-keys/-/sort-keys-1.1.2.tgz",
"integrity": "sha1-RBttTTRnmPG05J6JIK37oOVD+a0=",
"dev": true,
+ "optional": true,
"requires": {
"is-plain-obj": "^1.0.0"
}
@@ -14998,6 +15083,7 @@
"resolved": "https://registry.npmjs.org/sort-keys-length/-/sort-keys-length-1.0.1.tgz",
"integrity": "sha1-nLb09OnkgVWmqgZx7dM2/xR5oYg=",
"dev": true,
+ "optional": true,
"requires": {
"sort-keys": "^1.0.0"
}
@@ -15327,6 +15413,7 @@
"resolved": "https://registry.npmjs.org/strip-dirs/-/strip-dirs-2.1.0.tgz",
"integrity": "sha1-SYdzYmT8NEzyD2w0rKnRPR1O1sU=",
"dev": true,
+ "optional": true,
"requires": {
"is-natural-number": "^4.0.1"
}
@@ -15335,7 +15422,8 @@
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz",
"integrity": "sha1-u0P/VZim6wXYm1n80SnJgzE2Br8=",
- "dev": true
+ "dev": true,
+ "optional": true
},
"strip-final-newline": {
"version": "2.0.0",
@@ -15365,6 +15453,7 @@
"resolved": "https://registry.npmjs.org/strip-outer/-/strip-outer-1.0.1.tgz",
"integrity": "sha1-sv0qv2YEudHmATBXGV34Nrip1jE=",
"dev": true,
+ "optional": true,
"requires": {
"escape-string-regexp": "^1.0.2"
}
@@ -15490,6 +15579,7 @@
"resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-1.6.2.tgz",
"integrity": "sha1-jqVdqzeXIlPZqa+Q/c1VmuQ1xVU=",
"dev": true,
+ "optional": true,
"requires": {
"bl": "^1.0.0",
"buffer-alloc": "^1.2.0",
@@ -15504,13 +15594,15 @@
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
"integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=",
- "dev": true
+ "dev": true,
+ "optional": true
},
"readable-stream": {
"version": "2.3.7",
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz",
"integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==",
"dev": true,
+ "optional": true,
"requires": {
"core-util-is": "~1.0.0",
"inherits": "~2.0.3",
@@ -15526,6 +15618,7 @@
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
"integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==",
"dev": true,
+ "optional": true,
"requires": {
"safe-buffer": "~5.1.0"
}
@@ -15536,13 +15629,15 @@
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/temp-dir/-/temp-dir-1.0.0.tgz",
"integrity": "sha1-CnwOom06Oa+n4OvqnB/AvE2qAR0=",
- "dev": true
+ "dev": true,
+ "optional": true
},
"tempfile": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/tempfile/-/tempfile-2.0.0.tgz",
"integrity": "sha1-awRGhWqbERTRhW/8vlCczLCXcmU=",
"dev": true,
+ "optional": true,
"requires": {
"temp-dir": "^1.0.0",
"uuid": "^3.0.1"
@@ -15637,7 +15732,8 @@
"version": "4.0.1",
"resolved": "https://registry.npmjs.org/timed-out/-/timed-out-4.0.1.tgz",
"integrity": "sha1-8y6srFoXW+ol1/q1Zas+2HQe9W8=",
- "dev": true
+ "dev": true,
+ "optional": true
},
"timers-ext": {
"version": "0.1.7",
@@ -15694,7 +15790,8 @@
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/to-buffer/-/to-buffer-1.1.1.tgz",
"integrity": "sha1-STvUj2LXxD/N7TE6A9ytsuEhOoA=",
- "dev": true
+ "dev": true,
+ "optional": true
},
"to-fast-properties": {
"version": "2.0.0",
@@ -15796,6 +15893,7 @@
"resolved": "https://registry.npmjs.org/trim-repeated/-/trim-repeated-1.0.0.tgz",
"integrity": "sha1-42RqLqTokTEr9+rObPsFOAvAHCE=",
"dev": true,
+ "optional": true,
"requires": {
"escape-string-regexp": "^1.0.2"
}
@@ -15931,6 +16029,7 @@
"resolved": "https://registry.npmjs.org/unbzip2-stream/-/unbzip2-stream-1.4.3.tgz",
"integrity": "sha512-mlExGW4w71ebDJviH16lQLtZS32VKqsSfk80GCfUlwT/4/hNRFsoscrF/c++9xinkMzECL1uL9DDwXqFWkruPg==",
"dev": true,
+ "optional": true,
"requires": {
"buffer": "^5.2.1",
"through": "^2.3.8"
@@ -16139,7 +16238,8 @@
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/url-to-options/-/url-to-options-1.0.1.tgz",
"integrity": "sha1-FQWgOiiaSMvXpDTvuu7FBV9WM6k=",
- "dev": true
+ "dev": true,
+ "optional": true
},
"use": {
"version": "3.1.1",
@@ -16633,6 +16733,7 @@
"resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.10.0.tgz",
"integrity": "sha1-x+sXyT4RLLEIb6bY5R+wZnt5pfk=",
"dev": true,
+ "optional": true,
"requires": {
"buffer-crc32": "~0.2.3",
"fd-slicer": "~1.1.0"
diff --git a/src/Umbraco.Web.UI.Client/src/common/resources/content.resource.js b/src/Umbraco.Web.UI.Client/src/common/resources/content.resource.js
index b6f5d99d9f..70861c9a86 100644
--- a/src/Umbraco.Web.UI.Client/src/common/resources/content.resource.js
+++ b/src/Umbraco.Web.UI.Client/src/common/resources/content.resource.js
@@ -547,7 +547,7 @@ function contentResource($q, $http, umbDataFormatter, umbRequestHelper) {
$http.get(
umbRequestHelper.getApiUrl(
"contentApiBaseUrl",
- "GetEmpty",
+ "GetEmptyBlueprint",
{ blueprintId: blueprintId, parentId: parentId })),
'Failed to retrieve blueprint for id ' + blueprintId)
.then(function (result) {
@@ -639,7 +639,7 @@ function contentResource($q, $http, umbDataFormatter, umbRequestHelper) {
else if (options.orderDirection === "desc") {
options.orderDirection = "Descending";
}
-
+
//converts the value to a js bool
function toBool(v) {
if (Utilities.isNumber(v)) {
diff --git a/src/Umbraco.Web.UI.Client/src/common/resources/entity.resource.js b/src/Umbraco.Web.UI.Client/src/common/resources/entity.resource.js
index 838e8f1b80..0e271c1cc8 100644
--- a/src/Umbraco.Web.UI.Client/src/common/resources/entity.resource.js
+++ b/src/Umbraco.Web.UI.Client/src/common/resources/entity.resource.js
@@ -220,7 +220,7 @@ function entityResource($q, $http, umbRequestHelper) {
}),
'Failed to anchors data for rte content ' + rteContent);
},
-
+
/**
* @ngdoc method
* @name umbraco.resources.entityResource#getByIds
@@ -246,6 +246,10 @@ function entityResource($q, $http, umbRequestHelper) {
*/
getByIds: function (ids, type) {
+ if (!ids || ids.length === 0) {
+ return $q.when([]);
+ }
+
var query = "type=" + type;
return umbRequestHelper.resourcePromise(
@@ -321,7 +325,7 @@ function entityResource($q, $http, umbRequestHelper) {
getAll: function (type, postFilter) {
//need to build the query string manually
var query = "type=" + type + "&postFilter=" + (postFilter ? encodeURIComponent(postFilter) : "");
-
+
return umbRequestHelper.resourcePromise(
$http.get(
umbRequestHelper.getApiUrl(