Gets all list views working correctly with content apps, fixes various issues, cleans up a bunch of code and reduces amount of service locator.

This commit is contained in:
Shannon
2018-07-17 14:23:07 +10:00
parent 45f959fb6b
commit e9752cd5e1
25 changed files with 189 additions and 230 deletions

View File

@@ -43,7 +43,20 @@ namespace Umbraco.Web.WebApi.Binders
where TPersisted : class, IContentBase
where TModelSave : ContentBaseItemSave<TPersisted>
{
protected ServiceContext Services => Current.Services; // fixme - inject
protected Core.Logging.ILogger Logger { get; }
protected ServiceContext Services { get; }
protected IUmbracoContextAccessor UmbracoContextAccessor { get; }
public ContentItemBaseBinder() : this(Current.Logger, Current.Services, Current.UmbracoContextAccessor)
{
}
public ContentItemBaseBinder(Core.Logging.ILogger logger, ServiceContext services, IUmbracoContextAccessor umbracoContextAccessor)
{
Logger = logger;
Services = services;
UmbracoContextAccessor = umbracoContextAccessor;
}
public bool BindModel(HttpActionContext actionContext, ModelBindingContext bindingContext)
{
@@ -58,29 +71,18 @@ namespace Umbraco.Web.WebApi.Binders
Directory.CreateDirectory(root);
var provider = new MultipartFormDataStreamProvider(root);
var task = Task.Run(() => GetModelAsync(actionContext, bindingContext, provider))
.ContinueWith(x =>
{
if (x.IsFaulted && x.Exception != null)
{
throw x.Exception;
}
//now that everything is binded, validate the properties
var contentItemValidator = GetValidationHelper();
contentItemValidator.ValidateItem(actionContext, x.Result);
bindingContext.Model = x.Result;
});
task.Wait();
var model = GetModel(actionContext, bindingContext, provider);
//now that everything is binded, validate the properties
var contentItemValidator = GetValidationHelper();
contentItemValidator.ValidateItem(actionContext, model);
bindingContext.Model = model;
return bindingContext.Model != null;
}
protected virtual ContentItemValidationHelper<TPersisted, TModelSave> GetValidationHelper()
{
return new ContentItemValidationHelper<TPersisted, TModelSave>();
return new ContentItemValidationHelper<TPersisted, TModelSave>(Logger, UmbracoContextAccessor);
}
/// <summary>
@@ -90,29 +92,13 @@ namespace Umbraco.Web.WebApi.Binders
/// <param name="bindingContext"></param>
/// <param name="provider"></param>
/// <returns></returns>
private async Task<TModelSave> GetModelAsync(HttpActionContext actionContext, ModelBindingContext bindingContext, MultipartFormDataStreamProvider provider)
private TModelSave GetModel(HttpActionContext actionContext, ModelBindingContext bindingContext, MultipartFormDataStreamProvider provider)
{
// note
//
// for some reason, due to the way we do async, HttpContext.Current is null
// which means that the 'current' UmbracoContext is null too since we are using HttpContextUmbracoContextAccessor
// trying to 'EnsureContext' fails because that accessor cannot access the HttpContext either to register the current UmbracoContext
//
// so either we go with an HybridUmbracoContextAccessor that relies on a ThreadStatic variable when HttpContext.Current is null
// and I don't like it
// or
// we try to force-set the current http context, because, hey... it's there.
// and then there is no need to event 'Ensure' anything
// read http://stackoverflow.com/questions/1992141/how-do-i-get-an-httpcontext-object-from-httpcontextbase-in-asp-net-mvc-1
// what's below works but I cannot say I am proud of it
var request = actionContext.Request;
var httpContext = (HttpContextBase) request.Properties["MS_HttpContext"];
HttpContext.Current = httpContext.ApplicationInstance.Context;
var content = request.Content;
var result = await content.ReadAsMultipartAsync(provider);
var result = content.ReadAsMultipartAsync(provider).Result;
if (result.FormData["contentItem"] == null)
{

View File

@@ -5,7 +5,10 @@ using System.Net.Http;
using System.Web.Http.Controllers;
using AutoMapper;
using Umbraco.Core;
using Umbraco.Core.Logging;
using Umbraco.Core.Models;
using Umbraco.Core.Services;
using Umbraco.Web.Composing;
using Umbraco.Web.Models.ContentEditing;
using Umbraco.Web.Models.Mapping;
using Umbraco.Web.WebApi.Filters;
@@ -14,9 +17,18 @@ namespace Umbraco.Web.WebApi.Binders
{
internal class ContentItemBinder : ContentItemBaseBinder<IContent, ContentItemSave>
{
public ContentItemBinder() : this(Current.Logger, Current.Services, Current.UmbracoContextAccessor)
{
}
public ContentItemBinder(Core.Logging.ILogger logger, ServiceContext services, IUmbracoContextAccessor umbracoContextAccessor)
: base(logger, services, umbracoContextAccessor)
{
}
protected override ContentItemValidationHelper<IContent, ContentItemSave> GetValidationHelper()
{
return new ContentValidationHelper();
return new ContentValidationHelper(Logger, UmbracoContextAccessor);
}
protected override IContent GetExisting(ContentItemSave model)
@@ -49,6 +61,10 @@ namespace Umbraco.Web.WebApi.Binders
internal class ContentValidationHelper : ContentItemValidationHelper<IContent, ContentItemSave>
{
public ContentValidationHelper(ILogger logger, IUmbracoContextAccessor umbracoContextAccessor) : base(logger, umbracoContextAccessor)
{
}
/// <summary>
/// Validates that the correct information is in the request for saving a culture variant
/// </summary>

View File

@@ -2,6 +2,8 @@
using AutoMapper;
using Umbraco.Core;
using Umbraco.Core.Models;
using Umbraco.Core.Services;
using Umbraco.Web.Composing;
using Umbraco.Web.Models.ContentEditing;
using Umbraco.Web.Models.Mapping;
@@ -9,6 +11,15 @@ namespace Umbraco.Web.WebApi.Binders
{
internal class MediaItemBinder : ContentItemBaseBinder<IMedia, MediaItemSave>
{
public MediaItemBinder() : this(Current.Logger, Current.Services, Current.UmbracoContextAccessor)
{
}
public MediaItemBinder(Core.Logging.ILogger logger, ServiceContext services, IUmbracoContextAccessor umbracoContextAccessor)
: base(logger, services, umbracoContextAccessor)
{
}
protected override IMedia GetExisting(MediaItemSave model)
{
return Services.MediaService.GetById(Convert.ToInt32(model.Id));

View File

@@ -19,14 +19,25 @@ using Umbraco.Core.Models.Membership;
using Umbraco.Core.Services.Implement;
using Umbraco.Web;
using Umbraco.Web.Composing;
using Umbraco.Core.Logging;
namespace Umbraco.Web.WebApi.Binders
{
internal class MemberBinder : ContentItemBaseBinder<IMember, MemberSave>
{
public MemberBinder() : this(Current.Logger, Current.Services, Current.UmbracoContextAccessor)
{
}
public MemberBinder(ILogger logger, ServiceContext services, IUmbracoContextAccessor umbracoContextAccessor)
: base(logger, services, umbracoContextAccessor)
{
}
protected override ContentItemValidationHelper<IMember, MemberSave> GetValidationHelper()
{
return new MemberValidationHelper();
return new MemberValidationHelper(Logger, UmbracoContextAccessor);
}
/// <summary>
@@ -179,6 +190,10 @@ namespace Umbraco.Web.WebApi.Binders
/// </summary>
internal class MemberValidationHelper : ContentItemValidationHelper<IMember, MemberSave>
{
public MemberValidationHelper(ILogger logger, IUmbracoContextAccessor umbracoContextAccessor) : base(logger, umbracoContextAccessor)
{
}
/// <summary>
/// We need to manually validate a few things here like email and login to make sure they are valid and aren't duplicates
/// </summary>
@@ -244,12 +259,9 @@ namespace Umbraco.Web.WebApi.Binders
propertiesToValidate.RemoveAll(property => property.Alias == remove);
}
var umbCtx = Current.UmbracoContext; // fixme inject?
//if the user doesn't have access to sensitive values, then we need to validate the incoming properties to check
//if a sensitive value is being submitted.
if (umbCtx.Security.CurrentUser.HasAccessToSensitiveData() == false)
if (UmbracoContextAccessor.UmbracoContext.Security.CurrentUser.HasAccessToSensitiveData() == false)
{
var sensitiveProperties = postedItem.PersistedContent.ContentType
.PropertyTypes.Where(x => postedItem.PersistedContent.ContentType.IsSensitiveProperty(x.Alias))

View File

@@ -26,6 +26,14 @@ namespace Umbraco.Web.WebApi.Filters
where TPersisted : class, IContentBase
where TModelSave : ContentBaseItemSave<TPersisted>
{
protected IUmbracoContextAccessor UmbracoContextAccessor { get; }
protected ILogger Logger { get; }
public ContentItemValidationHelper(ILogger logger, IUmbracoContextAccessor umbracoContextAccessor)
{
Logger = logger ?? throw new ArgumentNullException(nameof(logger));
UmbracoContextAccessor = umbracoContextAccessor ?? throw new ArgumentNullException(nameof(umbracoContextAccessor));
}
/// <summary>
/// Validates the content item and updates the Response and ModelState accordingly
@@ -94,7 +102,7 @@ namespace Umbraco.Web.WebApi.Filters
/// <param name="persistedProperties"></param>
/// <param name="actionContext"></param>
/// <returns></returns>
protected bool ValidateProperties(List<ContentPropertyBasic> postedProperties , List<Property> persistedProperties, HttpActionContext actionContext)
protected bool ValidateProperties(List<ContentPropertyBasic> postedProperties, List<Property> persistedProperties, HttpActionContext actionContext)
{
foreach (var p in postedProperties)
{
@@ -131,7 +139,8 @@ namespace Umbraco.Web.WebApi.Filters
if (editor == null)
{
var message = $"Could not find property editor \"{p.DataType.EditorAlias}\" for property with id {p.Id}.";
Current.Logger.Warn<ContentItemValidationHelper<TPersisted, TModelSave>>(message);
Logger.Warn<ContentItemValidationHelper<TPersisted, TModelSave>>(message);
continue;
}