diff --git a/src/Umbraco.Core/TypeExtensions.cs b/src/Umbraco.Core/TypeExtensions.cs
index 3208c1fbe8..76dc79c219 100644
--- a/src/Umbraco.Core/TypeExtensions.cs
+++ b/src/Umbraco.Core/TypeExtensions.cs
@@ -425,7 +425,28 @@ namespace Umbraco.Core
assemblyName.FullName.StartsWith("App_Code.") ? "App_Code" : assemblyName.Name);
}
+ ///
+ /// If the given is an array or some other collection
+ /// comprised of 0 or more instances of a "subtype", get that type
+ ///
+ /// the source type
+ ///
+ internal static Type GetEnumeratedType(this Type type)
+ {
+ if (typeof(IEnumerable).IsAssignableFrom(type) == false)
+ return null;
+ // provided by Array
+ var elType = type.GetElementType();
+ if (null != elType) return elType;
+
+ // otherwise provided by collection
+ var elTypes = type.GetGenericArguments();
+ if (elTypes.Length > 0) return elTypes[0];
+
+ // otherwise is not an 'enumerated' type
+ return null;
+ }
}
}
\ No newline at end of file
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 5e0f5deada..3defb691aa 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
@@ -166,24 +166,17 @@ function entityResource($q, $http, umbRequestHelper) {
*/
getByIds: function (ids, type) {
- var query = "";
- _.each(ids, function(item) {
- query += "ids=" + item + "&";
- });
-
- // if ids array is empty we need a empty variable in the querystring otherwise the service returns a error
- if (ids.length === 0) {
- query += "ids=&";
- }
-
- query += "type=" + type;
+ var query = "type=" + type;
return umbRequestHelper.resourcePromise(
- $http.get(
+ $http.post(
umbRequestHelper.getApiUrl(
"entityApiBaseUrl",
"GetByIds",
- query)),
+ query),
+ {
+ ids: ids
+ }),
'Failed to retrieve entity data for ids ' + ids);
},
diff --git a/src/Umbraco.Web/Editors/EntityController.cs b/src/Umbraco.Web/Editors/EntityController.cs
index 6cdedfd352..40cec56a8e 100644
--- a/src/Umbraco.Web/Editors/EntityController.cs
+++ b/src/Umbraco.Web/Editors/EntityController.cs
@@ -55,7 +55,7 @@ namespace Umbraco.Web.Editors
{
//we are not also including the Udi[] overload because that is HttpPost only so there won't be any ambiguity
controllerSettings.Services.Replace(typeof(IHttpActionSelector), new ParameterSwapControllerActionSelector(
- new ParameterSwapControllerActionSelector.ParameterSwapInfo("GetByIds", "ids", typeof(int[]), typeof(Guid[]) )));
+ new ParameterSwapControllerActionSelector.ParameterSwapInfo("GetByIds", "ids", typeof(int[]), typeof(Guid[]), typeof(Udi[]) )));
}
}
@@ -263,8 +263,12 @@ namespace Umbraco.Web.Editors
///
///
///
+ ///
+ /// We allow for POST because there could be quite a lot of Ids
+ ///
[HttpGet]
- public IEnumerable GetByIds([FromUri]int[] ids, UmbracoEntityTypes type)
+ [HttpPost]
+ public IEnumerable GetByIds([FromJsonPath]int[] ids, UmbracoEntityTypes type)
{
if (ids == null)
{
@@ -279,8 +283,12 @@ namespace Umbraco.Web.Editors
///
///
///
+ ///
+ /// We allow for POST because there could be quite a lot of Ids
+ ///
[HttpGet]
- public IEnumerable GetByIds([FromUri]Guid[] ids, UmbracoEntityTypes type)
+ [HttpPost]
+ public IEnumerable GetByIds([FromJsonPath]Guid[] ids, UmbracoEntityTypes type)
{
if (ids == null)
{
@@ -288,7 +296,7 @@ namespace Umbraco.Web.Editors
}
return GetResultForKeys(ids, type);
}
-
+
///
/// Get entities by string ids - will try to convert to the correct id type (int, guid, udi)
///
@@ -296,8 +304,9 @@ namespace Umbraco.Web.Editors
///
///
///
- /// We only allow for POST because there could be quite a lot of Ids
+ /// We allow for POST because there could be quite a lot of Ids
///
+ [HttpGet]
[HttpPost]
public IEnumerable GetByIds([FromJsonPath]Udi[] ids, [FromUri]UmbracoEntityTypes type)
{
diff --git a/src/Umbraco.Web/Editors/FromJsonPathAttribute.cs b/src/Umbraco.Web/Editors/FromJsonPathAttribute.cs
index 3cadd2b6ca..bb275f8fa2 100644
--- a/src/Umbraco.Web/Editors/FromJsonPathAttribute.cs
+++ b/src/Umbraco.Web/Editors/FromJsonPathAttribute.cs
@@ -1,8 +1,12 @@
+using System.Collections.Generic;
using System.Net.Http;
+using System.Web.Http;
using System.Web.Http.Controllers;
using System.Web.Http.ModelBinding;
+using System.Web.Http.ValueProviders;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
+using Umbraco.Core;
namespace Umbraco.Web.Editors
{
@@ -23,6 +27,7 @@ namespace Umbraco.Web.Editors
internal class FromJsonPathAttribute : ModelBinderAttribute
{
private readonly string _jsonPath;
+ private readonly FromUriAttribute _fromUriAttribute = new FromUriAttribute();
public FromJsonPathAttribute()
{
@@ -33,10 +38,17 @@ namespace Umbraco.Web.Editors
_jsonPath = jsonPath;
}
+ public override IEnumerable GetValueProviderFactories(HttpConfiguration configuration)
+ {
+ return _fromUriAttribute.GetValueProviderFactories(configuration);
+ }
+
public override HttpParameterBinding GetBinding(HttpParameterDescriptor parameter)
{
var config = parameter.Configuration;
- var binder = new JsonPathBinder(_jsonPath);
+ //get the default binder, we'll use that if it's a GET or if the body is empty
+ var underlyingBinder = base.GetModelBinder(config, parameter.ParameterType);
+ var binder = new JsonPathBinder(underlyingBinder, _jsonPath);
var valueProviderFactories = GetValueProviderFactories(config);
return new ModelBinderParameterBinding(parameter, binder, valueProviderFactories);
@@ -44,17 +56,30 @@ namespace Umbraco.Web.Editors
private class JsonPathBinder : IModelBinder
{
+ private readonly IModelBinder _underlyingBinder;
private readonly string _jsonPath;
- public JsonPathBinder(string jsonPath)
+ public JsonPathBinder(IModelBinder underlyingBinder, string jsonPath)
{
+ _underlyingBinder = underlyingBinder;
_jsonPath = jsonPath;
}
public bool BindModel(HttpActionContext actionContext, ModelBindingContext bindingContext)
{
+ if (actionContext.Request.Method == HttpMethod.Get)
+ {
+ return _underlyingBinder.BindModel(actionContext, bindingContext);
+ }
+
var requestContent = new HttpMessageContent(actionContext.Request);
var strJson = requestContent.HttpRequestMessage.Content.ReadAsStringAsync().Result;
+
+ if (strJson.IsNullOrWhiteSpace())
+ {
+ return _underlyingBinder.BindModel(actionContext, bindingContext);
+ }
+
var json = JsonConvert.DeserializeObject(strJson);
//if no explicit json path then use the model name
diff --git a/src/Umbraco.Web/Editors/ParameterSwapControllerActionSelector.cs b/src/Umbraco.Web/Editors/ParameterSwapControllerActionSelector.cs
index 75916f6272..6eb2856912 100644
--- a/src/Umbraco.Web/Editors/ParameterSwapControllerActionSelector.cs
+++ b/src/Umbraco.Web/Editors/ParameterSwapControllerActionSelector.cs
@@ -42,33 +42,24 @@ namespace Umbraco.Web.Editors
if (found != null)
{
- if (controllerContext.Request.Method == HttpMethod.Get)
+ HttpActionDescriptor method;
+ if (TryBindFromUri(controllerContext, found, out method))
{
- var requestParam = HttpUtility.ParseQueryString(controllerContext.Request.RequestUri.Query).Get(found.ParamName);
-
- if (requestParam != null)
- {
- var paramTypes = found.SupportedTypes;
-
- foreach (var paramType in paramTypes)
- {
- var converted = requestParam.TryConvertTo(paramType);
- if (converted)
- {
- var method = MatchByType(paramType, controllerContext, found);
- if (method != null)
- return method;
- }
- }
- }
+ return method;
}
- else if (controllerContext.Request.Method == HttpMethod.Post)
- {
+ //if it's a post we can try to read from the body and bind from th
+ if (controllerContext.Request.Method == HttpMethod.Post)
+ {
var requestContent = new HttpMessageContent(controllerContext.Request);
var strJson = requestContent.HttpRequestMessage.Content.ReadAsStringAsync().Result;
var json = JsonConvert.DeserializeObject(strJson);
+ if (json == null)
+ {
+ return base.SelectAction(controllerContext);
+ }
+
var requestParam = json[found.ParamName];
if (requestParam != null)
@@ -82,7 +73,7 @@ namespace Umbraco.Web.Editors
var converted = requestParam.ToObject(paramType);
if (converted != null)
{
- var method = MatchByType(paramType, controllerContext, found);
+ method = MatchByType(paramType, controllerContext, found);
if (method != null)
return method;
}
@@ -102,6 +93,34 @@ namespace Umbraco.Web.Editors
return base.SelectAction(controllerContext);
}
+ private bool TryBindFromUri(HttpControllerContext controllerContext, ParameterSwapInfo found, out HttpActionDescriptor method)
+ {
+ var requestParam = HttpUtility.ParseQueryString(controllerContext.Request.RequestUri.Query).Get(found.ParamName);
+
+ if (requestParam != null)
+ {
+ var paramTypes = found.SupportedTypes;
+
+ foreach (var paramType in paramTypes)
+ {
+ //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)
+ {
+ method = MatchByType(paramType, controllerContext, found);
+ if (method != null)
+ return true;
+ }
+ }
+ }
+
+ method = null;
+ return false;
+ }
+
private static ReflectedHttpActionDescriptor MatchByType(Type idType, HttpControllerContext controllerContext, ParameterSwapInfo found)
{
var controllerType = controllerContext.Controller.GetType();