Gets FromJsonPath working for EntityController to have GetByIds with all types of Ids for both GET and POST
This commit is contained in:
@@ -425,7 +425,28 @@ namespace Umbraco.Core
|
||||
assemblyName.FullName.StartsWith("App_Code.") ? "App_Code" : assemblyName.Name);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// If the given <paramref name="type"/> is an array or some other collection
|
||||
/// comprised of 0 or more instances of a "subtype", get that type
|
||||
/// </summary>
|
||||
/// <param name="type">the source type</param>
|
||||
/// <returns></returns>
|
||||
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;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
},
|
||||
|
||||
|
||||
@@ -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
|
||||
/// <param name="ids"></param>
|
||||
/// <param name="type"></param>
|
||||
/// <returns></returns>
|
||||
/// <remarks>
|
||||
/// We allow for POST because there could be quite a lot of Ids
|
||||
/// </remarks>
|
||||
[HttpGet]
|
||||
public IEnumerable<EntityBasic> GetByIds([FromUri]int[] ids, UmbracoEntityTypes type)
|
||||
[HttpPost]
|
||||
public IEnumerable<EntityBasic> GetByIds([FromJsonPath]int[] ids, UmbracoEntityTypes type)
|
||||
{
|
||||
if (ids == null)
|
||||
{
|
||||
@@ -279,8 +283,12 @@ namespace Umbraco.Web.Editors
|
||||
/// <param name="ids"></param>
|
||||
/// <param name="type"></param>
|
||||
/// <returns></returns>
|
||||
/// <remarks>
|
||||
/// We allow for POST because there could be quite a lot of Ids
|
||||
/// </remarks>
|
||||
[HttpGet]
|
||||
public IEnumerable<EntityBasic> GetByIds([FromUri]Guid[] ids, UmbracoEntityTypes type)
|
||||
[HttpPost]
|
||||
public IEnumerable<EntityBasic> GetByIds([FromJsonPath]Guid[] ids, UmbracoEntityTypes type)
|
||||
{
|
||||
if (ids == null)
|
||||
{
|
||||
@@ -288,7 +296,7 @@ namespace Umbraco.Web.Editors
|
||||
}
|
||||
return GetResultForKeys(ids, type);
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Get entities by string ids - will try to convert to the correct id type (int, guid, udi)
|
||||
/// </summary>
|
||||
@@ -296,8 +304,9 @@ namespace Umbraco.Web.Editors
|
||||
/// <param name="type"></param>
|
||||
/// <returns></returns>
|
||||
/// <remarks>
|
||||
/// 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
|
||||
/// </remarks>
|
||||
[HttpGet]
|
||||
[HttpPost]
|
||||
public IEnumerable<EntityBasic> GetByIds([FromJsonPath]Udi[] ids, [FromUri]UmbracoEntityTypes type)
|
||||
{
|
||||
|
||||
@@ -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<ValueProviderFactory> 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<JObject>(strJson);
|
||||
|
||||
//if no explicit json path then use the model name
|
||||
|
||||
@@ -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<JObject>(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();
|
||||
|
||||
Reference in New Issue
Block a user