Merge pull request #1709 from umbraco/temp-U4-9435-2
U4-9435 Fix breaking change made in U4-9312
This commit is contained in:
@@ -262,7 +262,7 @@ namespace Umbraco.Web.Editors
|
||||
},
|
||||
{
|
||||
"mediaTypeApiBaseUrl", Url.GetUmbracoApiServiceBaseUrl<MediaTypeController>(
|
||||
controller => controller.GetAllowedChildren("0"))
|
||||
controller => controller.GetAllowedChildren(0))
|
||||
},
|
||||
{
|
||||
"macroApiBaseUrl", Url.GetUmbracoApiServiceBaseUrl<MacroController>(
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.IO;
|
||||
using System.Net;
|
||||
using System.Net.Http;
|
||||
@@ -27,6 +28,7 @@ using Umbraco.Web.Mvc;
|
||||
using Umbraco.Web.WebApi;
|
||||
using System.Linq;
|
||||
using System.Runtime.Serialization;
|
||||
using System.Web.Http.Controllers;
|
||||
using Umbraco.Web.WebApi.Binders;
|
||||
using Umbraco.Web.WebApi.Filters;
|
||||
using umbraco;
|
||||
@@ -45,9 +47,22 @@ namespace Umbraco.Web.Editors
|
||||
/// access to ALL of the methods on this controller will need access to the media application.
|
||||
/// </remarks>
|
||||
[PluginController("UmbracoApi")]
|
||||
[UmbracoApplicationAuthorizeAttribute(Constants.Applications.Media)]
|
||||
[UmbracoApplicationAuthorize(Constants.Applications.Media)]
|
||||
[MediaControllerControllerConfiguration]
|
||||
public class MediaController : ContentControllerBase
|
||||
{
|
||||
/// <summary>
|
||||
/// Configures this controller with a custom action selector
|
||||
/// </summary>
|
||||
private class MediaControllerControllerConfigurationAttribute : Attribute, IControllerConfiguration
|
||||
{
|
||||
public void Initialize(HttpControllerSettings controllerSettings, HttpControllerDescriptor controllerDescriptor)
|
||||
{
|
||||
controllerSettings.Services.Replace(typeof(IHttpActionSelector), new ParameterSwapControllerActionSelector(
|
||||
new ParameterSwapControllerActionSelector.ParameterSwapInfo("GetChildren", "id", typeof(int), typeof(Guid), typeof(string))));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Constructor
|
||||
/// </summary>
|
||||
@@ -173,40 +188,10 @@ namespace Umbraco.Web.Editors
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the child media objects
|
||||
/// Returns the child media objects - using the entity INT id
|
||||
/// </summary>
|
||||
[FilterAllowedOutgoingMedia(typeof(IEnumerable<ContentItemBasic<ContentPropertyBasic, IMedia>>), "Items")]
|
||||
public PagedResult<ContentItemBasic<ContentPropertyBasic, IMedia>> GetChildren(string id,
|
||||
int pageNumber = 0,
|
||||
int pageSize = 0,
|
||||
string orderBy = "SortOrder",
|
||||
Direction orderDirection = Direction.Ascending,
|
||||
bool orderBySystemField = true,
|
||||
string filter = "")
|
||||
{
|
||||
int idInt; Guid idGuid;
|
||||
|
||||
if (Guid.TryParse(id, out idGuid))
|
||||
{
|
||||
var entity = Services.EntityService.GetByKey(idGuid);
|
||||
if (entity != null)
|
||||
{
|
||||
return GetChildren(entity.Id, pageNumber, pageSize, orderBy, orderDirection, orderBySystemField, filter);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new HttpResponseException(HttpStatusCode.NotFound);
|
||||
}
|
||||
}
|
||||
else if (int.TryParse(id, out idInt))
|
||||
{
|
||||
return GetChildren(idInt, pageNumber, pageSize, orderBy, orderDirection, orderBySystemField, filter);
|
||||
}
|
||||
|
||||
throw new HttpResponseException(HttpStatusCode.NotFound);
|
||||
}
|
||||
|
||||
private PagedResult<ContentItemBasic<ContentPropertyBasic, IMedia>> GetChildren(int id,
|
||||
public PagedResult<ContentItemBasic<ContentPropertyBasic, IMedia>> GetChildren(int id,
|
||||
int pageNumber = 0,
|
||||
int pageSize = 0,
|
||||
string orderBy = "SortOrder",
|
||||
@@ -240,6 +225,58 @@ namespace Umbraco.Web.Editors
|
||||
return pagedResult;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the child media objects - using the entity GUID id
|
||||
/// </summary>
|
||||
/// <param name="id"></param>
|
||||
/// <param name="pageNumber"></param>
|
||||
/// <param name="pageSize"></param>
|
||||
/// <param name="orderBy"></param>
|
||||
/// <param name="orderDirection"></param>
|
||||
/// <param name="orderBySystemField"></param>
|
||||
/// <param name="filter"></param>
|
||||
/// <returns></returns>
|
||||
[FilterAllowedOutgoingMedia(typeof(IEnumerable<ContentItemBasic<ContentPropertyBasic, IMedia>>), "Items")]
|
||||
public PagedResult<ContentItemBasic<ContentPropertyBasic, IMedia>> GetChildren(Guid id,
|
||||
int pageNumber = 0,
|
||||
int pageSize = 0,
|
||||
string orderBy = "SortOrder",
|
||||
Direction orderDirection = Direction.Ascending,
|
||||
bool orderBySystemField = true,
|
||||
string filter = "")
|
||||
{
|
||||
var entity = Services.EntityService.GetByKey(id);
|
||||
if (entity != null)
|
||||
{
|
||||
return GetChildren(entity.Id, pageNumber, pageSize, orderBy, orderDirection, orderBySystemField, filter);
|
||||
}
|
||||
throw new HttpResponseException(HttpStatusCode.NotFound);
|
||||
}
|
||||
|
||||
[Obsolete("Do not use this method, use either the overload with INT or GUID instead, this will be removed in future versions")]
|
||||
[EditorBrowsable(EditorBrowsableState.Never)]
|
||||
[UmbracoTreeAuthorize(Constants.Trees.MediaTypes, Constants.Trees.Media)]
|
||||
public PagedResult<ContentItemBasic<ContentPropertyBasic, IMedia>> GetChildren(string id,
|
||||
int pageNumber = 0,
|
||||
int pageSize = 0,
|
||||
string orderBy = "SortOrder",
|
||||
Direction orderDirection = Direction.Ascending,
|
||||
bool orderBySystemField = true,
|
||||
string filter = "")
|
||||
{
|
||||
foreach (var type in new[] { typeof(int), typeof(Guid) })
|
||||
{
|
||||
var parsed = id.TryConvertTo(type);
|
||||
if (parsed)
|
||||
{
|
||||
//oooh magic! will auto select the right overload
|
||||
return GetChildren((dynamic)parsed.Result);
|
||||
}
|
||||
}
|
||||
|
||||
throw new HttpResponseException(HttpStatusCode.NotFound);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Moves an item to the recycle bin, if it is already there then it will permanently delete it
|
||||
/// </summary>
|
||||
|
||||
@@ -13,6 +13,9 @@ using Umbraco.Web.WebApi;
|
||||
using Umbraco.Core.Services;
|
||||
using Umbraco.Core.Models.EntityBase;
|
||||
using System;
|
||||
using System.ComponentModel;
|
||||
using System.Web.Http.Controllers;
|
||||
using Umbraco.Core;
|
||||
|
||||
namespace Umbraco.Web.Editors
|
||||
{
|
||||
@@ -26,8 +29,21 @@ namespace Umbraco.Web.Editors
|
||||
[PluginController("UmbracoApi")]
|
||||
[UmbracoTreeAuthorize(Constants.Trees.MediaTypes)]
|
||||
[EnableOverrideAuthorization]
|
||||
[MediaTypeControllerControllerConfigurationAttribute]
|
||||
public class MediaTypeController : ContentTypeControllerBase
|
||||
{
|
||||
/// <summary>
|
||||
/// Configures this controller with a custom action selector
|
||||
/// </summary>
|
||||
private class MediaTypeControllerControllerConfigurationAttribute : Attribute, IControllerConfiguration
|
||||
{
|
||||
public void Initialize(HttpControllerSettings controllerSettings, HttpControllerDescriptor controllerDescriptor)
|
||||
{
|
||||
controllerSettings.Services.Replace(typeof(IHttpActionSelector), new ParameterSwapControllerActionSelector(
|
||||
new ParameterSwapControllerActionSelector.ParameterSwapInfo("GetAllowedChildren", "contentId", typeof(int), typeof(Guid), typeof(string))));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Constructor
|
||||
/// </summary>
|
||||
@@ -172,26 +188,11 @@ namespace Umbraco.Web.Editors
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Returns the allowed child content type objects for the content item id passed in
|
||||
/// Returns the allowed child content type objects for the content item id passed in - based on an INT id
|
||||
/// </summary>
|
||||
/// <param name="contentId"></param>
|
||||
[UmbracoTreeAuthorize(Constants.Trees.MediaTypes, Constants.Trees.Media)]
|
||||
public IEnumerable<ContentTypeBasic> GetAllowedChildren(string contentId)
|
||||
{
|
||||
Guid idGuid = Guid.Empty;
|
||||
int idInt;
|
||||
if (Guid.TryParse(contentId, out idGuid)) {
|
||||
var entity = ApplicationContext.Services.EntityService.GetByKey(idGuid);
|
||||
return GetAllowedChildrenInternal(entity.Id);
|
||||
} else if (int.TryParse(contentId, out idInt))
|
||||
{
|
||||
return GetAllowedChildrenInternal(idInt);
|
||||
}
|
||||
|
||||
throw new HttpResponseException(HttpStatusCode.NotFound);
|
||||
}
|
||||
|
||||
private IEnumerable<ContentTypeBasic> GetAllowedChildrenInternal(int contentId)
|
||||
public IEnumerable<ContentTypeBasic> GetAllowedChildren(int contentId)
|
||||
{
|
||||
if (contentId == Constants.System.RecycleBinContent)
|
||||
return Enumerable.Empty<ContentTypeBasic>();
|
||||
@@ -231,6 +232,40 @@ namespace Umbraco.Web.Editors
|
||||
return basics;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the allowed child content type objects for the content item id passed in - based on a GUID id
|
||||
/// </summary>
|
||||
/// <param name="contentId"></param>
|
||||
[UmbracoTreeAuthorize(Constants.Trees.MediaTypes, Constants.Trees.Media)]
|
||||
public IEnumerable<ContentTypeBasic> GetAllowedChildren(Guid contentId)
|
||||
{
|
||||
var entity = ApplicationContext.Services.EntityService.GetByKey(contentId);
|
||||
if (entity != null)
|
||||
{
|
||||
return GetAllowedChildren(entity.Id);
|
||||
}
|
||||
|
||||
throw new HttpResponseException(HttpStatusCode.NotFound);
|
||||
}
|
||||
|
||||
[Obsolete("Do not use this method, use either the overload with INT or GUID instead, this will be removed in future versions")]
|
||||
[EditorBrowsable(EditorBrowsableState.Never)]
|
||||
[UmbracoTreeAuthorize(Constants.Trees.MediaTypes, Constants.Trees.Media)]
|
||||
public IEnumerable<ContentTypeBasic> GetAllowedChildren(string contentId)
|
||||
{
|
||||
foreach (var type in new[] { typeof(int), typeof(Guid) })
|
||||
{
|
||||
var parsed = contentId.TryConvertTo(type);
|
||||
if (parsed)
|
||||
{
|
||||
//oooh magic! will auto select the right overload
|
||||
return GetAllowedChildren((dynamic)parsed.Result);
|
||||
}
|
||||
}
|
||||
|
||||
throw new HttpResponseException(HttpStatusCode.NotFound);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Move the media type
|
||||
/// </summary>
|
||||
|
||||
@@ -0,0 +1,84 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Web;
|
||||
using System.Web.Http.Controllers;
|
||||
using Umbraco.Core;
|
||||
|
||||
namespace Umbraco.Web.Editors
|
||||
{
|
||||
/// <summary>
|
||||
/// This is used to auto-select specific actions on controllers that would otherwise be ambiguous based on a single parameter type
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// As an example, lets say we have 2 methods: GetChildren(int id) and GetChildren(Guid id), by default Web Api won't allow this since
|
||||
/// it won't know what to select, but if this Tuple is passed in new Tuple{string, string}("GetChildren", "id")
|
||||
/// </remarks>
|
||||
internal class ParameterSwapControllerActionSelector : ApiControllerActionSelector
|
||||
{
|
||||
private readonly ParameterSwapInfo[] _actions;
|
||||
|
||||
/// <summary>
|
||||
/// Constructor accepting a list of action name + parameter name
|
||||
/// </summary>
|
||||
/// <param name="actions"></param>
|
||||
public ParameterSwapControllerActionSelector(params ParameterSwapInfo[] actions)
|
||||
{
|
||||
_actions = actions;
|
||||
}
|
||||
public override HttpActionDescriptor SelectAction(HttpControllerContext controllerContext)
|
||||
{
|
||||
var found = _actions.FirstOrDefault(x => controllerContext.Request.RequestUri.GetLeftPart(UriPartial.Path).InvariantEndsWith(x.ActionName));
|
||||
|
||||
if (found != null)
|
||||
{
|
||||
var id = HttpUtility.ParseQueryString(controllerContext.Request.RequestUri.Query).Get(found.ParamName);
|
||||
|
||||
if (id != null)
|
||||
{
|
||||
var idTypes = found.SupportedTypes;
|
||||
|
||||
foreach (var idType in idTypes)
|
||||
{
|
||||
var converted = id.TryConvertTo(idType);
|
||||
if (converted)
|
||||
{
|
||||
var method = MatchByType(idType, controllerContext, found);
|
||||
if (method != null)
|
||||
return method;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return base.SelectAction(controllerContext);
|
||||
}
|
||||
|
||||
private static ReflectedHttpActionDescriptor MatchByType(Type idType, HttpControllerContext controllerContext, ParameterSwapInfo found)
|
||||
{
|
||||
var controllerType = controllerContext.Controller.GetType();
|
||||
var methods = controllerType.GetMethods().Where(info => info.Name == found.ActionName).ToArray();
|
||||
if (methods.Length > 1)
|
||||
{
|
||||
//choose the one that has the parameter with the T type
|
||||
var method = methods.FirstOrDefault(x => x.GetParameters().FirstOrDefault(p => p.Name == found.ParamName && p.ParameterType == idType) != null);
|
||||
|
||||
return new ReflectedHttpActionDescriptor(controllerContext.ControllerDescriptor, method);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
internal class ParameterSwapInfo
|
||||
{
|
||||
public string ActionName { get; private set; }
|
||||
public string ParamName { get; private set; }
|
||||
public Type[] SupportedTypes { get; private set; }
|
||||
|
||||
public ParameterSwapInfo(string actionName, string paramName, params Type[] supportedTypes)
|
||||
{
|
||||
ActionName = actionName;
|
||||
ParamName = paramName;
|
||||
SupportedTypes = supportedTypes;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -278,6 +278,7 @@
|
||||
<Compile Include="Editors\EditorValidationResolver.cs" />
|
||||
<Compile Include="Editors\EditorValidator.cs" />
|
||||
<Compile Include="Editors\GravatarController.cs" />
|
||||
<Compile Include="Editors\ParameterSwapControllerActionSelector.cs" />
|
||||
<Compile Include="HealthCheck\Checks\Config\AbstractConfigCheck.cs" />
|
||||
<Compile Include="HealthCheck\Checks\Config\AcceptableConfiguration.cs" />
|
||||
<Compile Include="HealthCheck\Checks\Config\ConfigurationService.cs" />
|
||||
|
||||
Reference in New Issue
Block a user