Merge branch 'dev-v7' into dev-v7.8

# Conflicts:
#	src/SolutionInfo.cs
#	src/Umbraco.Core/Configuration/UmbracoVersion.cs
#	src/Umbraco.Core/UdiEntityType.cs
#	src/Umbraco.Core/Umbraco.Core.csproj
#	src/Umbraco.Web.UI/Umbraco.Web.UI.csproj
#	src/umbraco.cms/umbraco.cms.csproj
This commit is contained in:
Shannon
2017-12-14 16:24:25 +11:00
44 changed files with 549 additions and 229 deletions
-2
View File
@@ -49,11 +49,9 @@
<Reference Include="System.Core" />
<Reference Include="System.Data.SqlServerCe, Version=4.0.0.1, Culture=neutral, PublicKeyToken=89845dcd8080cc91, processorArchitecture=MSIL">
<HintPath>..\packages\SqlServerCE.4.0.0.1\lib\System.Data.SqlServerCe.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="System.Data.SqlServerCe.Entity, Version=4.0.0.1, Culture=neutral, PublicKeyToken=89845dcd8080cc91, processorArchitecture=MSIL">
<HintPath>..\packages\SqlServerCE.4.0.0.1\lib\System.Data.SqlServerCe.Entity.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
@@ -0,0 +1,95 @@
using System;
using System.IO;
using log4net.Appender;
using log4net.Util;
namespace Umbraco.Core.Logging
{
/// <summary>
/// This class will do the exact same thing as the RollingFileAppender that comes from log4net
/// With the extension, that it is able to do automatic cleanup of the logfiles in the directory where logging happens
///
/// By specifying the properties MaxLogFileDays and BaseFilePattern, the files will automaticly get deleted when
/// the logger is configured(typically when the app starts). To utilize this appender swap out the type of the rollingFile appender
/// that ships with Umbraco, to be Umbraco.Core.Logging.RollingFileCleanupAppender, and add the maxLogFileDays and baseFilePattern elements
/// to the configuration i.e.:
///
/// <example>
/// <appender name="rollingFile" type="Log4netAwesomeness.CustomRollingFileAppender, Log4netAwesomeness">
/// <file type="log4net.Util.PatternString" value="App_Data\Logs\UmbracoTraceLog.%property{log4net:HostName}.txt" />
/// <lockingModel type="log4net.Appender.FileAppender+MinimalLock" />
/// <appendToFile value="true" />
/// <rollingStyle value="Date" />
/// <maximumFileSize value="5MB" />
/// <maxLogFileDays value="5"/>
/// <basefilePattern value="UmbracoTraceLog.*.txt.*"/>
/// <layout type="log4net.Layout.PatternLayout">
/// <conversionPattern value=" %date [P%property{processId}/D%property{appDomainId}/T%thread] %-5level %logger - %message%newline" />
/// </layout>
/// <layout type="log4net.Layout.PatternLayout">
/// <conversionPattern value=" %date [P%property{processId}/D%property{appDomainId}/T%thread] %-5level %logger - %message%newline" />
/// </layout>
/// <encoding value="utf-8" />
/// </appender>
/// </example>
/// </summary>
public class RollingFileCleanupAppender : RollingFileAppender
{
public int MaxLogFileDays { get; set; }
public string BaseFilePattern { get; set; }
/// <summary>
/// This override will delete logs older than the specified amount of days
/// </summary>
/// <param name="fileName"></param>
/// <param name="append"></param>
protected override void OpenFile(string fileName, bool append)
{
bool cleanup = true;
// Validate settings and input
if (MaxLogFileDays <= 0)
{
LogLog.Warn(typeof(RollingFileCleanupAppender), "Parameter 'MaxLogFileDays' needs to be a positive integer, aborting cleanup");
cleanup = false;
}
if (string.IsNullOrWhiteSpace(BaseFilePattern))
{
LogLog.Warn(typeof(RollingFileCleanupAppender), "Parameter 'BaseFilePattern' is empty, aborting cleanup");
cleanup = false;
}
// grab the directory we are logging to, as this is were we will search for older logfiles
var logFolder = Path.GetDirectoryName(fileName);
if (Directory.Exists(logFolder) == false)
{
LogLog.Warn(typeof(RollingFileCleanupAppender), string.Format("Directory '{0}' for logfiles does not exist, aborting cleanup", logFolder));
cleanup = false;
}
// If everything is validated, we can do the actual cleanup
if (cleanup)
{
Cleanup(logFolder);
}
base.OpenFile(fileName, append);
}
private void Cleanup(string directoryPath)
{
// only take files that matches the pattern we are using i.e. UmbracoTraceLog.*.txt.*
string[] logFiles = Directory.GetFiles(directoryPath, BaseFilePattern);
LogLog.Debug(typeof(RollingFileCleanupAppender), string.Format("Found {0} files that matches the baseFilePattern: '{1}'", logFiles.Length, BaseFilePattern));
foreach (var logFile in logFiles)
{
DateTime lastAccessTime = System.IO.File.GetLastWriteTimeUtc(logFile);
// take the value from the config file
if (lastAccessTime < DateTime.Now.AddDays(-MaxLogFileDays))
{
LogLog.Debug(typeof(RollingFileCleanupAppender), string.Format("Deleting file {0} as its lastAccessTime is older than {1} days speficied by MaxLogFileDays", logFile, MaxLogFileDays));
base.DeleteFile(logFile);
}
}
}
}
}
@@ -377,7 +377,7 @@ namespace Umbraco.Core.Services
repo.Delete(container);
uow.Commit();
deleteEventArgs.CanCancel = false;
uow.Events.Dispatch(DeletedMediaTypeContainer, this, deleteEventArgs);
uow.Events.Dispatch(DeletedMediaTypeContainer, this, deleteEventArgs, "DeletedMediaTypeContainer");
return OperationStatus.Success(evtMsgs);
//TODO: Audit trail ?
+2 -2
View File
@@ -118,7 +118,7 @@ namespace Umbraco.Core
case UmbracoObjectTypes.Document:
return Document;
case UmbracoObjectTypes.DocumentBlueprint:
return DocumentBlueprint;
return DocumentBluePrint;
case UmbracoObjectTypes.Media:
return Media;
case UmbracoObjectTypes.Member:
@@ -163,7 +163,7 @@ namespace Umbraco.Core
{
case Document:
return UmbracoObjectTypes.Document;
case DocumentBlueprint:
case DocumentBluePrint:
return UmbracoObjectTypes.DocumentBlueprint;
case Media:
return UmbracoObjectTypes.Media;
+2 -9
View File
@@ -39,18 +39,15 @@
<ItemGroup>
<Reference Include="AutoMapper, Version=3.3.1.0, Culture=neutral, PublicKeyToken=be96cd2c38ef1005, processorArchitecture=MSIL">
<HintPath>..\packages\AutoMapper.3.3.1\lib\net40\AutoMapper.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="AutoMapper.Net4, Version=3.3.1.0, Culture=neutral, PublicKeyToken=be96cd2c38ef1005, processorArchitecture=MSIL">
<HintPath>..\packages\AutoMapper.3.3.1\lib\net40\AutoMapper.Net4.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="ClientDependency.Core, Version=1.9.2.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\ClientDependency.1.9.2\lib\net45\ClientDependency.Core.dll</HintPath>
</Reference>
<Reference Include="HtmlAgilityPack, Version=1.4.9.5, Culture=neutral, PublicKeyToken=bd319b19eaf3b43a, processorArchitecture=MSIL">
<HintPath>..\packages\HtmlAgilityPack.1.4.9.5\lib\Net45\HtmlAgilityPack.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="ImageProcessor, Version=2.5.6.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\ImageProcessor.2.5.6\lib\net45\ImageProcessor.dll</HintPath>
@@ -63,11 +60,9 @@
</Reference>
<Reference Include="Microsoft.AspNet.Identity.Core, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<HintPath>..\packages\Microsoft.AspNet.Identity.Core.2.2.1\lib\net45\Microsoft.AspNet.Identity.Core.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="Microsoft.AspNet.Identity.Owin, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<HintPath>..\packages\Microsoft.AspNet.Identity.Owin.2.2.1\lib\net45\Microsoft.AspNet.Identity.Owin.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="Microsoft.Owin, Version=3.1.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<HintPath>..\packages\Microsoft.Owin.3.1.0\lib\net45\Microsoft.Owin.dll</HintPath>
@@ -83,17 +78,16 @@
</Reference>
<Reference Include="MiniProfiler, Version=2.1.0.0, Culture=neutral, PublicKeyToken=b44f9351044011a3, processorArchitecture=MSIL">
<HintPath>..\packages\MiniProfiler.2.1.0\lib\net40\MiniProfiler.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="MySql.Data, Version=6.9.9.0, Culture=neutral, PublicKeyToken=c5687fc88969c44d, processorArchitecture=MSIL">
<HintPath>..\packages\MySql.Data.6.9.9\lib\net45\MySql.Data.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="Newtonsoft.Json, Version=10.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
<HintPath>..\packages\Newtonsoft.Json.10.0.2\lib\net45\Newtonsoft.Json.dll</HintPath>
</Reference>
<Reference Include="Owin, Version=1.0.0.0, Culture=neutral, PublicKeyToken=f0ebd12fd5e55cc5, processorArchitecture=MSIL">
<HintPath>..\packages\Owin.1.0\lib\net40\Owin.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="Semver, Version=1.1.2.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\semver.1.1.2\lib\net45\Semver.dll</HintPath>
@@ -105,11 +99,9 @@
<Reference Include="System.Data.Entity" />
<Reference Include="System.Data.SqlServerCe, Version=4.0.0.1, Culture=neutral, PublicKeyToken=89845dcd8080cc91, processorArchitecture=MSIL">
<HintPath>..\packages\SqlServerCE.4.0.0.1\lib\System.Data.SqlServerCe.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="System.Data.SqlServerCe.Entity, Version=4.0.0.1, Culture=neutral, PublicKeyToken=89845dcd8080cc91, processorArchitecture=MSIL">
<HintPath>..\packages\SqlServerCE.4.0.0.1\lib\System.Data.SqlServerCe.Entity.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="System.DirectoryServices.AccountManagement" />
<Reference Include="System.Drawing" />
@@ -368,6 +360,7 @@
<Compile Include="HashGenerator.cs" />
<Compile Include="IEmailSender.cs" />
<Compile Include="IHttpContextAccessor.cs" />
<Compile Include="Logging\RollingFileCleanupAppender.cs" />
<Compile Include="Models\EntityBase\EntityPath.cs" />
<Compile Include="Models\EntityBase\IDeletableEntity.cs" />
<Compile Include="Models\IAuditItem.cs" />
@@ -40,34 +40,27 @@
<ItemGroup>
<Reference Include="BenchmarkDotNet, Version=0.9.9.0, Culture=neutral, PublicKeyToken=aa0ca2f9092cefc4, processorArchitecture=MSIL">
<HintPath>..\packages\BenchmarkDotNet.0.9.9\lib\net45\BenchmarkDotNet.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="BenchmarkDotNet.Core, Version=0.9.9.0, Culture=neutral, PublicKeyToken=aa0ca2f9092cefc4, processorArchitecture=MSIL">
<HintPath>..\packages\BenchmarkDotNet.Core.0.9.9\lib\net45\BenchmarkDotNet.Core.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="BenchmarkDotNet.Diagnostics.Windows, Version=0.9.9.0, Culture=neutral, PublicKeyToken=aa0ca2f9092cefc4, processorArchitecture=MSIL">
<HintPath>..\packages\BenchmarkDotNet.Diagnostics.Windows.0.9.9\lib\net45\BenchmarkDotNet.Diagnostics.Windows.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="BenchmarkDotNet.Toolchains.Roslyn, Version=0.9.9.0, Culture=neutral, PublicKeyToken=aa0ca2f9092cefc4, processorArchitecture=MSIL">
<HintPath>..\packages\BenchmarkDotNet.Toolchains.Roslyn.0.9.9\lib\net45\BenchmarkDotNet.Toolchains.Roslyn.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="Castle.Core, Version=4.0.0.0, Culture=neutral, PublicKeyToken=407dd0808d44fbdc, processorArchitecture=MSIL">
<HintPath>..\packages\Castle.Core.4.0.0\lib\net45\Castle.Core.dll</HintPath>
</Reference>
<Reference Include="Microsoft.CodeAnalysis, Version=1.3.1.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<HintPath>..\packages\Microsoft.CodeAnalysis.Common.1.3.2\lib\net45\Microsoft.CodeAnalysis.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="Microsoft.CodeAnalysis.CSharp, Version=1.3.1.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<HintPath>..\packages\Microsoft.CodeAnalysis.CSharp.1.3.2\lib\net45\Microsoft.CodeAnalysis.CSharp.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="Microsoft.Diagnostics.Tracing.TraceEvent, Version=1.0.41.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\packages\Microsoft.Diagnostics.Tracing.TraceEvent.1.0.41\lib\net40\Microsoft.Diagnostics.Tracing.TraceEvent.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="Moq, Version=4.1.1309.919, Culture=neutral, PublicKeyToken=69f491c39445e920, processorArchitecture=MSIL">
<HintPath>..\packages\Moq.4.1.1309.0919\lib\net40\Moq.dll</HintPath>
@@ -75,27 +68,22 @@
<Reference Include="System" />
<Reference Include="System.Collections.Immutable, Version=1.2.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\packages\System.Collections.Immutable.1.2.0\lib\portable-net45+win8+wp8+wpa81\System.Collections.Immutable.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="System.ComponentModel.Composition" />
<Reference Include="System.Core" />
<Reference Include="System.Data.SqlServerCe, Version=4.0.0.1, Culture=neutral, PublicKeyToken=89845dcd8080cc91, processorArchitecture=MSIL">
<HintPath>..\packages\SqlServerCE.4.0.0.1\lib\System.Data.SqlServerCe.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="System.Data.SqlServerCe.Entity, Version=4.0.0.1, Culture=neutral, PublicKeyToken=89845dcd8080cc91, processorArchitecture=MSIL">
<HintPath>..\packages\SqlServerCE.4.0.0.1\lib\System.Data.SqlServerCe.Entity.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="System.Management" />
<Reference Include="System.Numerics" />
<Reference Include="System.Reflection.Metadata, Version=1.3.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\packages\System.Reflection.Metadata.1.3.0\lib\portable-net45+win8\System.Reflection.Metadata.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="System.Threading.Tasks.Extensions, Version=4.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
<HintPath>..\packages\System.Threading.Tasks.Extensions.4.0.0\lib\portable-net45+win8+wp8+wpa81\System.Threading.Tasks.Extensions.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
@@ -116,6 +104,7 @@
<ItemGroup>
<None Include="App.config" />
<None Include="packages.config" />
<None Include="_TraceEventProgrammersGuide.docx" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Umbraco.Core\Umbraco.Core.csproj">
@@ -132,8 +121,8 @@
</ProjectReference>
</ItemGroup>
<ItemGroup>
<Analyzer Include="..\packages\Microsoft.CodeAnalysis.Analyzers.1.1.0\analyzers\dotnet\cs\Microsoft.CodeAnalysis.Analyzers.dll" />
<Analyzer Include="..\packages\Microsoft.CodeAnalysis.Analyzers.1.1.0\analyzers\dotnet\cs\Microsoft.CodeAnalysis.CSharp.Analyzers.dll" />
<Content Include="TraceEvent.ReadMe.txt" />
<Content Include="TraceEvent.ReleaseNotes.txt" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<PropertyGroup>
+2 -2
View File
@@ -62,8 +62,8 @@
<Reference Include="Castle.Core, Version=4.0.0.0, Culture=neutral, PublicKeyToken=407dd0808d44fbdc, processorArchitecture=MSIL">
<HintPath>..\packages\Castle.Core.4.0.0\lib\net45\Castle.Core.dll</HintPath>
</Reference>
<Reference Include="Examine, Version=0.1.88.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\Examine.0.1.88\lib\net45\Examine.dll</HintPath>
<Reference Include="Examine, Version=0.1.89.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\Examine.0.1.89-beta05\lib\net45\Examine.dll</HintPath>
</Reference>
<Reference Include="ICSharpCode.SharpZipLib, Version=0.86.0.518, Culture=neutral, PublicKeyToken=1b03e6acf1164f73, processorArchitecture=MSIL">
<HintPath>..\packages\SharpZipLib.0.86.0\lib\20\ICSharpCode.SharpZipLib.dll</HintPath>
+1 -1
View File
@@ -2,7 +2,7 @@
<packages>
<package id="AutoMapper" version="3.3.1" targetFramework="net45" />
<package id="Castle.Core" version="4.0.0" targetFramework="net45" />
<package id="Examine" version="0.1.88" targetFramework="net45" />
<package id="Examine" version="0.1.89-beta05" targetFramework="net45" />
<package id="log4net" version="2.0.8" targetFramework="net45" />
<package id="Log4Net.Async" version="2.0.4" targetFramework="net45" />
<package id="Lucene.Net" version="2.9.4.1" targetFramework="net45" />
@@ -366,6 +366,9 @@ angular.module("umbraco.directives")
// element might still be there even after the modal has been hidden.
scope.$on('$destroy', function () {
unsubscribe();
if (tinyMceEditor !== undefined && tinyMceEditor != null) {
tinyMceEditor.destroy()
}
});
});
@@ -2,7 +2,7 @@
<umb-control-group label="@general_url">
<input id="url" class="umb-editor input-block-level" type="text" style="margin-bottom: 10px;" ng-model="model.embed.url" ng-keyup="$event.keyCode == 13 ? vm.showPreview() : null" required />
<input type="button" ng-click="vm.showPreview()" class="btn" localize="value" value="@general_retrieve" />
<input type="button" ng-click="vm.showPreview()" class="btn" value="@general_retrieve" localize="value" />
</umb-control-group>
<umb-control-group>
@@ -12,15 +12,15 @@
<div ng-show="model.embed.supportsDimensions">
<umb-control-group label="@general_width">
<input type="text" ng-model="model.embed.width" on-blur="vm.changeSize('width')" />
<input type="number" pattern="[0-9]*" min="0" ng-model="model.embed.width" on-blur="vm.changeSize('width')" />
</umb-control-group>
<umb-control-group label="@general_height">
<input type="text" ng-model="model.embed.height" on-blur="vm.changeSize('height')" />
<input type="number" pattern="[0-9]*" min="0" ng-model="model.embed.height" on-blur="vm.changeSize('height')" />
</umb-control-group>
<umb-control-group label="@general_constrain">
<input id="constrain" type="checkbox" ng-model="model.embed.constrain" />
<input id="constrain" type="checkbox" ng-model="model.embed.constrain" />
</umb-control-group>
</div>
@@ -374,6 +374,9 @@ angular.module("umbraco")
// element might still be there even after the modal has been hidden.
$scope.$on('$destroy', function () {
unsubscribe();
if (tinyMceEditor !== undefined && tinyMceEditor != null) {
tinyMceEditor.destroy()
}
});
});
});
+2 -4
View File
@@ -127,11 +127,10 @@
<Reference Include="dotless.Core, Version=1.5.2.0, Culture=neutral, PublicKeyToken=96b446c9e63eae34, processorArchitecture=MSIL">
<HintPath>..\packages\dotless.1.5.2\lib\dotless.Core.dll</HintPath>
</Reference>
<Reference Include="Examine, Version=0.1.88.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\Examine.0.1.88\lib\net45\Examine.dll</HintPath>
<Reference Include="Examine, Version=0.1.89.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\Examine.0.1.89-beta05\lib\net45\Examine.dll</HintPath>
</Reference>
<Reference Include="ICSharpCode.SharpZipLib, Version=0.86.0.518, Culture=neutral, PublicKeyToken=1b03e6acf1164f73, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\SharpZipLib.0.86.0\lib\20\ICSharpCode.SharpZipLib.dll</HintPath>
</Reference>
<Reference Include="ImageProcessor, Version=2.5.6.0, Culture=neutral, processorArchitecture=MSIL">
@@ -144,7 +143,6 @@
<HintPath>..\packages\log4net.2.0.8\lib\net45-full\log4net.dll</HintPath>
</Reference>
<Reference Include="Lucene.Net, Version=2.9.4.1, Culture=neutral, PublicKeyToken=85089178b9ac3181, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\Lucene.Net.2.9.4.1\lib\net40\Lucene.Net.dll</HintPath>
</Reference>
<Reference Include="Microsoft.AspNet.Identity.Core">
+12 -1
View File
@@ -422,7 +422,7 @@
<key alias="showPageOnSend">Hvilken side skal vises etter at skjemaet er sendt</key>
<key alias="size">Størrelse</key>
<key alias="sort">Sorter</key>
<key alias="submit">Submit</key> <!-- TODO: Translate this -->
<key alias="submit">Send</key>
<key alias="type">Type</key>
<key alias="typeToSearch">Søk...</key>
<key alias="up">Opp</key>
@@ -439,6 +439,17 @@
<key alias="yes">Ja</key>
<key alias="folder">Mappe</key>
<key alias="searchResults">Søkeresultater</key>
<key alias="reorder">Sorter</key>
<key alias="reorderDone">Avslutt sortering</key>
<key alias="preview">Eksempel</key>
<key alias="changePassword">Bytt passord</key>
<key alias="to">til</key>
<key alias="listView">Listevisning</key>
<key alias="saving">Lagrer...</key>
<key alias="current">nåværende</key>
<key alias="embed">Innbygging</key>
<key alias="retrieve">Hent</key>
<key alias="selected">valgt</key>
</area>
<area alias="graphicheadline">
<key alias="backgroundcolor">Bakgrunnsfarge</key>
+1 -1
View File
@@ -4,7 +4,7 @@
<package id="ClientDependency" version="1.9.2" targetFramework="net45" />
<package id="ClientDependency-Mvc5" version="1.8.0.0" targetFramework="net45" />
<package id="dotless" version="1.5.2" targetFramework="net45" />
<package id="Examine" version="0.1.88" targetFramework="net45" />
<package id="Examine" version="0.1.89-beta05" targetFramework="net45" />
<package id="ImageProcessor" version="2.5.6" targetFramework="net45" />
<package id="ImageProcessor.Web" version="4.8.7" targetFramework="net45" />
<package id="ImageProcessor.Web.Config" version="2.3.1" targetFramework="net45" />
@@ -590,7 +590,6 @@
<key alias="sort">Sortér</key>
<key alias="status">Status</key>
<key alias="submit">Indsend</key>
<!-- TODO: Translate this -->
<key alias="type">Type</key>
<key alias="typeToSearch">Skriv for at søge...</key>
<key alias="up">Op</key>
@@ -616,6 +615,7 @@
<key alias="saving">Gemmer...</key>
<key alias="current">nuværende</key>
<key alias="embed">Indlejring</key>
<key alias="retrieve">Hent</key>
<key alias="selected">valgt</key>
</area>
@@ -638,6 +638,7 @@
<key alias="saving">Saving...</key>
<key alias="current">current</key>
<key alias="embed">Embed</key>
<key alias="retrieve">Retrieve</key>
<key alias="selected">selected</key>
</area>
@@ -649,6 +649,7 @@
<key alias="saving">Saving...</key>
<key alias="current">current</key>
<key alias="embed">Embed</key>
<key alias="retrieve">Retrieve</key>
<key alias="selected">selected</key>
</area>
<area alias="colors">
+12 -3
View File
@@ -411,7 +411,7 @@
<key alias="showPageOnSend">Vilken sida skall visas när formuläret är skickat</key>
<key alias="size">Storlek</key>
<key alias="sort">Sortera</key>
<key alias="submit">Submit</key> <!-- TODO: Translate this -->
<key alias="submit">Skicka</key>
<key alias="type">Skriv</key>
<key alias="typeToSearch">Skriv för att söka...</key>
<key alias="up">Upp</key>
@@ -426,8 +426,17 @@
<key alias="width">Bredd</key>
<key alias="view">Titta på</key>
<key alias="yes">Ja</key>
<key alias="reorder">Reorder</key>
<key alias="reorderDone">I am done reordering</key>
<key alias="reorder">Sortera</key>
<key alias="reorderDone">Avsluta sortering</key>
<key alias="preview">Förhandsvisning</key>
<key alias="changePassword">Ändra lösenord</key>
<key alias="to">till</key>
<key alias="listView">Listvy</key>
<key alias="saving">Sparar...</key>
<key alias="current">nuvarande</key>
<key alias="embed">Inbäddning</key>
<key alias="retrieve">Hämta</key>
<key alias="selected">valgt</key>
</area>
<area alias="graphicheadline">
<key alias="backgroundcolor">Bakgrundsfärg</key>
+1 -1
View File
@@ -555,7 +555,7 @@ namespace Umbraco.Web.Editors
var builtInAliases = Constants.Conventions.Member.GetStandardPropertyTypeStubs().Select(x => x.Key).ToArray();
foreach (var p in contentItem.PersistedContent.Properties)
{
var valueMapped = currProps.SingleOrDefault(x => x.Alias == p.Alias);
var valueMapped = currProps.FirstOrDefault(x => x.Alias == p.Alias);
if (builtInAliases.Contains(p.Alias) == false && valueMapped != null)
{
p.Value = valueMapped.Value;
+176
View File
@@ -0,0 +1,176 @@
using System.Collections.Generic;
using System.Linq;
using Examine;
using Examine.Config;
using Examine.LuceneEngine;
using Examine.LuceneEngine.Providers;
using Examine.Providers;
using Lucene.Net.Index;
using Lucene.Net.Store;
using Umbraco.Core;
using Umbraco.Core.Logging;
using UmbracoExamine;
namespace Umbraco.Web
{
/// <summary>
/// Used to configure Examine during startup for the web application
/// </summary>
internal class ExamineStartup
{
private readonly List<BaseIndexProvider> _indexesToRebuild = new List<BaseIndexProvider>();
private readonly ApplicationContext _appCtx;
private readonly ProfilingLogger _profilingLogger;
//this is used if we are not the MainDom, in which case we need to ensure that if indexes need rebuilding that this
//doesn't occur since that should only occur when we are MainDom
private bool _disableExamineIndexing = false;
public ExamineStartup(ApplicationContext appCtx)
{
_appCtx = appCtx;
_profilingLogger = appCtx.ProfilingLogger;
}
/// <summary>
/// Called during the initialize operation of the boot manager process
/// </summary>
public void Initialize()
{
//We want to manage Examine's appdomain shutdown sequence ourselves so first we'll disable Examine's default behavior
//and then we'll use MainDom to control Examine's shutdown
ExamineManager.DisableDefaultHostingEnvironmentRegistration();
//we want to tell examine to use a different fs lock instead of the default NativeFSFileLock which could cause problems if the appdomain
//terminates and in some rare cases would only allow unlocking of the file if IIS is forcefully terminated. Instead we'll rely on the simplefslock
//which simply checks the existence of the lock file
DirectoryTracker.DefaultLockFactory = d =>
{
var simpleFsLockFactory = new NoPrefixSimpleFsLockFactory(d);
return simpleFsLockFactory;
};
//This is basically a hack for this item: http://issues.umbraco.org/issue/U4-5976
// when Examine initializes it will try to rebuild if the indexes are empty, however in many cases not all of Examine's
// event handlers will be assigned during bootup when the rebuilding starts which is a problem. So with the examine 0.1.58.2941 build
// it has an event we can subscribe to in order to cancel this rebuilding process, but what we'll do is cancel it and postpone the rebuilding until the
// boot process has completed. It's a hack but it works.
ExamineManager.Instance.BuildingEmptyIndexOnStartup += OnInstanceOnBuildingEmptyIndexOnStartup;
//let's deal with shutting down Examine with MainDom
var examineShutdownRegistered = _appCtx.MainDom.Register(() =>
{
using (_profilingLogger.TraceDuration<ExamineStartup>("Examine shutting down"))
{
//Due to the way Examine's own IRegisteredObject works, we'll first run it with immediate=false and then true so that
//it's correct subroutines are executed (otherwise we'd have to run this logic manually ourselves)
ExamineManager.Instance.Stop(false);
ExamineManager.Instance.Stop(true);
}
});
if (examineShutdownRegistered)
{
_profilingLogger.Logger.Debug<ExamineStartup>("Examine shutdown registered with MainDom");
}
else
{
_profilingLogger.Logger.Debug<ExamineStartup>("Examine shutdown not registered, this appdomain is not the MainDom");
//if we could not register the shutdown examine ourselves, it means we are not maindom! in this case all of examine should be disabled
//from indexing anything on startup!!
_disableExamineIndexing = true;
Suspendable.ExamineEvents.SuspendIndexers();
}
}
/// <summary>
/// Called during the Complete operation of the boot manager process
/// </summary>
public void Complete()
{
//We now need to disable waiting for indexing for Examine so that the appdomain is shutdown immediately and doesn't wait for pending
//indexing operations. We used to wait for indexing operations to complete but this can cause more problems than that is worth because
//that could end up halting shutdown for a very long time causing overlapping appdomains and many other problems.
foreach (var luceneIndexer in ExamineManager.Instance.IndexProviderCollection.OfType<LuceneIndexer>())
{
luceneIndexer.WaitForIndexQueueOnShutdown = false;
}
//Ok, now that everything is complete we'll check if we've stored any references to index that need rebuilding and run them
// (see the initialize method for notes) - we'll ensure we remove the event handler too in case examine manager doesn't actually
// initialize during startup, in which case we want it to rebuild the indexes itself.
ExamineManager.Instance.BuildingEmptyIndexOnStartup -= OnInstanceOnBuildingEmptyIndexOnStartup;
//don't do anything if we have disabled this
if (_disableExamineIndexing == false)
{
foreach (var indexer in _indexesToRebuild)
{
indexer.RebuildIndex();
}
}
}
/// <summary>
/// Called to perform the rebuilding indexes on startup if the indexes don't exist
/// </summary>
public void RebuildIndexes()
{
//don't do anything if we have disabled this
if (_disableExamineIndexing) return;
//If the developer has explicitly opted out of rebuilding indexes on startup then we
// should adhere to that and not do it, this means that if they are load balancing things will be
// out of sync if they are auto-scaling but there's not much we can do about that.
if (ExamineSettings.Instance.RebuildOnAppStart == false) return;
foreach (var indexer in GetIndexesForColdBoot())
{
indexer.RebuildIndex();
}
}
/// <summary>
/// The method used to create indexes on a cold boot
/// </summary>
/// <remarks>
/// A cold boot is when the server determines it will not (or cannot) process instructions in the cache table and
/// will rebuild it's own caches itself.
/// </remarks>
public IEnumerable<BaseIndexProvider> GetIndexesForColdBoot()
{
// NOTE: This is IMPORTANT! ... we don't want to rebuild any index that is already flagged to be re-indexed
// on startup based on our _indexesToRebuild variable and how Examine auto-rebuilds when indexes are empty.
// This callback is used above for the DatabaseServerMessenger startup options.
// all indexes
IEnumerable<BaseIndexProvider> indexes = ExamineManager.Instance.IndexProviderCollection;
// except those that are already flagged
// and are processed in Complete()
if (_indexesToRebuild.Any())
indexes = indexes.Except(_indexesToRebuild);
// return
foreach (var index in indexes)
yield return index;
}
private void OnInstanceOnBuildingEmptyIndexOnStartup(object sender, BuildingEmptyIndexOnStartupEventArgs args)
{
//store the indexer that needs rebuilding because it's empty for when the boot process
// is complete and cancel this current event so the rebuild process doesn't start right now.
args.Cancel = true;
_indexesToRebuild.Add((BaseIndexProvider)args.Indexer);
//check if the index is rebuilding due to an error and log it
if (args.IsHealthy == false)
{
var baseIndex = args.Indexer as BaseIndexProvider;
var name = baseIndex != null ? baseIndex.Name : "[UKNOWN]";
_profilingLogger.Logger.Error<ExamineStartup>(string.Format("The index {0} is rebuilding due to being unreadable/corrupt", name), args.UnhealthyException);
}
}
}
}
@@ -86,7 +86,16 @@ namespace Umbraco.Web.Scheduling
finally
{
if (tempContext != null)
{
// because we created an http context and assigned it to UmbracoContext,
// the batched messenger does batch instructions, but since there is no
// request, we need to explicitely tell it to flush the batch of instrs.
var batchedMessenger = ServerMessengerResolver.Current.Messenger as BatchedDatabaseServerMessenger;
if (batchedMessenger != null)
batchedMessenger.FlushBatch();
tempContext.Dispose(); // nulls the ThreadStatic context
}
}
return true; // repeat
+3 -4
View File
@@ -112,8 +112,8 @@
<Reference Include="dotless.Core, Version=1.5.2.0, Culture=neutral, PublicKeyToken=96b446c9e63eae34, processorArchitecture=MSIL">
<HintPath>..\packages\dotless.1.5.2\lib\dotless.Core.dll</HintPath>
</Reference>
<Reference Include="Examine, Version=0.1.88.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\Examine.0.1.88\lib\net45\Examine.dll</HintPath>
<Reference Include="Examine, Version=0.1.89.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\Examine.0.1.89-beta05\lib\net45\Examine.dll</HintPath>
</Reference>
<Reference Include="HtmlAgilityPack, Version=1.4.9.5, Culture=neutral, PublicKeyToken=bd319b19eaf3b43a, processorArchitecture=MSIL">
<HintPath>..\packages\HtmlAgilityPack.1.4.9.5\lib\Net45\HtmlAgilityPack.dll</HintPath>
@@ -121,11 +121,9 @@
</Reference>
<Reference Include="ICSharpCode.SharpZipLib, Version=0.86.0.518, Culture=neutral, PublicKeyToken=1b03e6acf1164f73, processorArchitecture=MSIL">
<HintPath>..\packages\SharpZipLib.0.86.0\lib\20\ICSharpCode.SharpZipLib.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="Lucene.Net, Version=2.9.4.1, Culture=neutral, PublicKeyToken=85089178b9ac3181, processorArchitecture=MSIL">
<HintPath>..\packages\Lucene.Net.2.9.4.1\lib\net40\Lucene.Net.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="MarkdownSharp, Version=1.14.5.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\Markdown.1.14.7\lib\net45\MarkdownSharp.dll</HintPath>
@@ -335,6 +333,7 @@
<Compile Include="Editors\UserGroupEditorAuthorizationHelper.cs" />
<Compile Include="Editors\UserGroupsController.cs" />
<Compile Include="Editors\UserGroupValidateAttribute.cs" />
<Compile Include="ExamineStartup.cs" />
<Compile Include="Extensions\UdiExtensions.cs" />
<Compile Include="HealthCheck\Checks\Config\AbstractConfigCheck.cs" />
<Compile Include="HealthCheck\Checks\Config\AcceptableConfiguration.cs" />
+1 -10
View File
@@ -97,17 +97,8 @@ namespace Umbraco.Web.WebApi.Binders
if (member == null)
{
throw new InvalidOperationException("Could not find member with key " + key);
}
}
var standardProps = Constants.Conventions.Member.GetStandardPropertyTypeStubs();
//remove all membership properties, these values are set with the membership provider.
var exclude = standardProps.Select(x => x.Value.Alias).ToArray();
foreach (var remove in exclude)
{
member.Properties.Remove(remove);
}
return member;
}
+17 -89
View File
@@ -3,7 +3,6 @@ using System.Collections.Generic;
using System.Collections.Specialized;
using System.Configuration;
using System.Linq;
using System.Reflection;
using System.Web;
using System.Web.Configuration;
using System.Web.Http;
@@ -11,10 +10,7 @@ using System.Web.Http.Dispatcher;
using System.Web.Mvc;
using System.Web.Routing;
using ClientDependency.Core.Config;
using Examine;
using Examine.Config;
using Examine.Providers;
using umbraco;
using Umbraco.Core;
using Umbraco.Core.Configuration;
using Umbraco.Core.Dictionary;
@@ -27,25 +23,18 @@ using Umbraco.Core.PropertyEditors.ValueConverters;
using Umbraco.Core.Sync;
using Umbraco.Web.Dictionary;
using Umbraco.Web.Install;
using Umbraco.Web.Macros;
using Umbraco.Web.Media;
using Umbraco.Web.Media.ThumbnailProviders;
using Umbraco.Web.Models;
using Umbraco.Web.Mvc;
using Umbraco.Web.PropertyEditors;
using Umbraco.Web.PropertyEditors.ValueConverters;
using Umbraco.Web.PublishedCache;
using Umbraco.Web.Routing;
using Umbraco.Web.Security;
using Umbraco.Web.Scheduling;
using Umbraco.Web.UI.JavaScript;
using Umbraco.Web.WebApi;
using umbraco.BusinessLogic;
using Umbraco.Core.Cache;
using Umbraco.Core.Events;
using Umbraco.Core.Persistence;
using Umbraco.Core.Persistence.UnitOfWork;
using Umbraco.Core.Publishing;
using Umbraco.Core.Scoping;
using Umbraco.Core.Services;
using Umbraco.Web.Editors;
@@ -64,8 +53,9 @@ namespace Umbraco.Web
public class WebBootManager : CoreBootManager
{
private readonly bool _isForTesting;
//NOTE: see the Initialize method for what this is used for
private static readonly List<BaseIndexProvider> IndexesToRebuild = new List<BaseIndexProvider>();
//needs to be static because we have the public static method GetIndexesForColdBoot
private static ExamineStartup _examineStartup;
public WebBootManager(UmbracoApplicationBase umbracoApplication)
: base(umbracoApplication)
@@ -109,15 +99,11 @@ namespace Umbraco.Web
/// <returns></returns>
public override IBootManager Initialize()
{
//This is basically a hack for this item: http://issues.umbraco.org/issue/U4-5976
// when Examine initializes it will try to rebuild if the indexes are empty, however in many cases not all of Examine's
// event handlers will be assigned during bootup when the rebuilding starts which is a problem. So with the examine 0.1.58.2941 build
// it has an event we can subscribe to in order to cancel this rebuilding process, but what we'll do is cancel it and postpone the rebuilding until the
// boot process has completed. It's a hack but it works.
ExamineManager.Instance.BuildingEmptyIndexOnStartup += OnInstanceOnBuildingEmptyIndexOnStartup;
base.Initialize();
_examineStartup = new ExamineStartup(ApplicationContext);
_examineStartup.Initialize();
// Backwards compatibility - set the path and URL type for ClientDependency 1.5.1 [LK]
ClientDependency.Core.CompositeFiles.Providers.XmlFileMapper.FileMapVirtualFolder = "~/App_Data/TEMP/ClientDependency";
ClientDependency.Core.CompositeFiles.Providers.BaseCompositeFileProcessingProvider.UrlTypeDefault = ClientDependency.Core.CompositeFiles.Providers.CompositeUrlType.Base64QueryStrings;
@@ -214,25 +200,15 @@ namespace Umbraco.Web
//Now, startup all of our legacy startup handler
ApplicationEventsResolver.Current.InstantiateLegacyStartupHandlers();
//Ok, now that everything is complete we'll check if we've stored any references to index that need rebuilding and run them
// (see the initialize method for notes) - we'll ensure we remove the event handler too in case examine manager doesn't actually
// initialize during startup, in which case we want it to rebuild the indexes itself.
ExamineManager.Instance.BuildingEmptyIndexOnStartup -= OnInstanceOnBuildingEmptyIndexOnStartup;
if (IndexesToRebuild.Any())
{
foreach (var indexer in IndexesToRebuild)
{
indexer.RebuildIndex();
}
}
_examineStartup.Complete();
//Now ensure webapi is initialized after everything
GlobalConfiguration.Configuration.EnsureInitialized();
return this;
}
internal static void ConfigureGlobalFilters()
{
@@ -377,11 +353,11 @@ namespace Umbraco.Web
{
base.InitializeResolvers();
SearchableTreeResolver.Current = new SearchableTreeResolver(ServiceProvider, LoggerResolver.Current.Logger, ApplicationContext.Services.ApplicationTreeService, () => PluginManager.ResolveSearchableTrees());
SearchableTreeResolver.Current = new SearchableTreeResolver(ServiceProvider, LoggerResolver.Current.Logger, ApplicationContext.Services.ApplicationTreeService, () => PluginManager.ResolveSearchableTrees());
XsltExtensionsResolver.Current = new XsltExtensionsResolver(ServiceProvider, LoggerResolver.Current.Logger, () => PluginManager.ResolveXsltExtensions());
EditorValidationResolver.Current= new EditorValidationResolver(ServiceProvider, LoggerResolver.Current.Logger, () => PluginManager.ResolveTypes<IEditorValidator>());
EditorValidationResolver.Current = new EditorValidationResolver(ServiceProvider, LoggerResolver.Current.Logger, () => PluginManager.ResolveTypes<IEditorValidator>());
//set the default RenderMvcController
DefaultRenderMvcControllerResolver.Current = new DefaultRenderMvcControllerResolver(typeof(RenderMvcController));
@@ -421,23 +397,6 @@ namespace Umbraco.Web
}
else
{
//We are using a custom action here so we can check the examine settings value first, we don't want to
// put that check into the CreateIndexesOnColdBoot method because developers may choose to use this
// method directly and they will be in charge of this check if they need it
Action rebuildIndexes = () =>
{
//If the developer has explicitly opted out of rebuilding indexes on startup then we
// should adhere to that and not do it, this means that if they are load balancing things will be
// out of sync if they are auto-scaling but there's not much we can do about that.
if (ExamineSettings.Instance.RebuildOnAppStart == false) return;
foreach (var indexer in GetIndexesForColdBoot())
{
indexer.RebuildIndex();
}
};
ServerMessengerResolver.Current.SetServerMessenger(new BatchedDatabaseServerMessenger(
ApplicationContext,
true,
@@ -453,7 +412,7 @@ namespace Umbraco.Web
//rebuild indexes if the server is not synced
// NOTE: This will rebuild ALL indexes including the members, if developers want to target specific
// indexes then they can adjust this logic themselves.
rebuildIndexes
() => _examineStartup.RebuildIndexes()
}
}));
}
@@ -489,9 +448,9 @@ namespace Umbraco.Web
// add all known factories, devs can then modify this list on application
// startup either by binding to events or in their own global.asax
new[]
{
typeof (RenderControllerFactory)
});
{
typeof (RenderControllerFactory)
});
UrlProviderResolver.Current = new UrlProviderResolver(
ServiceProvider, LoggerResolver.Current.Logger,
@@ -559,42 +518,11 @@ namespace Umbraco.Web
/// <remarks>
/// A cold boot is when the server determines it will not (or cannot) process instructions in the cache table and
/// will rebuild it's own caches itself.
/// TODO: Does this method need to exist? Is it used publicly elsewhere (i.e. outside of core?)
/// </remarks>
public static IEnumerable<BaseIndexProvider> GetIndexesForColdBoot()
{
// NOTE: This is IMPORTANT! ... we don't want to rebuild any index that is already flagged to be re-indexed
// on startup based on our _indexesToRebuild variable and how Examine auto-rebuilds when indexes are empty.
// This callback is used above for the DatabaseServerMessenger startup options.
// all indexes
IEnumerable<BaseIndexProvider> indexes = ExamineManager.Instance.IndexProviderCollection;
// except those that are already flagged
// and are processed in Complete()
if (IndexesToRebuild.Any())
indexes = indexes.Except(IndexesToRebuild);
// return
foreach (var index in indexes)
yield return index;
}
private void OnInstanceOnBuildingEmptyIndexOnStartup(object sender, BuildingEmptyIndexOnStartupEventArgs args)
{
//store the indexer that needs rebuilding because it's empty for when the boot process
// is complete and cancel this current event so the rebuild process doesn't start right now.
args.Cancel = true;
IndexesToRebuild.Add((BaseIndexProvider)args.Indexer);
//check if the index is rebuilding due to an error and log it
if (args.IsHealthy == false)
{
var baseIndex = args.Indexer as BaseIndexProvider;
var name = baseIndex != null ? baseIndex.Name : "[UKNOWN]";
ProfilingLogger.Logger.Error<WebBootManager>(string.Format("The index {0} is rebuilding due to being unreadable/corrupt", name), args.UnhealthyException);
}
return _examineStartup.GetIndexesForColdBoot();
}
}
}
@@ -8,7 +8,9 @@ using Examine;
using Examine.LuceneEngine;
using Examine.LuceneEngine.Providers;
using Examine.Providers;
using Lucene.Net.Index;
using Lucene.Net.Search;
using Lucene.Net.Store;
using Umbraco.Core;
using Umbraco.Core.Logging;
using Umbraco.Web.Search;
@@ -189,20 +191,39 @@ namespace Umbraco.Web.WebServices
{
indexer.RebuildIndex();
}
catch (LockObtainFailedException)
{
//this will occur if the index is locked (which it should defo not be!) so in this case we'll forcibly unlock it and try again
try
{
IndexWriter.Unlock(indexer.GetLuceneDirectory());
indexer.RebuildIndex();
}
catch (Exception e)
{
return HandleException(e, indexer);
}
}
catch (Exception ex)
{
//ensure it's not listening
indexer.IndexOperationComplete -= Indexer_IndexOperationComplete;
LogHelper.Error<ExamineManagementApiController>("An error occurred rebuilding index", ex);
var response = Request.CreateResponse(HttpStatusCode.Conflict);
response.Content = new StringContent(string.Format("The index could not be rebuilt at this time, most likely there is another thread currently writing to the index. Error: {0}", ex));
response.ReasonPhrase = "Could Not Rebuild";
return response;
return HandleException(ex, indexer);
}
}
return msg;
}
private HttpResponseMessage HandleException(Exception ex, LuceneIndexer indexer)
{
//ensure it's not listening
indexer.IndexOperationComplete -= Indexer_IndexOperationComplete;
LogHelper.Error<ExamineManagementApiController>("An error occurred rebuilding index", ex);
var response = Request.CreateResponse(HttpStatusCode.Conflict);
response.Content = new StringContent(string.Format("The index could not be rebuilt at this time, most likely there is another thread currently writing to the index. Error: {0}", ex));
response.ReasonPhrase = "Could Not Rebuild";
return response;
}
//static listener so it's not GC'd
private static void Indexer_IndexOperationComplete(object sender, EventArgs e)
{
+1 -1
View File
@@ -3,7 +3,7 @@
<package id="AutoMapper" version="3.3.1" targetFramework="net45" />
<package id="ClientDependency" version="1.9.2" targetFramework="net45" />
<package id="dotless" version="1.5.2" targetFramework="net45" />
<package id="Examine" version="0.1.88" targetFramework="net45" />
<package id="Examine" version="0.1.89-beta05" targetFramework="net45" />
<package id="HtmlAgilityPack" version="1.4.9.5" targetFramework="net45" />
<package id="Lucene.Net" version="2.9.4.1" targetFramework="net45" />
<package id="Markdown" version="1.14.7" targetFramework="net45" />
+8 -3
View File
@@ -150,7 +150,7 @@ namespace UmbracoExamine
{
//By default, we will be using the UmbracoDataService
//generally this would only need to be set differently for unit testing
DataService = new UmbracoDataService();
DataService = CreateDefaultUmbracoDataService();
}
DataService.LogService.LogLevel = LoggingLevel.Normal;
@@ -206,10 +206,15 @@ namespace UmbracoExamine
}
}
}
}
#endregion
protected virtual IDataService CreateDefaultUmbracoDataService()
{
return new UmbracoDataService();
}
/// <summary>
/// Used to aquire the internal searcher
/// </summary>
@@ -13,10 +13,12 @@ namespace UmbracoExamine.Config
/// </summary>
public static class IndexSetExtensions
{
internal static IIndexCriteria ToIndexCriteria(this IndexSet set, IDataService svc,
StaticFieldCollection indexFieldPolicies)
internal static IIndexCriteria ToIndexCriteria(this IndexSet set,
IDataService svc,
StaticFieldCollection indexFieldPolicies,
IEnumerable<IndexField> additionalUserFields = null)
{
return new LazyIndexCriteria(set, svc, indexFieldPolicies);
return new LazyIndexCriteria(set, svc, indexFieldPolicies, additionalUserFields);
}
/// <summary>
+17 -3
View File
@@ -12,7 +12,8 @@ namespace UmbracoExamine.Config
public LazyIndexCriteria(
IndexSet set,
IDataService svc,
StaticFieldCollection indexFieldPolicies)
StaticFieldCollection indexFieldPolicies,
IEnumerable<IndexField> additionalUserFields = null)
{
if (set == null) throw new ArgumentNullException("set");
if (indexFieldPolicies == null) throw new ArgumentNullException("indexFieldPolicies");
@@ -21,7 +22,7 @@ namespace UmbracoExamine.Config
_lazyCriteria = new Lazy<IIndexCriteria>(() =>
{
var attributeFields = set.IndexAttributeFields.Cast<IIndexField>().ToArray();
var userFields = set.IndexUserFields.Cast<IIndexField>().ToArray();
var userFields = set.IndexUserFields.Cast<IIndexField>().ToList();
var includeNodeTypes = set.IncludeNodeTypes.Cast<IIndexField>().Select(x => x.Name).ToArray();
var excludeNodeTypes = set.ExcludeNodeTypes.Cast<IIndexField>().Select(x => x.Name).ToArray();
var parentId = set.IndexParentId;
@@ -44,7 +45,7 @@ namespace UmbracoExamine.Config
}
fields.Add(field);
}
userFields = fields.ToArray();
userFields = fields.ToList();
}
//if there are no attribute fields defined, we'll populate them from the data source (include them all)
@@ -68,6 +69,19 @@ namespace UmbracoExamine.Config
attributeFields = fields.ToArray();
}
//merge in the additional user fields if any are defined
if (additionalUserFields != null)
{
foreach (var field in additionalUserFields)
{
var f = field; //copy local
if (userFields.Any(x => x.Name == f.Name) == false)
{
userFields.Add(f);
}
}
}
return new IndexCriteria(
attributeFields,
@@ -13,7 +13,7 @@ namespace UmbracoExamine.DataServices
{
public class UmbracoContentService : IContentService
{
private readonly ApplicationContext _applicationContext;
protected ApplicationContext ApplicationContext { get; private set; }
public UmbracoContentService()
: this(ApplicationContext.Current)
@@ -21,7 +21,7 @@ namespace UmbracoExamine.DataServices
public UmbracoContentService(ApplicationContext applicationContext)
{
_applicationContext = applicationContext;
ApplicationContext = applicationContext;
}
/// <summary>
@@ -60,11 +60,11 @@ namespace UmbracoExamine.DataServices
using (var scope = ApplicationContext.Current.ScopeProvider.CreateScope())
{
var xmlContent = XDocument.Parse("<content></content>");
var rootContent = _applicationContext.Services.ContentService.GetRootContent();
var rootContent = ApplicationContext.Services.ContentService.GetRootContent();
foreach (var c in rootContent)
{
// not sure this uses the database, but better be save
xmlContent.Root.Add(c.ToDeepXml(_applicationContext.Services.PackagingService));
xmlContent.Root.Add(c.ToDeepXml(ApplicationContext.Services.PackagingService));
}
var result = ((IEnumerable)xmlContent.XPathEvaluate(xpath)).Cast<XElement>();
scope.Complete();
@@ -82,7 +82,7 @@ namespace UmbracoExamine.DataServices
{
using (var scope = ApplicationContext.Current.ScopeProvider.CreateScope())
{
var ret = _applicationContext.Services.PublicAccessService.IsProtected(path.EnsureEndsWith("," + nodeId));
var ret = ApplicationContext.Services.PublicAccessService.IsProtected(path.EnsureEndsWith("," + nodeId));
scope.Complete();
return ret;
}
@@ -93,14 +93,26 @@ namespace UmbracoExamine.DataServices
/// </summary>
/// <returns></returns>
public IEnumerable<string> GetAllUserPropertyNames()
public virtual IEnumerable<string> GetAllUserPropertyNames()
{
using (var scope = ApplicationContext.Current.ScopeProvider.CreateScope())
{
try
{
var result = _applicationContext.DatabaseContext.Database.Fetch<string>("select distinct alias from cmsPropertyType order by alias");
scope.Complete();
{
//only return the property type aliases for media and content
var result = ApplicationContext.DatabaseContext.Database.Fetch<string>(
@"select distinct cmsPropertyType.alias from cmsPropertyType
inner join cmsContentType on cmsContentType.nodeId = cmsPropertyType.contentTypeId
inner join umbracoNode on umbracoNode.id = cmsContentType.nodeId
where umbracoNode.nodeObjectType = @contentNodeObjectType OR umbracoNode.nodeObjectType = @mediaNodeObjectType
order by alias", new
{
contentNodeObjectType = Constants.ObjectTypes.DocumentType,
mediaNodeObjectType = Constants.ObjectTypes.MediaType
});
scope.Complete();
return result;
}
catch (Exception ex)
@@ -0,0 +1,37 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Umbraco.Core;
using Umbraco.Core.Logging;
namespace UmbracoExamine.DataServices
{
public class UmbracoMemberContentService : UmbracoContentService
{
public override IEnumerable<string> GetAllUserPropertyNames()
{
using (var scope = ApplicationContext.Current.ScopeProvider.CreateScope())
{
try
{
//only return the property type aliases for members
var result = ApplicationContext.DatabaseContext.Database.Fetch<string>(
@"select distinct cmsPropertyType.alias from cmsPropertyType
inner join cmsContentType on cmsContentType.nodeId = cmsPropertyType.contentTypeId
inner join umbracoNode on umbracoNode.id = cmsContentType.nodeId
where umbracoNode.nodeObjectType = @nodeObjectType
order by alias", new {nodeObjectType = Constants.ObjectTypes.MemberType});
scope.Complete();
return result;
}
catch (Exception ex)
{
LogHelper.Error<UmbracoMemberContentService>("EXCEPTION OCCURRED reading GetAllUserPropertyNames", ex);
return Enumerable.Empty<string>();
}
}
}
}
}
@@ -0,0 +1,10 @@
namespace UmbracoExamine.DataServices
{
public class UmbracoMemberDataService : UmbracoDataService
{
public UmbracoMemberDataService()
{
ContentService = new UmbracoMemberContentService();
}
}
}
@@ -0,0 +1,26 @@
using System.IO;
using Examine;
using Examine.LuceneEngine;
using Lucene.Net.Store;
namespace UmbracoExamine
{
/// <summary>
/// A custom <see cref="SimpleFSLockFactory"/> that ensures a prefixless lock prefix
/// </summary>
/// <remarks>
/// This is a work around for the Lucene APIs. By default Lucene will use a null prefix however when we set a custom
/// lock factory the null prefix is overwritten.
/// </remarks>
public class NoPrefixSimpleFsLockFactory : SimpleFSLockFactory
{
public NoPrefixSimpleFsLockFactory(DirectoryInfo lockDir) : base(lockDir)
{
}
public override void SetLockPrefix(string lockPrefix)
{
base.SetLockPrefix(null);
}
}
}
+7 -3
View File
@@ -410,7 +410,11 @@ namespace UmbracoExamine
{
if (SupportedTypes.Contains(type) == false)
return;
//if the app is shutting down do not continue
if (IsCancellationRequested)
return;
var pageIndex = 0;
DataService.LogService.AddInfoLog(-1, string.Format("PerformIndexAll - Start data queries - {0}", type));
@@ -530,7 +534,7 @@ namespace UmbracoExamine
content, notPublished).WhereNotNull(), type);
pageIndex++;
} while (currentPageSize == PageSize);
} while (currentPageSize == PageSize && IsCancellationRequested == false); //do not continue if app is shutting down
}
break;
@@ -628,7 +632,7 @@ namespace UmbracoExamine
AddNodesToIndex(xElements, type);
pageIndex++;
} while (more);
} while (more && IsCancellationRequested == false); //don't continue if the app is shutting down
}
internal static IEnumerable<XElement> GetSerializedContent(
+5 -3
View File
@@ -82,15 +82,14 @@
<AssemblyOriginatorKeyFile>..\Solution Items\TheFARM-Public.snk</AssemblyOriginatorKeyFile>
</PropertyGroup>
<ItemGroup>
<Reference Include="Examine, Version=0.1.88.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\Examine.0.1.88\lib\net45\Examine.dll</HintPath>
<Reference Include="Examine, Version=0.1.89.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\Examine.0.1.89-beta05\lib\net45\Examine.dll</HintPath>
</Reference>
<Reference Include="ICSharpCode.SharpZipLib, Version=0.86.0.518, Culture=neutral, PublicKeyToken=1b03e6acf1164f73, processorArchitecture=MSIL">
<HintPath>..\packages\SharpZipLib.0.86.0\lib\20\ICSharpCode.SharpZipLib.dll</HintPath>
</Reference>
<Reference Include="Lucene.Net, Version=2.9.4.1, Culture=neutral, PublicKeyToken=85089178b9ac3181, processorArchitecture=MSIL">
<HintPath>..\packages\Lucene.Net.2.9.4.1\lib\net40\Lucene.Net.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="Microsoft.CSharp" />
<Reference Include="System" />
@@ -118,6 +117,8 @@
<Compile Include="DataServices\UmbracoDataService.cs" />
<Compile Include="DataServices\UmbracoContentService.cs" />
<Compile Include="DataServices\UmbracoMediaService.cs" />
<Compile Include="DataServices\UmbracoMemberContentService.cs" />
<Compile Include="DataServices\UmbracoMemberDataService.cs" />
<Compile Include="DeletePolicyTracker.cs" />
<Compile Include="ExamineHelper.cs" />
<Compile Include="IndexTypes.cs" />
@@ -133,6 +134,7 @@
<Compile Include="LocalStorage\MultiIndexLockFactory.cs" />
<Compile Include="LocalStorage\MultiIndexOutput.cs" />
<Compile Include="LoggingLevel.cs" />
<Compile Include="NoPrefixSimpleFsLockFactory.cs" />
<Compile Include="StaticField.cs" />
<Compile Include="StaticFieldCollection.cs" />
<Compile Include="UmbracoMemberIndexer.cs" />
+26 -27
View File
@@ -19,6 +19,8 @@ using Lucene.Net.Analysis;
namespace UmbracoExamine
{
/// <summary>
/// Custom indexer for members
/// </summary>
@@ -101,6 +103,11 @@ namespace UmbracoExamine
_memberTypeService = memberTypeService;
}
protected override IDataService CreateDefaultUmbracoDataService()
{
return new UmbracoMemberDataService();
}
/// <summary>
/// Ensures that the'_searchEmail' is added to the user fields so that it is indexed - without having to modify the config
/// </summary>
@@ -108,34 +115,26 @@ namespace UmbracoExamine
/// <returns></returns>
protected override IIndexCriteria GetIndexerData(IndexSet indexSet)
{
var indexerData = base.GetIndexerData(indexSet);
if (CanInitialize())
{
//If the fields are missing a custom _searchEmail, then add it
if (indexerData.UserFields.Any(x => x.Name == "_searchEmail") == false)
//Add a custom _searchEmail to the index criteria no matter what is in config
var field = new IndexField { Name = "_searchEmail" };
StaticField policy;
if (IndexFieldPolicies.TryGetValue("_searchEmail", out policy))
{
var field = new IndexField { Name = "_searchEmail" };
StaticField policy;
if (IndexFieldPolicies.TryGetValue("_searchEmail", out policy))
{
field.Type = policy.Type;
field.EnableSorting = policy.EnableSorting;
}
return new IndexCriteria(
indexerData.StandardFields,
indexerData.UserFields.Concat(new[] { field }),
indexerData.IncludeNodeTypes,
indexerData.ExcludeNodeTypes,
indexerData.ParentNodeId
);
field.Type = policy.Type;
field.EnableSorting = policy.EnableSorting;
}
}
return indexerData;
return indexSet.ToIndexCriteria(DataService, IndexFieldPolicies,
//add additional explicit fields
new []{field});
}
else
{
return base.GetIndexerData(indexSet);
}
}
/// <summary>
@@ -198,7 +197,7 @@ namespace UmbracoExamine
AddNodesToIndex(GetSerializedMembers(members), type);
pageIndex++;
} while (members.Length == pageSize);
} while (members.Length == pageSize && IsCancellationRequested == false); //don't continue if the app is shutting down
}
}
else
@@ -212,7 +211,7 @@ namespace UmbracoExamine
AddNodesToIndex(GetSerializedMembers(members), type);
pageIndex++;
} while (members.Length == pageSize);
} while (members.Length == pageSize && IsCancellationRequested == false); //don't continue if the app is shutting down
}
}
}
@@ -233,8 +232,8 @@ namespace UmbracoExamine
protected override XDocument GetXDocument(string xPath, string type)
{
throw new NotSupportedException();
}
}
/// <summary>
/// Add the special __key and _searchEmail fields
/// </summary>
+1 -1
View File
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="Examine" version="0.1.88" targetFramework="net45" />
<package id="Examine" version="0.1.89-beta05" targetFramework="net45" />
<package id="Lucene.Net" version="2.9.4.1" targetFramework="net45" />
<package id="SharpZipLib" version="0.86.0" targetFramework="net45" />
</packages>
+1 -1
View File
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="Examine" version="0.1.88" targetFramework="net45" />
<package id="Examine" version="0.1.89-beta05" targetFramework="net45" />
<package id="HtmlAgilityPack" version="1.4.9.5" targetFramework="net45" />
<package id="Lucene.Net" version="2.9.4.1" targetFramework="net45" />
<package id="Microsoft.AspNet.Mvc" version="5.2.3" targetFramework="net45" />
@@ -45,8 +45,8 @@
<Prefer32Bit>false</Prefer32Bit>
</PropertyGroup>
<ItemGroup>
<Reference Include="Examine, Version=0.1.88.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\Examine.0.1.88\lib\net45\Examine.dll</HintPath>
<Reference Include="Examine, Version=0.1.89.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\Examine.0.1.89-beta05\lib\net45\Examine.dll</HintPath>
</Reference>
<Reference Include="HtmlAgilityPack, Version=1.4.9.5, Culture=neutral, PublicKeyToken=bd319b19eaf3b43a, processorArchitecture=MSIL">
<HintPath>..\packages\HtmlAgilityPack.1.4.9.5\lib\Net45\HtmlAgilityPack.dll</HintPath>
@@ -57,7 +57,6 @@
</Reference>
<Reference Include="Lucene.Net, Version=2.9.4.1, Culture=neutral, PublicKeyToken=85089178b9ac3181, processorArchitecture=MSIL">
<HintPath>..\packages\Lucene.Net.2.9.4.1\lib\net40\Lucene.Net.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="Microsoft.Web.Infrastructure, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<HintPath>..\packages\Microsoft.Web.Infrastructure.1.0.0.0\lib\net40\Microsoft.Web.Infrastructure.dll</HintPath>
@@ -108,11 +108,9 @@
<ItemGroup>
<Reference Include="AutoMapper, Version=3.3.1.0, Culture=neutral, PublicKeyToken=be96cd2c38ef1005, processorArchitecture=MSIL">
<HintPath>..\packages\AutoMapper.3.3.1\lib\net40\AutoMapper.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="AutoMapper.Net4, Version=3.3.1.0, Culture=neutral, PublicKeyToken=be96cd2c38ef1005, processorArchitecture=MSIL">
<HintPath>..\packages\AutoMapper.3.3.1\lib\net40\AutoMapper.Net4.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="Microsoft.AspNet.Identity.Core, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<HintPath>..\packages\Microsoft.AspNet.Identity.Core.2.2.1\lib\net45\Microsoft.AspNet.Identity.Core.dll</HintPath>
@@ -122,11 +120,9 @@
</Reference>
<Reference Include="Microsoft.Web.Infrastructure, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<HintPath>..\packages\Microsoft.Web.Infrastructure.1.0.0.0\lib\net40\Microsoft.Web.Infrastructure.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="Owin, Version=1.0.0.0, Culture=neutral, PublicKeyToken=f0ebd12fd5e55cc5, processorArchitecture=MSIL">
<HintPath>..\packages\Owin.1.0\lib\net40\Owin.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="System" />
<Reference Include="System.configuration" />
@@ -145,27 +141,21 @@
</Reference>
<Reference Include="System.Web.Helpers, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<HintPath>..\packages\Microsoft.AspNet.WebPages.3.2.3\lib\net45\System.Web.Helpers.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="System.Web.Mvc, Version=5.2.3.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<HintPath>..\packages\Microsoft.AspNet.Mvc.5.2.3\lib\net45\System.Web.Mvc.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="System.Web.Razor, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<HintPath>..\packages\Microsoft.AspNet.Razor.3.2.3\lib\net45\System.Web.Razor.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="System.Web.WebPages, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<HintPath>..\packages\Microsoft.AspNet.WebPages.3.2.3\lib\net45\System.Web.WebPages.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="System.Web.WebPages.Deployment, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<HintPath>..\packages\Microsoft.AspNet.WebPages.3.2.3\lib\net45\System.Web.WebPages.Deployment.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="System.Web.WebPages.Razor, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<HintPath>..\packages\Microsoft.AspNet.WebPages.3.2.3\lib\net45\System.Web.WebPages.Razor.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="System.Xml">
<Name>System.XML</Name>
-3
View File
@@ -108,11 +108,9 @@
<ItemGroup>
<Reference Include="ClientDependency.Core, Version=1.9.2.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\ClientDependency.1.9.2\lib\net45\ClientDependency.Core.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="HtmlAgilityPack, Version=1.4.9.5, Culture=neutral, PublicKeyToken=bd319b19eaf3b43a, processorArchitecture=MSIL">
<HintPath>..\packages\HtmlAgilityPack.1.4.9.5\lib\Net45\HtmlAgilityPack.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="Microsoft.CSharp" />
<Reference Include="Newtonsoft.Json, Version=10.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
@@ -166,7 +164,6 @@
<Reference Include="System.Xml.Linq" />
<Reference Include="TidyNet, Version=1.0.0.0, Culture=neutral">
<HintPath>..\packages\Tidy.Net.1.0.0\lib\TidyNet.dll</HintPath>
<Private>True</Private>
</Reference>
</ItemGroup>
<ItemGroup>
@@ -70,7 +70,6 @@
<ItemGroup>
<Reference Include="ClientDependency.Core, Version=1.9.2.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\ClientDependency.1.9.2\lib\net45\ClientDependency.Core.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="System" />
<Reference Include="System.configuration" />
@@ -70,10 +70,10 @@
<ItemGroup>
<Reference Include="Microsoft.ApplicationBlocks.Data, Version=1.0.1559.20655, Culture=neutral">
<HintPath>..\packages\Microsoft.ApplicationBlocks.Data.1.0.1559.20655\lib\Microsoft.ApplicationBlocks.Data.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="MySql.Data, Version=6.9.9.0, Culture=neutral, PublicKeyToken=c5687fc88969c44d, processorArchitecture=MSIL">
<HintPath>..\packages\MySql.Data.6.9.9\lib\net45\MySql.Data.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="System" />
<Reference Include="System.Configuration" />
@@ -116,7 +116,6 @@
</ProjectReference>
<Reference Include="ClientDependency.Core, Version=1.9.2.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\ClientDependency.1.9.2\lib\net45\ClientDependency.Core.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="System">
<Name>System</Name>