Merge remote-tracking branch 'origin/6.2.2' into 7.1.5
Conflicts: src/Umbraco.Core/Sync/DefaultServerMessenger.cs src/Umbraco.Tests/Services/ContentServiceTests.cs
This commit is contained in:
@@ -12,6 +12,17 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
public interface IRepositoryVersionable<TId, TEntity> : IRepositoryQueryable<TId, TEntity>
|
||||
where TEntity : IAggregateRoot
|
||||
{
|
||||
/// <summary>
|
||||
/// Get the total count of entities
|
||||
/// </summary>
|
||||
/// <param name="contentTypeAlias"></param>
|
||||
/// <returns></returns>
|
||||
int Count(string contentTypeAlias = null);
|
||||
|
||||
int CountChildren(int parentId, string contentTypeAlias = null);
|
||||
|
||||
int CountDescendants(int parentId, string contentTypeAlias = null);
|
||||
|
||||
/// <summary>
|
||||
/// Gets a list of all versions for an <see cref="TEntity"/>.
|
||||
/// </summary>
|
||||
|
||||
@@ -96,6 +96,90 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
|
||||
#endregion
|
||||
|
||||
public int CountDescendants(int parentId, string contentTypeAlias = null)
|
||||
{
|
||||
var pathMatch = parentId == -1
|
||||
? "-1,"
|
||||
: "," + parentId + ",";
|
||||
var sql = new Sql();
|
||||
if (contentTypeAlias.IsNullOrWhiteSpace())
|
||||
{
|
||||
sql.Select("COUNT(*)")
|
||||
.From<NodeDto>()
|
||||
.Where<NodeDto>(x => x.NodeObjectType == NodeObjectTypeId)
|
||||
.Where<NodeDto>(x => x.Path.Contains(pathMatch));
|
||||
}
|
||||
else
|
||||
{
|
||||
sql.Select("COUNT(*)")
|
||||
.From<NodeDto>()
|
||||
.InnerJoin<ContentDto>()
|
||||
.On<NodeDto, ContentDto>(left => left.NodeId, right => right.NodeId)
|
||||
.InnerJoin<ContentTypeDto>()
|
||||
.On<ContentTypeDto, ContentDto>(left => left.NodeId, right => right.ContentTypeId)
|
||||
.Where<NodeDto>(x => x.NodeObjectType == NodeObjectTypeId)
|
||||
.Where<NodeDto>(x => x.Path.Contains(pathMatch))
|
||||
.Where<ContentTypeDto>(x => x.Alias == contentTypeAlias);
|
||||
}
|
||||
|
||||
return Database.ExecuteScalar<int>(sql);
|
||||
}
|
||||
|
||||
public int CountChildren(int parentId, string contentTypeAlias = null)
|
||||
{
|
||||
var sql = new Sql();
|
||||
if (contentTypeAlias.IsNullOrWhiteSpace())
|
||||
{
|
||||
sql.Select("COUNT(*)")
|
||||
.From<NodeDto>()
|
||||
.Where<NodeDto>(x => x.NodeObjectType == NodeObjectTypeId)
|
||||
.Where<NodeDto>(x => x.ParentId == parentId);
|
||||
}
|
||||
else
|
||||
{
|
||||
sql.Select("COUNT(*)")
|
||||
.From<NodeDto>()
|
||||
.InnerJoin<ContentDto>()
|
||||
.On<NodeDto, ContentDto>(left => left.NodeId, right => right.NodeId)
|
||||
.InnerJoin<ContentTypeDto>()
|
||||
.On<ContentTypeDto, ContentDto>(left => left.NodeId, right => right.ContentTypeId)
|
||||
.Where<NodeDto>(x => x.NodeObjectType == NodeObjectTypeId)
|
||||
.Where<NodeDto>(x => x.ParentId == parentId)
|
||||
.Where<ContentTypeDto>(x => x.Alias == contentTypeAlias);
|
||||
}
|
||||
|
||||
return Database.ExecuteScalar<int>(sql);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the total count of entities
|
||||
/// </summary>
|
||||
/// <param name="contentTypeAlias"></param>
|
||||
/// <returns></returns>
|
||||
public int Count(string contentTypeAlias = null)
|
||||
{
|
||||
var sql = new Sql();
|
||||
if (contentTypeAlias.IsNullOrWhiteSpace())
|
||||
{
|
||||
sql.Select("COUNT(*)")
|
||||
.From<NodeDto>()
|
||||
.Where<NodeDto>(x => x.NodeObjectType == NodeObjectTypeId);
|
||||
}
|
||||
else
|
||||
{
|
||||
sql.Select("COUNT(*)")
|
||||
.From<NodeDto>()
|
||||
.InnerJoin<ContentDto>()
|
||||
.On<NodeDto, ContentDto>(left => left.NodeId, right => right.NodeId)
|
||||
.InnerJoin<ContentTypeDto>()
|
||||
.On<ContentTypeDto, ContentDto>(left => left.NodeId, right => right.ContentTypeId)
|
||||
.Where<NodeDto>(x => x.NodeObjectType == NodeObjectTypeId)
|
||||
.Where<ContentTypeDto>(x => x.Alias == contentTypeAlias);
|
||||
}
|
||||
|
||||
return Database.ExecuteScalar<int>(sql);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This removes associated tags from the entity - used generally when an entity is recycled
|
||||
/// </summary>
|
||||
|
||||
@@ -74,6 +74,33 @@ namespace Umbraco.Core.Services
|
||||
_dataTypeService = dataTypeService;
|
||||
}
|
||||
|
||||
public int Count(string contentTypeAlias = null)
|
||||
{
|
||||
var uow = _uowProvider.GetUnitOfWork();
|
||||
using (var repository = _repositoryFactory.CreateContentRepository(uow))
|
||||
{
|
||||
return repository.Count(contentTypeAlias);
|
||||
}
|
||||
}
|
||||
|
||||
public int CountChildren(int parentId, string contentTypeAlias = null)
|
||||
{
|
||||
var uow = _uowProvider.GetUnitOfWork();
|
||||
using (var repository = _repositoryFactory.CreateContentRepository(uow))
|
||||
{
|
||||
return repository.CountChildren(parentId, contentTypeAlias);
|
||||
}
|
||||
}
|
||||
|
||||
public int CountDescendants(int parentId, string contentTypeAlias = null)
|
||||
{
|
||||
var uow = _uowProvider.GetUnitOfWork();
|
||||
using (var repository = _repositoryFactory.CreateContentRepository(uow))
|
||||
{
|
||||
return repository.CountDescendants(parentId, contentTypeAlias);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Used to bulk update the permissions set for a content item. This will replace all permissions
|
||||
/// assigned to an entity with a list of user id & permission pairs.
|
||||
|
||||
@@ -11,6 +11,10 @@ namespace Umbraco.Core.Services
|
||||
/// </summary>
|
||||
public interface IContentService : IService
|
||||
{
|
||||
int Count(string contentTypeAlias = null);
|
||||
int CountChildren(int parentId, string contentTypeAlias = null);
|
||||
int CountDescendants(int parentId, string contentTypeAlias = null);
|
||||
|
||||
/// <summary>
|
||||
/// Used to bulk update the permissions set for a content item. This will replace all permissions
|
||||
/// assigned to an entity with a list of user id & permission pairs.
|
||||
|
||||
@@ -9,6 +9,10 @@ namespace Umbraco.Core.Services
|
||||
/// </summary>
|
||||
public interface IMediaService : IService
|
||||
{
|
||||
int Count(string contentTypeAlias = null);
|
||||
int CountChildren(int parentId, string contentTypeAlias = null);
|
||||
int CountDescendants(int parentId, string contentTypeAlias = null);
|
||||
|
||||
IEnumerable<IMedia> GetByIds(IEnumerable<int> ids);
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -11,6 +11,8 @@ namespace Umbraco.Core.Services
|
||||
/// </summary>
|
||||
public interface IMemberService : IMembershipMemberService
|
||||
{
|
||||
int Count(string contentTypeAlias = null);
|
||||
|
||||
IMember CreateMember(string username, string email, string name, string memberTypeAlias);
|
||||
IMember CreateMember(string username, string email, string name, IMemberType memberType);
|
||||
IMember CreateMemberWithIdentity(string username, string email, string name, string memberTypeAlias);
|
||||
|
||||
@@ -251,6 +251,33 @@ namespace Umbraco.Core.Services
|
||||
}
|
||||
}
|
||||
|
||||
public int Count(string contentTypeAlias = null)
|
||||
{
|
||||
var uow = _uowProvider.GetUnitOfWork();
|
||||
using (var repository = _repositoryFactory.CreateMediaRepository(uow))
|
||||
{
|
||||
return repository.Count(contentTypeAlias);
|
||||
}
|
||||
}
|
||||
|
||||
public int CountChildren(int parentId, string contentTypeAlias = null)
|
||||
{
|
||||
var uow = _uowProvider.GetUnitOfWork();
|
||||
using (var repository = _repositoryFactory.CreateMediaRepository(uow))
|
||||
{
|
||||
return repository.CountChildren(parentId, contentTypeAlias);
|
||||
}
|
||||
}
|
||||
|
||||
public int CountDescendants(int parentId, string contentTypeAlias = null)
|
||||
{
|
||||
var uow = _uowProvider.GetUnitOfWork();
|
||||
using (var repository = _repositoryFactory.CreateMediaRepository(uow))
|
||||
{
|
||||
return repository.CountDescendants(parentId, contentTypeAlias);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets an <see cref="IMedia"/> object by Id
|
||||
/// </summary>
|
||||
|
||||
@@ -644,6 +644,15 @@ namespace Umbraco.Core.Services
|
||||
}
|
||||
}
|
||||
|
||||
public int Count(string contentTypeAlias = null)
|
||||
{
|
||||
var uow = _uowProvider.GetUnitOfWork();
|
||||
using (var repository = _repositoryFactory.CreateMemberRepository(uow))
|
||||
{
|
||||
return repository.Count(contentTypeAlias);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a member object
|
||||
/// </summary>
|
||||
|
||||
@@ -20,18 +20,19 @@ namespace Umbraco.Core.Sync
|
||||
{
|
||||
private readonly Func<Tuple<string, string>> _getUserNamePasswordDelegate;
|
||||
private volatile bool _hasResolvedDelegate = false;
|
||||
private readonly object _locker = new object();
|
||||
private bool _useDistributedCalls;
|
||||
private readonly object _locker = new object();
|
||||
|
||||
protected string Login { get; private set; }
|
||||
protected string Password{ get; private set; }
|
||||
|
||||
protected bool UseDistributedCalls { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Without a username/password all distribuion will be disabled
|
||||
/// </summary>
|
||||
internal DefaultServerMessenger()
|
||||
{
|
||||
_useDistributedCalls = false;
|
||||
UseDistributedCalls = false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -55,7 +56,7 @@ namespace Umbraco.Core.Sync
|
||||
if (login == null) throw new ArgumentNullException("login");
|
||||
if (password == null) throw new ArgumentNullException("password");
|
||||
|
||||
_useDistributedCalls = useDistributedCalls;
|
||||
UseDistributedCalls = useDistributedCalls;
|
||||
Login = login;
|
||||
Password = password;
|
||||
}
|
||||
@@ -221,13 +222,13 @@ namespace Umbraco.Core.Sync
|
||||
{
|
||||
Login = null;
|
||||
Password = null;
|
||||
_useDistributedCalls = false;
|
||||
UseDistributedCalls = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
Login = result.Item1;
|
||||
Password = result.Item2;
|
||||
_useDistributedCalls = UmbracoConfig.For.UmbracoSettings().DistributedCall.Enabled;
|
||||
UseDistributedCalls = UmbracoConfig.For.UmbracoSettings().DistributedCall.Enabled;
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
@@ -235,7 +236,7 @@ namespace Umbraco.Core.Sync
|
||||
LogHelper.Error<DefaultServerMessenger>("Could not resolve username/password delegate, server distribution will be disabled", ex);
|
||||
Login = null;
|
||||
Password = null;
|
||||
_useDistributedCalls = false;
|
||||
UseDistributedCalls = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -314,7 +315,7 @@ namespace Umbraco.Core.Sync
|
||||
|
||||
//Now, check if we are using Distrubuted calls. If there are no servers in the list then we
|
||||
// can definitely not distribute.
|
||||
if (!_useDistributedCalls || !servers.Any())
|
||||
if (!UseDistributedCalls || !servers.Any())
|
||||
{
|
||||
//if we are not, then just invoke the call on the cache refresher
|
||||
InvokeMethodOnRefresherInstance(refresher, dispatchType, getId, instances);
|
||||
@@ -325,7 +326,7 @@ namespace Umbraco.Core.Sync
|
||||
MessageSeversForIdsOrJson(servers, refresher, dispatchType, instances.Select(getId));
|
||||
}
|
||||
|
||||
private void MessageSeversForIdsOrJson(
|
||||
protected virtual void MessageSeversForIdsOrJson(
|
||||
IEnumerable<IServerAddress> servers,
|
||||
ICacheRefresher refresher,
|
||||
MessageType dispatchType,
|
||||
@@ -345,7 +346,7 @@ namespace Umbraco.Core.Sync
|
||||
|
||||
//Now, check if we are using Distrubuted calls. If there are no servers in the list then we
|
||||
// can definitely not distribute.
|
||||
if (!_useDistributedCalls || !servers.Any())
|
||||
if (!UseDistributedCalls || !servers.Any())
|
||||
{
|
||||
//if we are not, then just invoke the call on the cache refresher
|
||||
InvokeMethodOnRefresherInstance(refresher, dispatchType, ids, jsonPayload);
|
||||
@@ -456,16 +457,16 @@ namespace Umbraco.Core.Sync
|
||||
}
|
||||
}
|
||||
|
||||
List<WaitHandle> waitHandlesList;
|
||||
var asyncResults = GetAsyncResults(asyncResultsList, out waitHandlesList);
|
||||
|
||||
var waitHandlesList = asyncResultsList.Select(x => x.AsyncWaitHandle).ToArray();
|
||||
|
||||
var errorCount = 0;
|
||||
|
||||
// Once for each WaitHandle that we have, wait for a response and log it
|
||||
// We're previously submitted all these requests effectively in parallel and will now retrieve responses on a FIFO basis
|
||||
foreach (var t in asyncResults)
|
||||
//Wait for all requests to complete
|
||||
WaitHandle.WaitAll(waitHandlesList.ToArray());
|
||||
|
||||
foreach (var t in asyncResultsList)
|
||||
{
|
||||
var handleIndex = WaitHandle.WaitAny(waitHandlesList.ToArray(), TimeSpan.FromSeconds(15));
|
||||
//var handleIndex = WaitHandle.WaitAny(waitHandlesList.ToArray(), TimeSpan.FromSeconds(15));
|
||||
|
||||
try
|
||||
{
|
||||
@@ -520,18 +521,7 @@ namespace Umbraco.Core.Sync
|
||||
LogDispatchBatchError(ee);
|
||||
}
|
||||
}
|
||||
|
||||
internal IEnumerable<IAsyncResult> GetAsyncResults(List<IAsyncResult> asyncResultsList, out List<WaitHandle> waitHandlesList)
|
||||
{
|
||||
var asyncResults = asyncResultsList.ToArray();
|
||||
waitHandlesList = new List<WaitHandle>();
|
||||
foreach (var asyncResult in asyncResults)
|
||||
{
|
||||
waitHandlesList.Add(asyncResult.AsyncWaitHandle);
|
||||
}
|
||||
return asyncResults;
|
||||
}
|
||||
|
||||
|
||||
private void LogDispatchBatchError(Exception ee)
|
||||
{
|
||||
LogHelper.Error<DefaultServerMessenger>("Error refreshing distributed list", ee);
|
||||
|
||||
@@ -8,5 +8,7 @@ namespace Umbraco.Core.Sync
|
||||
public interface IServerAddress
|
||||
{
|
||||
string ServerAddress { get; }
|
||||
|
||||
//TODO : Should probably add things like port, protocol, server name, app id
|
||||
}
|
||||
}
|
||||
@@ -22,19 +22,21 @@ namespace Umbraco.Core.Sync
|
||||
|
||||
/// <remarks/>
|
||||
[System.Web.Services.Protocols.SoapDocumentMethodAttribute("http://umbraco.org/webservices/BulkRefresh", RequestNamespace = "http://umbraco.org/webservices/", ResponseNamespace = "http://umbraco.org/webservices/", Use = System.Web.Services.Description.SoapBindingUse.Literal, ParameterStyle = System.Web.Services.Protocols.SoapParameterStyle.Wrapped)]
|
||||
public void BulkRefresh(RefreshInstruction[] instructions, string login, string password)
|
||||
public void BulkRefresh(RefreshInstruction[] instructions, string appId, string login, string password)
|
||||
{
|
||||
this.Invoke("BulkRefresh", new object[] {
|
||||
instructions,
|
||||
appId,
|
||||
login,
|
||||
password});
|
||||
}
|
||||
|
||||
/// <remarks/>
|
||||
public System.IAsyncResult BeginBulkRefresh(RefreshInstruction[] instructions, string login, string password, System.AsyncCallback callback, object asyncState)
|
||||
public System.IAsyncResult BeginBulkRefresh(RefreshInstruction[] instructions, string appId, string login, string password, System.AsyncCallback callback, object asyncState)
|
||||
{
|
||||
return this.BeginInvoke("BulkRefresh", new object[] {
|
||||
instructions,
|
||||
appId,
|
||||
login,
|
||||
password}, callback, asyncState);
|
||||
}
|
||||
|
||||
@@ -39,6 +39,82 @@ namespace Umbraco.Tests.Services
|
||||
//TODO Add test to verify there is only ONE newest document/content in cmsDocument table after updating.
|
||||
//TODO Add test to delete specific version (with and without deleting prior versions) and versions by date.
|
||||
|
||||
[Test]
|
||||
public void Count_All()
|
||||
{
|
||||
// Arrange
|
||||
var contentService = ServiceContext.ContentService;
|
||||
|
||||
// Act
|
||||
for (int i = 0; i < 20; i++)
|
||||
{
|
||||
contentService.CreateContentWithIdentity("Test", -1, "umbTextpage", 0);
|
||||
}
|
||||
|
||||
// Assert
|
||||
Assert.AreEqual(24, contentService.Count());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Count_By_Content_Type()
|
||||
{
|
||||
// Arrange
|
||||
var contentService = ServiceContext.ContentService;
|
||||
var contentTypeService = ServiceContext.ContentTypeService;
|
||||
var contentType = MockedContentTypes.CreateSimpleContentType("umbBlah", "test Doc Type");
|
||||
contentTypeService.Save(contentType);
|
||||
|
||||
// Act
|
||||
for (int i = 0; i < 20; i++)
|
||||
{
|
||||
contentService.CreateContentWithIdentity("Test", -1, "umbBlah", 0);
|
||||
}
|
||||
|
||||
// Assert
|
||||
Assert.AreEqual(20, contentService.Count(contentTypeAlias: "umbBlah"));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Count_Children()
|
||||
{
|
||||
// Arrange
|
||||
var contentService = ServiceContext.ContentService;
|
||||
var contentTypeService = ServiceContext.ContentTypeService;
|
||||
var contentType = MockedContentTypes.CreateSimpleContentType("umbBlah", "test Doc Type");
|
||||
contentTypeService.Save(contentType);
|
||||
var parent = contentService.CreateContentWithIdentity("Test", -1, "umbBlah", 0);
|
||||
|
||||
// Act
|
||||
for (int i = 0; i < 20; i++)
|
||||
{
|
||||
contentService.CreateContentWithIdentity("Test", parent, "umbBlah");
|
||||
}
|
||||
|
||||
// Assert
|
||||
Assert.AreEqual(20, contentService.CountChildren(parent.Id));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Count_Descendants()
|
||||
{
|
||||
// Arrange
|
||||
var contentService = ServiceContext.ContentService;
|
||||
var contentTypeService = ServiceContext.ContentTypeService;
|
||||
var contentType = MockedContentTypes.CreateSimpleContentType("umbBlah", "test Doc Type");
|
||||
contentTypeService.Save(contentType);
|
||||
var parent = contentService.CreateContentWithIdentity("Test", -1, "umbBlah", 0);
|
||||
|
||||
// Act
|
||||
IContent current = parent;
|
||||
for (int i = 0; i < 20; i++)
|
||||
{
|
||||
current = contentService.CreateContentWithIdentity("Test", current, "umbBlah");
|
||||
}
|
||||
|
||||
// Assert
|
||||
Assert.AreEqual(20, contentService.CountDescendants(parent.Id));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Tags_For_Entity_Are_Not_Exposed_Via_Tag_Api_When_Content_Is_Recycled()
|
||||
{
|
||||
|
||||
@@ -2,6 +2,7 @@ using System;
|
||||
using System.Linq;
|
||||
using NUnit.Framework;
|
||||
using Umbraco.Core;
|
||||
using Umbraco.Core.Events;
|
||||
using Umbraco.Core.Models;
|
||||
using Umbraco.Core.Models.EntityBase;
|
||||
using Umbraco.Core.Models.Membership;
|
||||
@@ -376,6 +377,34 @@ namespace Umbraco.Tests.Services
|
||||
Assert.IsNull(ServiceContext.MemberService.GetByEmail("do@not.find"));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Get_Member_Name()
|
||||
{
|
||||
IMemberType memberType = MockedContentTypes.CreateSimpleMemberType();
|
||||
ServiceContext.MemberTypeService.Save(memberType);
|
||||
IMember member = MockedMember.CreateSimpleMember(memberType, "Test Real Name", "test@test.com", "pass", "testUsername");
|
||||
ServiceContext.MemberService.Save(member);
|
||||
|
||||
|
||||
Assert.AreEqual("Test Real Name", member.Name);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Get_Member_Name_In_Created_Event()
|
||||
{
|
||||
IMemberType memberType = MockedContentTypes.CreateSimpleMemberType();
|
||||
ServiceContext.MemberTypeService.Save(memberType);
|
||||
|
||||
TypedEventHandler<IMemberService, NewEventArgs<IMember>> callback = (sender, args) =>
|
||||
{
|
||||
Assert.AreEqual("Test Real Name", args.Entity.Name);
|
||||
};
|
||||
|
||||
MemberService.Created += callback;
|
||||
var member = ServiceContext.MemberService.CreateMember("testUsername", "test@test.com", "Test Real Name", memberType);
|
||||
MemberService.Created -= callback;
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Get_By_Username()
|
||||
{
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
<%@ Page MasterPageFile="../masterpages/umbracoPage.Master" Language="c#" CodeBehind="EditTemplate.aspx.cs"
|
||||
ValidateRequest="false" AutoEventWireup="True" Inherits="Umbraco.Web.UI.Umbraco.Settings.EditTemplate" %>
|
||||
|
||||
<%@ OutputCache Location="None" %>
|
||||
|
||||
<%@ Import Namespace="Umbraco.Core" %>
|
||||
<%@ Import Namespace="Umbraco.Core.Configuration" %>
|
||||
<%@ Import Namespace="Umbraco.Core.IO" %>
|
||||
|
||||
@@ -2,6 +2,8 @@
|
||||
CodeBehind="EditView.aspx.cs" Inherits="Umbraco.Web.UI.Umbraco.Settings.Views.EditView"
|
||||
ValidateRequest="False" %>
|
||||
|
||||
<%@ OutputCache Location="None" %>
|
||||
|
||||
<%@ Import Namespace="Umbraco.Core" %>
|
||||
<%@ Import Namespace="Umbraco.Core.IO" %>
|
||||
<%@ Register TagPrefix="cc1" Namespace="umbraco.uicontrols" Assembly="controls" %>
|
||||
|
||||
@@ -67,6 +67,43 @@ namespace Umbraco.Web
|
||||
public string JsonPayload { get; set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// We need to check if distributed calls are enabled, if they are we also want to make sure
|
||||
/// that the current server's cache is updated internally in real time instead of at the end of
|
||||
/// the call. This is because things like the URL cache, etc... might need to be updated during
|
||||
/// the request that is making these calls.
|
||||
/// </summary>
|
||||
/// <param name="servers"></param>
|
||||
/// <param name="refresher"></param>
|
||||
/// <param name="dispatchType"></param>
|
||||
/// <param name="ids"></param>
|
||||
/// <param name="jsonPayload"></param>
|
||||
/// <remarks>
|
||||
/// See: http://issues.umbraco.org/issue/U4-2633#comment=67-15604
|
||||
/// </remarks>
|
||||
protected override void MessageSeversForIdsOrJson(IEnumerable<IServerAddress> servers, ICacheRefresher refresher, MessageType dispatchType, IEnumerable<object> ids = null, string jsonPayload = null)
|
||||
{
|
||||
//do all the normal stuff
|
||||
base.MessageSeversForIdsOrJson(servers, refresher, dispatchType, ids, jsonPayload);
|
||||
|
||||
//Now, check if we are using Distrubuted calls
|
||||
if (UseDistributedCalls && servers.Any())
|
||||
{
|
||||
//invoke on the current server - we will basically be double cache refreshing for the calling
|
||||
// server but that just needs to be done currently, see the link above for details.
|
||||
InvokeMethodOnRefresherInstance(refresher, dispatchType, ids, jsonPayload);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This adds the call to batched list
|
||||
/// </summary>
|
||||
/// <param name="servers"></param>
|
||||
/// <param name="refresher"></param>
|
||||
/// <param name="dispatchType"></param>
|
||||
/// <param name="ids"></param>
|
||||
/// <param name="idArrayType"></param>
|
||||
/// <param name="jsonPayload"></param>
|
||||
protected override void PerformDistributedCall(
|
||||
IEnumerable<IServerAddress> servers,
|
||||
ICacheRefresher refresher,
|
||||
@@ -75,6 +112,7 @@ namespace Umbraco.Web
|
||||
Type idArrayType = null,
|
||||
string jsonPayload = null)
|
||||
{
|
||||
|
||||
//NOTE: we use UmbracoContext instead of HttpContext.Current because when some web methods run async, the
|
||||
// HttpContext.Current is null but the UmbracoContext.Current won't be since we manually assign it.
|
||||
if (UmbracoContext.Current == null || UmbracoContext.Current.HttpContext == null)
|
||||
@@ -205,19 +243,22 @@ namespace Umbraco.Web
|
||||
|
||||
asyncResultsList.Add(
|
||||
cacheRefresher.BeginBulkRefresh(
|
||||
instructions, Login, Password, null, null));
|
||||
instructions,
|
||||
HttpRuntime.AppDomainAppId,
|
||||
Login, Password, null, null));
|
||||
}
|
||||
|
||||
List<WaitHandle> waitHandlesList;
|
||||
var asyncResults = GetAsyncResults(asyncResultsList, out waitHandlesList);
|
||||
|
||||
var waitHandlesList = asyncResultsList.Select(x => x.AsyncWaitHandle).ToArray();
|
||||
|
||||
var errorCount = 0;
|
||||
|
||||
// Once for each WaitHandle that we have, wait for a response and log it
|
||||
// We're previously submitted all these requests effectively in parallel and will now retrieve responses on a FIFO basis
|
||||
foreach (var t in asyncResults)
|
||||
//Wait for all requests to complete
|
||||
WaitHandle.WaitAll(waitHandlesList.ToArray());
|
||||
|
||||
foreach (var t in asyncResultsList)
|
||||
{
|
||||
var handleIndex = WaitHandle.WaitAny(waitHandlesList.ToArray(), TimeSpan.FromSeconds(15));
|
||||
//var handleIndex = WaitHandle.WaitAny(waitHandlesList.ToArray(), TimeSpan.FromSeconds(15));
|
||||
|
||||
try
|
||||
{
|
||||
cacheRefresher.EndBulkRefresh(t);
|
||||
|
||||
@@ -24,13 +24,26 @@ namespace umbraco.presentation.webservices
|
||||
{
|
||||
|
||||
[WebMethod]
|
||||
public void BulkRefresh(RefreshInstruction[] instructions, string login, string password)
|
||||
public void BulkRefresh(RefreshInstruction[] instructions, string appId, string login, string password)
|
||||
{
|
||||
if (BusinessLogic.User.validateCredentials(login, password) == false)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
//check if this is the same app id as the one passed in, if it is, then we will ignore
|
||||
// the request - we will have to assume that the cache refeshing has already been applied to the server
|
||||
// that executed the request.
|
||||
if (SystemUtilities.GetCurrentTrustLevel() == AspNetHostingPermissionLevel.Unrestricted)
|
||||
{
|
||||
//we can only check this in full trust. if it's in medium trust we'll just end up with
|
||||
// the server refreshing it's cache twice.
|
||||
if (HttpRuntime.AppDomainAppId == appId)
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
//only execute distinct instructions - no sense in running the same one.
|
||||
foreach (var instruction in instructions.Distinct())
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user