Merge remote-tracking branch 'origin/netcore/netcore' into netcore/feature/remove-httpresponseexception
This commit is contained in:
@@ -30,10 +30,10 @@ using Umbraco.Web.BackOffice.Security;
|
||||
using Umbraco.Web.Common.ActionsResults;
|
||||
using Umbraco.Web.Common.Attributes;
|
||||
using Umbraco.Web.Common.Authorization;
|
||||
using Umbraco.Web.Common.Controllers;
|
||||
using Umbraco.Web.Common.Filters;
|
||||
using Umbraco.Web.Common.Security;
|
||||
using Umbraco.Web.Models;
|
||||
using Umbraco.Web.Mvc;
|
||||
using Umbraco.Web.WebAssets;
|
||||
using Constants = Umbraco.Core.Constants;
|
||||
|
||||
|
||||
@@ -621,19 +621,20 @@ namespace Umbraco.Web.BackOffice.Controllers
|
||||
/// <summary>
|
||||
/// Saves content
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
[FileUploadCleanupFilter]
|
||||
[ContentSaveValidation]
|
||||
public async Task<ContentItemDisplay> PostSaveBlueprint([ModelBinder(typeof(BlueprintItemBinder))] ContentItemSave contentItem)
|
||||
{
|
||||
var contentItemDisplay = await PostSaveInternal(contentItem,
|
||||
var contentItemDisplay = await PostSaveInternal(
|
||||
contentItem,
|
||||
content =>
|
||||
{
|
||||
EnsureUniqueName(content.Name, content, "Name");
|
||||
|
||||
_contentService.SaveBlueprint(contentItem.PersistedContent, _backofficeSecurityAccessor.BackOfficeSecurity.CurrentUser.Id);
|
||||
//we need to reuse the underlying logic so return the result that it wants
|
||||
return OperationResult.Succeed(new EventMessages());
|
||||
|
||||
// we need to reuse the underlying logic so return the result that it wants
|
||||
return OperationResult.Succeed(new EventMessages());
|
||||
},
|
||||
content =>
|
||||
{
|
||||
@@ -648,7 +649,6 @@ namespace Umbraco.Web.BackOffice.Controllers
|
||||
/// <summary>
|
||||
/// Saves content
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
[FileUploadCleanupFilter]
|
||||
[ContentSaveValidation]
|
||||
[OutgoingEditorModelEvent]
|
||||
@@ -664,9 +664,9 @@ namespace Umbraco.Web.BackOffice.Controllers
|
||||
|
||||
private async Task<ActionResult<ContentItemDisplay>> PostSaveInternal(ContentItemSave contentItem, Func<IContent, OperationResult> saveMethod, Func<IContent, ContentItemDisplay> mapToDisplay)
|
||||
{
|
||||
//Recent versions of IE/Edge may send in the full client side file path instead of just the file name.
|
||||
//To ensure similar behavior across all browsers no matter what they do - we strip the FileName property of all
|
||||
//uploaded files to being *only* the actual file name (as it should be).
|
||||
// Recent versions of IE/Edge may send in the full client side file path instead of just the file name.
|
||||
// To ensure similar behavior across all browsers no matter what they do - we strip the FileName property of all
|
||||
// uploaded files to being *only* the actual file name (as it should be).
|
||||
if (contentItem.UploadedFiles != null && contentItem.UploadedFiles.Any())
|
||||
{
|
||||
foreach (var file in contentItem.UploadedFiles)
|
||||
@@ -675,7 +675,7 @@ namespace Umbraco.Web.BackOffice.Controllers
|
||||
}
|
||||
}
|
||||
|
||||
//If we've reached here it means:
|
||||
// If we've reached here it means:
|
||||
// * Our model has been bound
|
||||
// * and validated
|
||||
// * any file attachments have been saved to their temporary location for us to use
|
||||
@@ -685,20 +685,20 @@ namespace Umbraco.Web.BackOffice.Controllers
|
||||
|
||||
var passesCriticalValidationRules = ValidateCriticalData(contentItem, out var variantCount);
|
||||
|
||||
//we will continue to save if model state is invalid, however we cannot save if critical data is missing.
|
||||
// we will continue to save if model state is invalid, however we cannot save if critical data is missing.
|
||||
if (!ModelState.IsValid)
|
||||
{
|
||||
//check for critical data validation issues, we can't continue saving if this data is invalid
|
||||
// check for critical data validation issues, we can't continue saving if this data is invalid
|
||||
if (!passesCriticalValidationRules)
|
||||
{
|
||||
//ok, so the absolute mandatory data is invalid and it's new, we cannot actually continue!
|
||||
// ok, so the absolute mandatory data is invalid and it's new, we cannot actually continue!
|
||||
// add the model state to the outgoing object and throw a validation message
|
||||
var forDisplay = mapToDisplay(contentItem.PersistedContent);
|
||||
forDisplay.Errors = ModelState.ToErrorDictionary();
|
||||
return new ValidationErrorResult(forDisplay);
|
||||
}
|
||||
|
||||
//if there's only one variant and the model state is not valid we cannot publish so change it to save
|
||||
// if there's only one variant and the model state is not valid we cannot publish so change it to save
|
||||
if (variantCount == 1)
|
||||
{
|
||||
switch (contentItem.Action)
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
using System;
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Net.Http;
|
||||
@@ -29,14 +29,12 @@ namespace Umbraco.Web.BackOffice.Controllers
|
||||
[JsonDateTimeFormat]
|
||||
public abstract class ContentControllerBase : BackOfficeNotificationsController
|
||||
{
|
||||
protected ICultureDictionary CultureDictionary { get; }
|
||||
protected ILoggerFactory LoggerFactory { get; }
|
||||
protected IShortStringHelper ShortStringHelper { get; }
|
||||
protected IEventMessagesFactory EventMessages { get; }
|
||||
protected ILocalizedTextService LocalizedTextService { get; }
|
||||
private readonly ILogger<ContentControllerBase> _logger;
|
||||
private readonly IJsonSerializer _serializer;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="ContentControllerBase"/> class.
|
||||
/// </summary>
|
||||
protected ContentControllerBase(
|
||||
ICultureDictionary cultureDictionary,
|
||||
ILoggerFactory loggerFactory,
|
||||
@@ -54,6 +52,31 @@ namespace Umbraco.Web.BackOffice.Controllers
|
||||
_serializer = serializer;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the <see cref="ICultureDictionary"/>
|
||||
/// </summary>
|
||||
protected ICultureDictionary CultureDictionary { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the <see cref="ILoggerFactory"/>
|
||||
/// </summary>
|
||||
protected ILoggerFactory LoggerFactory { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the <see cref="IShortStringHelper"/>
|
||||
/// </summary>
|
||||
protected IShortStringHelper ShortStringHelper { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the <see cref="IEventMessagesFactory"/>
|
||||
/// </summary>
|
||||
protected IEventMessagesFactory EventMessages { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the <see cref="ILocalizedTextService"/>
|
||||
/// </summary>
|
||||
protected ILocalizedTextService LocalizedTextService { get; }
|
||||
|
||||
protected NotFoundObjectResult HandleContentNotFound(object id, bool throwException = true)
|
||||
{
|
||||
ModelState.AddModelError("id", $"content with id: {id} was not found");
|
||||
|
||||
@@ -114,8 +114,6 @@ namespace Umbraco.Web.BackOffice.Controllers
|
||||
/// <summary>
|
||||
/// Gets the document type a given id
|
||||
/// </summary>
|
||||
/// <param name="id"></param>
|
||||
/// <returns></returns>
|
||||
[DetermineAmbiguousActionByPassingParameters]
|
||||
[Authorize(Policy = AuthorizationPolicies.TreeAccessDocumentTypes)]
|
||||
public ActionResult<DocumentTypeDisplay> GetById(int id)
|
||||
@@ -133,8 +131,6 @@ namespace Umbraco.Web.BackOffice.Controllers
|
||||
/// <summary>
|
||||
/// Gets the document type a given guid
|
||||
/// </summary>
|
||||
/// <param name="id"></param>
|
||||
/// <returns></returns>
|
||||
[DetermineAmbiguousActionByPassingParameters]
|
||||
[Authorize(Policy = AuthorizationPolicies.TreeAccessDocumentTypes)]
|
||||
public ActionResult<DocumentTypeDisplay> GetById(Guid id)
|
||||
@@ -152,8 +148,6 @@ namespace Umbraco.Web.BackOffice.Controllers
|
||||
/// <summary>
|
||||
/// Gets the document type a given udi
|
||||
/// </summary>
|
||||
/// <param name="id"></param>
|
||||
/// <returns></returns>
|
||||
[DetermineAmbiguousActionByPassingParameters]
|
||||
[Authorize(Policy = AuthorizationPolicies.TreeAccessDocumentTypes)]
|
||||
public ActionResult<DocumentTypeDisplay> GetById(Udi id)
|
||||
@@ -175,8 +169,6 @@ namespace Umbraco.Web.BackOffice.Controllers
|
||||
/// <summary>
|
||||
/// Deletes a document type with a given ID
|
||||
/// </summary>
|
||||
/// <param name="id"></param>
|
||||
/// <returns></returns>
|
||||
[HttpDelete]
|
||||
[HttpPost]
|
||||
[Authorize(Policy = AuthorizationPolicies.TreeAccessDocumentTypes)]
|
||||
@@ -195,7 +187,6 @@ namespace Umbraco.Web.BackOffice.Controllers
|
||||
/// <summary>
|
||||
/// Gets all user defined properties.
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
[Authorize(Policy = AuthorizationPolicies.TreeAccessAnyContentOrTypes)]
|
||||
public IEnumerable<string> GetAllPropertyTypeAliases()
|
||||
{
|
||||
@@ -205,7 +196,6 @@ namespace Umbraco.Web.BackOffice.Controllers
|
||||
/// <summary>
|
||||
/// Gets all the standard fields.
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
[Authorize(Policy = AuthorizationPolicies.TreeAccessAnyContentOrTypes)]
|
||||
public IEnumerable<string> GetAllStandardFields()
|
||||
{
|
||||
@@ -217,8 +207,6 @@ namespace Umbraco.Web.BackOffice.Controllers
|
||||
/// Returns the available compositions for this content type
|
||||
/// This has been wrapped in a dto instead of simple parameters to support having multiple parameters in post request body
|
||||
/// </summary>
|
||||
/// <param name="filter"></param>
|
||||
/// <returns></returns>
|
||||
[HttpPost]
|
||||
[Authorize(Policy = AuthorizationPolicies.TreeAccessDocumentTypes)]
|
||||
public IActionResult GetAvailableCompositeContentTypes(GetAvailableCompositionsFilter filter)
|
||||
@@ -235,7 +223,6 @@ namespace Umbraco.Web.BackOffice.Controllers
|
||||
/// <summary>
|
||||
/// Returns true if any content types have culture variation enabled
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
[HttpGet]
|
||||
[Authorize(Policy = AuthorizationPolicies.BackOfficeAccess)]
|
||||
public bool AllowsCultureVariation()
|
||||
@@ -248,8 +235,6 @@ namespace Umbraco.Web.BackOffice.Controllers
|
||||
/// Returns where a particular composition has been used
|
||||
/// This has been wrapped in a dto instead of simple parameters to support having multiple parameters in post request body
|
||||
/// </summary>
|
||||
/// <param name="filter"></param>
|
||||
/// <returns></returns>
|
||||
[HttpPost]
|
||||
[Authorize(Policy = AuthorizationPolicies.TreeAccessDocumentTypes)]
|
||||
public IActionResult GetWhereCompositionIsUsedInContentTypes(GetAvailableCompositionsFilter filter)
|
||||
@@ -287,8 +272,6 @@ namespace Umbraco.Web.BackOffice.Controllers
|
||||
/// <summary>
|
||||
/// Deletes a document type container with a given ID
|
||||
/// </summary>
|
||||
/// <param name="id"></param>
|
||||
/// <returns></returns>
|
||||
[HttpDelete]
|
||||
[HttpPost]
|
||||
[Authorize(Policy = AuthorizationPolicies.TreeAccessDocumentTypes)]
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.AspNetCore.Mvc.ViewEngines;
|
||||
using Microsoft.Extensions.Options;
|
||||
@@ -108,7 +108,6 @@ namespace Umbraco.Web.BackOffice.Controllers
|
||||
/// <summary>
|
||||
/// The endpoint that is loaded within the preview iframe
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
[Authorize(Policy = AuthorizationPolicies.BackOfficeAccess)]
|
||||
public ActionResult Frame(int id, string culture)
|
||||
{
|
||||
@@ -119,22 +118,17 @@ namespace Umbraco.Web.BackOffice.Controllers
|
||||
|
||||
return RedirectPermanent($"../../{id}.aspx{query}");
|
||||
}
|
||||
|
||||
public ActionResult EnterPreview(int id)
|
||||
{
|
||||
var user = _backofficeSecurityAccessor.BackOfficeSecurity.CurrentUser;
|
||||
|
||||
var previewToken = _publishedSnapshotService.EnterPreview(user, id);
|
||||
|
||||
_cookieManager.SetCookieValue(Constants.Web.PreviewCookieName, previewToken);
|
||||
_cookieManager.SetCookieValue(Constants.Web.PreviewCookieName, "preview");
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public ActionResult End(string redir = null)
|
||||
{
|
||||
var previewToken = _cookieManager.GetPreviewCookieValue();
|
||||
|
||||
_publishedSnapshotService.ExitPreview(previewToken);
|
||||
|
||||
_cookieManager.ExpireCookie(Constants.Web.PreviewCookieName);
|
||||
|
||||
// Expire Client-side cookie that determines whether the user has accepted to be in Preview Mode when visiting the website.
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
using System;
|
||||
using System;
|
||||
using System.Reflection.Metadata;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Umbraco.Core;
|
||||
using Umbraco.Web.Cache;
|
||||
@@ -8,43 +9,54 @@ using Umbraco.Web.PublishedCache;
|
||||
|
||||
namespace Umbraco.Web.BackOffice.Controllers
|
||||
{
|
||||
[PluginController(Constants.Web.Mvc.BackOfficeApiArea)]
|
||||
[PluginController(Constants.Web.Mvc.BackOfficeApiArea)]
|
||||
public class PublishedSnapshotCacheStatusController : UmbracoAuthorizedApiController
|
||||
{
|
||||
private readonly IPublishedSnapshotService _publishedSnapshotService;
|
||||
private readonly IPublishedSnapshotStatus _publishedSnapshotStatus;
|
||||
private readonly DistributedCache _distributedCache;
|
||||
|
||||
public PublishedSnapshotCacheStatusController(IPublishedSnapshotService publishedSnapshotService, DistributedCache distributedCache)
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="PublishedSnapshotCacheStatusController"/> class.
|
||||
/// </summary>
|
||||
public PublishedSnapshotCacheStatusController(
|
||||
IPublishedSnapshotService publishedSnapshotService,
|
||||
IPublishedSnapshotStatus publishedSnapshotStatus,
|
||||
DistributedCache distributedCache)
|
||||
{
|
||||
_publishedSnapshotService = publishedSnapshotService ?? throw new ArgumentNullException(nameof(publishedSnapshotService));
|
||||
_publishedSnapshotStatus = publishedSnapshotStatus;
|
||||
_distributedCache = distributedCache;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Rebuilds the Database cache
|
||||
/// </summary>
|
||||
[HttpPost]
|
||||
public string RebuildDbCache()
|
||||
{
|
||||
_publishedSnapshotService.Rebuild();
|
||||
return _publishedSnapshotService.GetStatus();
|
||||
return _publishedSnapshotStatus.GetStatus();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a status report
|
||||
/// </summary>
|
||||
[HttpGet]
|
||||
public string GetStatus()
|
||||
{
|
||||
return _publishedSnapshotService.GetStatus();
|
||||
}
|
||||
public string GetStatus() => _publishedSnapshotStatus.GetStatus();
|
||||
|
||||
/// <summary>
|
||||
/// Cleans up unused snapshots
|
||||
/// </summary>
|
||||
[HttpGet]
|
||||
public string Collect()
|
||||
public async Task<string> Collect()
|
||||
{
|
||||
GC.Collect();
|
||||
_publishedSnapshotService.Collect();
|
||||
return _publishedSnapshotService.GetStatus();
|
||||
await _publishedSnapshotService.CollectAsync();
|
||||
return _publishedSnapshotStatus.GetStatus();
|
||||
}
|
||||
|
||||
[HttpPost]
|
||||
public void ReloadCache()
|
||||
{
|
||||
_distributedCache.RefreshAllPublishedSnapshot();
|
||||
}
|
||||
public void ReloadCache() => _distributedCache.RefreshAllPublishedSnapshot();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
using System;
|
||||
using System;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Umbraco.Web.PublishedCache;
|
||||
|
||||
@@ -6,22 +6,22 @@ namespace Umbraco.Web.BackOffice.Controllers
|
||||
{
|
||||
public class PublishedStatusController : UmbracoAuthorizedApiController
|
||||
{
|
||||
private readonly IPublishedSnapshotService _publishedSnapshotService;
|
||||
private readonly IPublishedSnapshotStatus _publishedSnapshotStatus;
|
||||
|
||||
public PublishedStatusController(IPublishedSnapshotService publishedSnapshotService)
|
||||
public PublishedStatusController(IPublishedSnapshotStatus publishedSnapshotStatus)
|
||||
{
|
||||
_publishedSnapshotService = publishedSnapshotService ?? throw new ArgumentNullException(nameof(publishedSnapshotService));
|
||||
_publishedSnapshotStatus = publishedSnapshotStatus ?? throw new ArgumentNullException(nameof(publishedSnapshotStatus));
|
||||
}
|
||||
|
||||
[HttpGet]
|
||||
public string GetPublishedStatusUrl()
|
||||
{
|
||||
if (!string.IsNullOrWhiteSpace(_publishedSnapshotService.StatusUrl))
|
||||
if (!string.IsNullOrWhiteSpace(_publishedSnapshotStatus.StatusUrl))
|
||||
{
|
||||
return _publishedSnapshotService.StatusUrl;
|
||||
return _publishedSnapshotStatus.StatusUrl;
|
||||
}
|
||||
|
||||
throw new NotSupportedException("Not supported: " + _publishedSnapshotService.GetType().FullName);
|
||||
throw new NotSupportedException("Not supported: " + _publishedSnapshotStatus.GetType().FullName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user