diff --git a/build/NuSpecs/UmbracoCms.Core.nuspec b/build/NuSpecs/UmbracoCms.Core.nuspec
index 7aab71e73a..19ecd8182e 100644
--- a/build/NuSpecs/UmbracoCms.Core.nuspec
+++ b/build/NuSpecs/UmbracoCms.Core.nuspec
@@ -15,44 +15,49 @@
en-US
umbraco
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/build/NuSpecs/UmbracoCms.nuspec b/build/NuSpecs/UmbracoCms.nuspec
index 1c306423b7..de5cf0e54f 100644
--- a/build/NuSpecs/UmbracoCms.nuspec
+++ b/build/NuSpecs/UmbracoCms.nuspec
@@ -16,7 +16,12 @@
umbraco
-
+
+
diff --git a/src/Umbraco.Core/Components/BootLoader.cs b/src/Umbraco.Core/Components/BootLoader.cs
index 0b2374a6bb..d292ff8d62 100644
--- a/src/Umbraco.Core/Components/BootLoader.cs
+++ b/src/Umbraco.Core/Components/BootLoader.cs
@@ -29,8 +29,7 @@ namespace Umbraco.Core.Components
/// The application container.
public BootLoader(IServiceContainer container)
{
- if (container == null) throw new ArgumentNullException(nameof(container));
- _container = container;
+ _container = container ?? throw new ArgumentNullException(nameof(container));
_proflog = container.GetInstance();
_logger = container.GetInstance();
}
@@ -176,8 +175,7 @@ namespace Umbraco.Core.Components
foreach (var attr in componentType.GetCustomAttributes())
{
var type = attr.EnabledType ?? componentType;
- EnableInfo enableInfo;
- if (enabled.TryGetValue(type, out enableInfo) == false) enableInfo = enabled[type] = new EnableInfo();
+ if (enabled.TryGetValue(type, out var enableInfo) == false) enableInfo = enabled[type] = new EnableInfo();
var weight = type == componentType ? 1 : 2;
if (enableInfo.Weight > weight) continue;
@@ -188,8 +186,7 @@ namespace Umbraco.Core.Components
{
var type = attr.DisabledType ?? componentType;
if (type == typeof(UmbracoCoreComponent)) throw new InvalidOperationException("Cannot disable UmbracoCoreComponent.");
- EnableInfo enableInfo;
- if (enabled.TryGetValue(type, out enableInfo) == false) enableInfo = enabled[type] = new EnableInfo();
+ if (enabled.TryGetValue(type, out var enableInfo) == false) enableInfo = enabled[type] = new EnableInfo();
var weight = type == componentType ? 1 : 2;
if (enableInfo.Weight > weight) continue;
diff --git a/src/Umbraco.Core/Events/CancellableObjectEventArgs.cs b/src/Umbraco.Core/Events/CancellableObjectEventArgs.cs
index 748ecb31ed..8c8362251a 100644
--- a/src/Umbraco.Core/Events/CancellableObjectEventArgs.cs
+++ b/src/Umbraco.Core/Events/CancellableObjectEventArgs.cs
@@ -97,14 +97,14 @@ namespace Umbraco.Core.Events
public bool Equals(CancellableObjectEventArgs other)
{
- if (ReferenceEquals(null, other)) return false;
+ if (other is null) return false;
if (ReferenceEquals(this, other)) return true;
return base.Equals(other) && EqualityComparer.Default.Equals(EventObject, other.EventObject);
}
public override bool Equals(object obj)
{
- if (ReferenceEquals(null, obj)) return false;
+ if (obj is null) return false;
if (ReferenceEquals(this, obj)) return true;
if (obj.GetType() != this.GetType()) return false;
return Equals((CancellableObjectEventArgs)obj);
@@ -154,7 +154,7 @@ namespace Umbraco.Core.Events
public bool Equals(CancellableEnumerableObjectEventArgs other)
{
- if (ReferenceEquals(null, other)) return false;
+ if (other is null) return false;
if (ReferenceEquals(this, other)) return true;
return EventObject.SequenceEqual(other.EventObject);
@@ -162,7 +162,7 @@ namespace Umbraco.Core.Events
public override bool Equals(object obj)
{
- if (ReferenceEquals(null, obj)) return false;
+ if (obj is null) return false;
if (ReferenceEquals(this, obj)) return true;
if (obj.GetType() != this.GetType()) return false;
return Equals((CancellableEnumerableObjectEventArgs)obj);
diff --git a/src/Umbraco.Core/Events/MoveEventArgs.cs b/src/Umbraco.Core/Events/MoveEventArgs.cs
index afc1f57111..9ae5840349 100644
--- a/src/Umbraco.Core/Events/MoveEventArgs.cs
+++ b/src/Umbraco.Core/Events/MoveEventArgs.cs
@@ -17,7 +17,7 @@ namespace Umbraco.Core.Events
/// A colleciton of MoveEventInfo objects that exposes all entities that have been moved during a single move operation
///
public MoveEventArgs(bool canCancel, EventMessages eventMessages, params MoveEventInfo[] moveInfo)
- : base(default(TEntity), canCancel, eventMessages)
+ : base(default, canCancel, eventMessages)
{
if (moveInfo.FirstOrDefault() == null)
{
@@ -27,7 +27,6 @@ namespace Umbraco.Core.Events
MoveInfoCollection = moveInfo;
//assign the legacy props
EventObject = moveInfo.First().Entity;
- ParentId = moveInfo.First().NewParentId;
}
///
@@ -38,7 +37,7 @@ namespace Umbraco.Core.Events
/// A colleciton of MoveEventInfo objects that exposes all entities that have been moved during a single move operation
///
public MoveEventArgs(EventMessages eventMessages, params MoveEventInfo[] moveInfo)
- : base(default(TEntity), eventMessages)
+ : base(default, eventMessages)
{
if (moveInfo.FirstOrDefault() == null)
{
@@ -48,7 +47,6 @@ namespace Umbraco.Core.Events
MoveInfoCollection = moveInfo;
//assign the legacy props
EventObject = moveInfo.First().Entity;
- ParentId = moveInfo.First().NewParentId;
}
///
@@ -59,7 +57,7 @@ namespace Umbraco.Core.Events
/// A colleciton of MoveEventInfo objects that exposes all entities that have been moved during a single move operation
///
public MoveEventArgs(bool canCancel, params MoveEventInfo[] moveInfo)
- : base(default(TEntity), canCancel)
+ : base(default, canCancel)
{
if (moveInfo.FirstOrDefault() == null)
{
@@ -69,7 +67,6 @@ namespace Umbraco.Core.Events
MoveInfoCollection = moveInfo;
//assign the legacy props
EventObject = moveInfo.First().Entity;
- ParentId = moveInfo.First().NewParentId;
}
///
@@ -79,7 +76,7 @@ namespace Umbraco.Core.Events
/// A colleciton of MoveEventInfo objects that exposes all entities that have been moved during a single move operation
///
public MoveEventArgs(params MoveEventInfo[] moveInfo)
- : base(default(TEntity))
+ : base(default)
{
if (moveInfo.FirstOrDefault() == null)
{
@@ -89,22 +86,17 @@ namespace Umbraco.Core.Events
MoveInfoCollection = moveInfo;
//assign the legacy props
EventObject = moveInfo.First().Entity;
- ParentId = moveInfo.First().NewParentId;
}
[Obsolete("Use the overload that specifies the MoveEventInfo object")]
public MoveEventArgs(TEntity eventObject, bool canCancel, int parentId)
: base(eventObject, canCancel)
- {
- ParentId = parentId;
- }
+ { }
[Obsolete("Use the overload that specifies the MoveEventInfo object")]
public MoveEventArgs(TEntity eventObject, int parentId)
: base(eventObject)
- {
- ParentId = parentId;
- }
+ { }
///
/// Gets all MoveEventInfo objects used to create the object
@@ -124,7 +116,6 @@ namespace Umbraco.Core.Events
//assign the legacy props
EventObject = first.Entity;
- ParentId = first.NewParentId;
}
}
@@ -137,22 +128,16 @@ namespace Umbraco.Core.Events
get { return EventObject; }
}
- ///
- /// Gets the Id of the object's new parent
- ///
- [Obsolete("Retrieve the ParentId from the MoveInfoCollection property instead")]
- public int ParentId { get; private set; }
-
public bool Equals(MoveEventArgs other)
{
- if (ReferenceEquals(null, other)) return false;
+ if (other is null) return false;
if (ReferenceEquals(this, other)) return true;
return base.Equals(other) && MoveInfoCollection.Equals(other.MoveInfoCollection);
}
public override bool Equals(object obj)
{
- if (ReferenceEquals(null, obj)) return false;
+ if (obj is null) return false;
if (ReferenceEquals(this, obj)) return true;
if (obj.GetType() != this.GetType()) return false;
return Equals((MoveEventArgs) obj);
diff --git a/src/Umbraco.Core/IO/MediaFileSystem.cs b/src/Umbraco.Core/IO/MediaFileSystem.cs
index 5534936a04..2c9773a9cb 100644
--- a/src/Umbraco.Core/IO/MediaFileSystem.cs
+++ b/src/Umbraco.Core/IO/MediaFileSystem.cs
@@ -115,6 +115,9 @@ namespace Umbraco.Core.IO
if (FileExists(file) == false) return;
DeleteFile(file);
+#pragma warning disable 162 // unreachable code
+ // Not implemented yet, so need to disable warnings
+ // ReSharper disable once ConditionIsAlwaysTrueOrFalse
if (UseTheNewMediaPathScheme == false)
{
// old scheme: filepath is "/" OR "-"
@@ -130,6 +133,7 @@ namespace Umbraco.Core.IO
var dir = Path.GetDirectoryName(file);
DeleteDirectory(dir, true);
}
+#pragma warning restore 162
}
catch (Exception e)
{
@@ -155,6 +159,9 @@ namespace Umbraco.Core.IO
filename = IOHelper.SafeFileName(filename.ToLowerInvariant());
string folder;
+#pragma warning disable 162 // unreachable code
+ // Not implemented yet, so need to disable warnings
+ // ReSharper disable once ConditionIsAlwaysTrueOrFalse
if (UseTheNewMediaPathScheme == false)
{
// old scheme: filepath is "/" OR "-"
@@ -169,6 +176,7 @@ namespace Umbraco.Core.IO
// for a single content cannot store two different files with the same name
folder = Combine(cuid, puid).ToHexString(/*'/', 2, 4*/); // could use ext to fragment path eg 12/e4/f2/...
}
+#pragma warning restore 162
var filepath = UmbracoConfig.For.UmbracoSettings().Content.UploadAllowDirectories
? Path.Combine(folder, filename).Replace('\\', '/')
@@ -213,9 +221,8 @@ namespace Umbraco.Core.IO
var sep = UmbracoConfig.For.UmbracoSettings().Content.UploadAllowDirectories ? "/" : "-";
var pos = prevpath.IndexOf(sep, StringComparison.Ordinal);
var s = pos > 0 ? prevpath.Substring(0, pos) : null;
- int ignored;
- var folder = (pos > 0 && int.TryParse(s, out ignored)) ? s : GetNextFolder();
+ var folder = (pos > 0 && int.TryParse(s, out _)) ? s : GetNextFolder();
// ReSharper disable once AssignNullToNotNullAttribute
var filepath = UmbracoConfig.For.UmbracoSettings().Content.UploadAllowDirectories
@@ -246,8 +253,7 @@ namespace Umbraco.Core.IO
var directories = GetDirectories("");
foreach (var directory in directories)
{
- long folderNumber;
- if (long.TryParse(directory, out folderNumber) && folderNumber > _folderCounter)
+ if (long.TryParse(directory, out var folderNumber) && folderNumber > _folderCounter)
_folderCounter = folderNumber;
}
diff --git a/src/Umbraco.Core/Logging/WebProfilerProvider.cs b/src/Umbraco.Core/Logging/WebProfilerProvider.cs
index 8fe657a01b..35ecd002c8 100644
--- a/src/Umbraco.Core/Logging/WebProfilerProvider.cs
+++ b/src/Umbraco.Core/Logging/WebProfilerProvider.cs
@@ -92,6 +92,7 @@ namespace Umbraco.Core.Logging
}
// obsolete but that's the one that's called ;-(
+ [Obsolete]
public override MiniProfiler Start(ProfileLevel level, string sessionName = null)
{
return Start(sessionName);
diff --git a/src/Umbraco.Core/Migrations/Install/DatabaseBuilder.cs b/src/Umbraco.Core/Migrations/Install/DatabaseBuilder.cs
index b7f1569e20..2ed5fda7af 100644
--- a/src/Umbraco.Core/Migrations/Install/DatabaseBuilder.cs
+++ b/src/Umbraco.Core/Migrations/Install/DatabaseBuilder.cs
@@ -134,7 +134,7 @@ namespace Umbraco.Core.Migrations.Install
{
SaveConnectionString(EmbeddedDatabaseConnectionString, Constants.DbProviderNames.SqlCe, logger);
- var path = Path.Combine(GlobalSettings.FullPathToRoot, "App_Data", "Umbraco.sdf");
+ var path = Path.Combine(IOHelper.GetRootDirectorySafe(), "App_Data", "Umbraco.sdf");
if (File.Exists(path) == false)
{
// this should probably be in a "using (new SqlCeEngine)" clause but not sure
@@ -173,8 +173,7 @@ namespace Umbraco.Core.Migrations.Install
/// The name the provider (Sql, Sql Azure, Sql Ce, MySql).
public void ConfigureDatabaseConnection(string server, string databaseName, string user, string password, string databaseProvider)
{
- string providerName;
- var connectionString = GetDatabaseConnectionString(server, databaseName, user, password, databaseProvider, out providerName);
+ var connectionString = GetDatabaseConnectionString(server, databaseName, user, password, databaseProvider, out var providerName);
SaveConnectionString(connectionString, providerName, _logger);
_databaseFactory.Configure(connectionString, providerName);
diff --git a/src/Umbraco.Core/Migrations/Upgrade/Upgrader.cs b/src/Umbraco.Core/Migrations/Upgrade/Upgrader.cs
index 7481444bd8..974ed7b4f8 100644
--- a/src/Umbraco.Core/Migrations/Upgrade/Upgrader.cs
+++ b/src/Umbraco.Core/Migrations/Upgrade/Upgrader.cs
@@ -60,7 +60,7 @@ namespace Umbraco.Core.Migrations.Upgrade
// save new state
if (forceState)
_keyValueService.SetValue(StateValueKey, state);
- else
+ else if (currentState != state)
_keyValueService.SetValue(StateValueKey, currentState, state);
// run post-migrations
diff --git a/src/Umbraco.Core/Migrations/Upgrade/V_7_5_0/RemoveStylesheetDataAndTablesAgain.cs b/src/Umbraco.Core/Migrations/Upgrade/V_7_5_0/RemoveStylesheetDataAndTablesAgain.cs
index 77fb24ddbc..d27ed11a21 100644
--- a/src/Umbraco.Core/Migrations/Upgrade/V_7_5_0/RemoveStylesheetDataAndTablesAgain.cs
+++ b/src/Umbraco.Core/Migrations/Upgrade/V_7_5_0/RemoveStylesheetDataAndTablesAgain.cs
@@ -1,4 +1,5 @@
-using System.Linq;
+using System;
+using System.Linq;
namespace Umbraco.Core.Migrations.Upgrade.V_7_5_0
{
@@ -14,19 +15,23 @@ namespace Umbraco.Core.Migrations.Upgrade.V_7_5_0
public override void Migrate()
{
+ // these have been obsoleted, need to copy the values here
+ var stylesheetPropertyObjectType = new Guid("5555da4f-a123-42b2-4488-dcdfb25e4111");
+ var stylesheetObjectType = new Guid("9F68DA4F-A3A8-44C2-8226-DCBD125E4840");
+
//Clear all stylesheet data if the tables exist
var tables = SqlSyntax.GetTablesInSchema(Context.Database).ToArray();
if (tables.InvariantContains("cmsStylesheetProperty"))
{
Delete.FromTable("cmsStylesheetProperty").AllRows().Do();
- Delete.FromTable("umbracoNode").Row(new { nodeObjectType = Constants.ObjectTypes.StylesheetProperty }).Do();
+ Delete.FromTable("umbracoNode").Row(new { nodeObjectType = stylesheetPropertyObjectType }).Do();
Delete.Table("cmsStylesheetProperty").Do();
}
if (tables.InvariantContains("cmsStylesheet"))
{
Delete.FromTable("cmsStylesheet").AllRows().Do();
- Delete.FromTable("umbracoNode").Row(new { nodeObjectType = Constants.ObjectTypes.Stylesheet }).Do();
+ Delete.FromTable("umbracoNode").Row(new { nodeObjectType = stylesheetObjectType }).Do();
Delete.Table("cmsStylesheet").Do();
}
diff --git a/src/Umbraco.Core/Models/PublishedContent/PublishedContentTypeFactory.cs b/src/Umbraco.Core/Models/PublishedContent/PublishedContentTypeFactory.cs
index a98dca4f29..3ba908b9bf 100644
--- a/src/Umbraco.Core/Models/PublishedContent/PublishedContentTypeFactory.cs
+++ b/src/Umbraco.Core/Models/PublishedContent/PublishedContentTypeFactory.cs
@@ -31,13 +31,13 @@ namespace Umbraco.Core.Models.PublishedContent
return new PublishedContentType(contentType, this);
}
- // for tests - fixme what's the point of the factory here?
+ // for tests
internal PublishedContentType CreateContentType(int id, string alias, IEnumerable propertyTypes, ContentVariation variations = ContentVariation.InvariantNeutral)
{
return new PublishedContentType(id, alias, PublishedItemType.Content, Enumerable.Empty(), propertyTypes, variations);
}
- // for tests - fixme what's the point of the factory here?
+ // for tests
internal PublishedContentType CreateContentType(int id, string alias, IEnumerable compositionAliases, IEnumerable propertyTypes, ContentVariation variations = ContentVariation.InvariantNeutral)
{
return new PublishedContentType(id, alias, PublishedItemType.Content, compositionAliases, propertyTypes, variations);
@@ -84,15 +84,6 @@ namespace Umbraco.Core.Models.PublishedContent
return dataType;
}
- ///
- public void NotifyDataTypeChanges()
- {
- lock (_publishedDataTypesLocker)
- {
- _publishedDataTypes = null;
- }
- }
-
///
public void NotifyDataTypeChanges(int[] ids)
{
diff --git a/src/Umbraco.Core/Packaging/PackageInstallation.cs b/src/Umbraco.Core/Packaging/PackageInstallation.cs
index 2e33bfbf2b..0d95a6096b 100644
--- a/src/Umbraco.Core/Packaging/PackageInstallation.cs
+++ b/src/Umbraco.Core/Packaging/PackageInstallation.cs
@@ -25,7 +25,7 @@ namespace Umbraco.Core.Packaging
public PackageInstallation(IPackagingService packagingService, IMacroService macroService,
IFileService fileService, IPackageExtraction packageExtraction)
- : this(packagingService, macroService, fileService, packageExtraction, GlobalSettings.FullPathToRoot)
+ : this(packagingService, macroService, fileService, packageExtraction, IOHelper.GetRootDirectorySafe())
{}
public PackageInstallation(IPackagingService packagingService, IMacroService macroService,
@@ -212,9 +212,8 @@ namespace Umbraco.Core.Packaging
private XDocument GetConfigXmlDoc(string packageFilePath)
{
- string filePathInPackage;
- string configXmlContent = _packageExtraction.ReadTextFileFromArchive(packageFilePath,
- Constants.Packaging.PackageXmlFileName, out filePathInPackage);
+ var configXmlContent = _packageExtraction.ReadTextFileFromArchive(packageFilePath,
+ Constants.Packaging.PackageXmlFileName, out _);
return XDocument.Parse(configXmlContent);
}
@@ -294,15 +293,13 @@ namespace Umbraco.Core.Packaging
};
- XAttribute attr = elemet.Attribute(Constants.Packaging.RunatNodeAttribute);
+ var attr = elemet.Attribute(Constants.Packaging.RunatNodeAttribute);
- ActionRunAt runAt;
- if (attr != null && Enum.TryParse(attr.Value, true, out runAt)) { packageAction.RunAt = runAt; }
+ if (attr != null && Enum.TryParse(attr.Value, true, out ActionRunAt runAt)) { packageAction.RunAt = runAt; }
attr = elemet.Attribute(Constants.Packaging.UndoNodeAttribute);
- bool undo;
- if (attr != null && bool.TryParse(attr.Value, out undo)) { packageAction.Undo = undo; }
+ if (attr != null && bool.TryParse(attr.Value, out var undo)) { packageAction.Undo = undo; }
return packageAction;
@@ -570,8 +567,7 @@ namespace Umbraco.Core.Packaging
private static int IntValue(XElement xElement, int defaultValue = 0)
{
- int val;
- return xElement == null ? defaultValue : int.TryParse(xElement.Value, out val) ? val : defaultValue;
+ return xElement == null ? defaultValue : int.TryParse(xElement.Value, out var val) ? val : defaultValue;
}
private static string UpdatePathPlaceholders(string path)
diff --git a/src/Umbraco.Core/Persistence/NPocoSqlExtensions.cs b/src/Umbraco.Core/Persistence/NPocoSqlExtensions.cs
index 178b68b4f8..9c1f0d9a07 100644
--- a/src/Umbraco.Core/Persistence/NPocoSqlExtensions.cs
+++ b/src/Umbraco.Core/Persistence/NPocoSqlExtensions.cs
@@ -916,6 +916,82 @@ namespace Umbraco.Core.Persistence
#endregion
+ #region Hints
+
+ ///
+ /// Appends the relevant ForUpdate hint.
+ ///
+ /// The Sql statement.
+ /// The Sql statement.
+ public static Sql ForUpdate(this Sql sql)
+ {
+ // MySql wants "FOR UPDATE" at the end, and T-Sql wants "WITH (UPDLOCK)" in the FROM statement,
+ // and we want to implement it in the least expensive way, so parsing the entire string here is
+ // a no, so we use reflection to work on the Sql expression before it is built.
+ // TODO propose a clean way to do that type of thing in NPoco
+
+ if (sql.SqlContext.DatabaseType.IsMySql())
+ {
+ sql.Append("FOR UPDATE");
+ return sql;
+ }
+
+ // go find the first FROM clause, and append the lock hint
+ Sql s = sql;
+ var updated = false;
+
+ while (s != null)
+ {
+ var sqlText = SqlInspector.GetSqlText(s);
+ if (sqlText.StartsWith("FROM ", StringComparison.OrdinalIgnoreCase))
+ {
+ SqlInspector.SetSqlText(s, sqlText + " WITH (UPDLOCK)");
+ updated = true;
+ break;
+ }
+
+ s = SqlInspector.GetSqlRhs(sql);
+ }
+
+ if (updated)
+ SqlInspector.Reset(sql);
+
+ return sql;
+ }
+
+ #endregion
+
+ #region Sql Inspection
+
+ private static SqlInspectionUtilities _sqlInspector;
+
+ private static SqlInspectionUtilities SqlInspector => _sqlInspector ?? (_sqlInspector = new SqlInspectionUtilities());
+
+ private class SqlInspectionUtilities
+ {
+ private readonly Func _getSqlText;
+ private readonly Action _setSqlText;
+ private readonly Func _getSqlRhs;
+ private readonly Action _setSqlFinal;
+
+ public SqlInspectionUtilities()
+ {
+ (_getSqlText, _setSqlText) = ReflectionUtilities.EmitFieldGetterAndSetter("_sql");
+ _getSqlRhs = ReflectionUtilities.EmitFieldGetter("_rhs");
+ _setSqlFinal = ReflectionUtilities.EmitFieldSetter("_sqlFinal");
+ }
+
+ public string GetSqlText(Sql sql) => _getSqlText(sql);
+
+ public void SetSqlText(Sql sql, string sqlText) => _setSqlText(sql, sqlText);
+
+ public Sql GetSqlRhs(Sql sql) => _getSqlRhs(sql);
+
+ public void Reset(Sql sql) => _setSqlFinal(sql, null);
+ }
+
+ #endregion
+
#region Utilities
private static string[] GetColumns(this Sql sql, string tableAlias = null, string referenceName = null, Expression>[] columnExpressions = null, bool withAlias = true)
diff --git a/src/Umbraco.Core/Persistence/Repositories/Implement/UserRepository.cs b/src/Umbraco.Core/Persistence/Repositories/Implement/UserRepository.cs
index 05fe456bbd..0ec5f9353b 100644
--- a/src/Umbraco.Core/Persistence/Repositories/Implement/UserRepository.cs
+++ b/src/Umbraco.Core/Persistence/Repositories/Implement/UserRepository.cs
@@ -191,7 +191,20 @@ ORDER BY colName";
public bool ValidateLoginSession(int userId, Guid sessionId)
{
- var found = Database.FirstOrDefault("WHERE sessionId=@sessionId", new {sessionId = sessionId});
+ // with RepeatableRead transaction mode, read-then-update operations can
+ // cause deadlocks, and the ForUpdate() hint is required to tell the database
+ // to acquire an exclusive lock when reading
+
+ // that query is going to run a *lot*, make it a template
+ var t = SqlContext.Templates.Get("Umbraco.Core.UserRepository.ValidateLoginSession", s => s
+ .Select()
+ .From()
+ .Where(x => x.SessionId == SqlTemplate.Arg("sessionId"))
+ .ForUpdate());
+
+ var sql = t.Sql(sessionId);
+
+ var found = Database.Query(sql).FirstOrDefault();
if (found == null || found.UserId != userId || found.LoggedOutUtc.HasValue)
return false;
@@ -211,34 +224,21 @@ ORDER BY colName";
public int ClearLoginSessions(int userId)
{
- //TODO: I know this doesn't follow the normal repository conventions which would require us to crete a UserSessionRepository
- //and also business logic models for these objects but that's just so overkill for what we are doing
- //and now that everything is properly in a transaction (Scope) there doesn't seem to be much reason for using that anymore
- var count = Database.ExecuteScalar("SELECT COUNT(*) FROM umbracoUserLogin WHERE userId=@userId", new { userId = userId });
- Database.Execute("DELETE FROM umbracoUserLogin WHERE userId=@userId", new {userId = userId});
- return count;
+ return Database.Delete(Sql().Where(x => x.UserId == userId));
}
public int ClearLoginSessions(TimeSpan timespan)
{
- //TODO: I know this doesn't follow the normal repository conventions which would require us to crete a UserSessionRepository
- //and also business logic models for these objects but that's just so overkill for what we are doing
- //and now that everything is properly in a transaction (Scope) there doesn't seem to be much reason for using that anymore
-
var fromDate = DateTime.UtcNow - timespan;
-
- var count = Database.ExecuteScalar("SELECT COUNT(*) FROM umbracoUserLogin WHERE lastValidatedUtc=@fromDate", new { fromDate = fromDate });
- Database.Execute("DELETE FROM umbracoUserLogin WHERE lastValidatedUtc=@fromDate", new { fromDate = fromDate });
- return count;
+ return Database.Delete(Sql().Where(x => x.LastValidatedUtc < fromDate));
}
public void ClearLoginSession(Guid sessionId)
{
- //TODO: I know this doesn't follow the normal repository conventions which would require us to crete a UserSessionRepository
- //and also business logic models for these objects but that's just so overkill for what we are doing
- //and now that everything is properly in a transaction (Scope) there doesn't seem to be much reason for using that anymore
- Database.Execute("UPDATE umbracoUserLogin SET loggedOutUtc=@now WHERE sessionId=@sessionId",
- new { now = DateTime.UtcNow, sessionId = sessionId });
+ // fixme why is that one updating and not deleting?
+ Database.Execute(Sql()
+ .Update(u => u.Set(x => x.LoggedOutUtc, DateTime.UtcNow))
+ .Where(x => x.SessionId == sessionId));
}
protected override IEnumerable PerformGetAll(params int[] ids)
@@ -718,7 +718,7 @@ ORDER BY colName";
if (string.IsNullOrWhiteSpace(orderBy)) throw new ArgumentException("Value cannot be null or whitespace.", nameof(orderBy));
Sql filterSql = null;
- var customFilterWheres = filter != null ? filter.GetWhereClauses().ToArray() : null;
+ var customFilterWheres = filter?.GetWhereClauses().ToArray();
var hasCustomFilter = customFilterWheres != null && customFilterWheres.Length > 0;
if (hasCustomFilter
|| includeUserGroups != null && includeUserGroups.Length > 0
diff --git a/src/Umbraco.Core/Properties/AssemblyInfo.cs b/src/Umbraco.Core/Properties/AssemblyInfo.cs
index 5e411e681c..1391aaa9ed 100644
--- a/src/Umbraco.Core/Properties/AssemblyInfo.cs
+++ b/src/Umbraco.Core/Properties/AssemblyInfo.cs
@@ -34,7 +34,8 @@ using System.Runtime.InteropServices;
[assembly: InternalsVisibleTo("Umbraco.Forms.Web")]
// Umbraco Headless
-[assembly: InternalsVisibleTo("Umbraco.Headless")]
+[assembly: InternalsVisibleTo("Umbraco.Headless")]
-// v8
-[assembly: InternalsVisibleTo("Umbraco.Compat7")]
+// code analysis
+// IDE1006 is broken, wants _value syntax for consts, etc - and it's even confusing ppl at MS, kill it
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Style", "IDE1006:Naming Styles", Justification = "~_~")]
diff --git a/src/Umbraco.Core/ReflectionUtilities.cs b/src/Umbraco.Core/ReflectionUtilities.cs
index db0cde87db..3cca2b5b62 100644
--- a/src/Umbraco.Core/ReflectionUtilities.cs
+++ b/src/Umbraco.Core/ReflectionUtilities.cs
@@ -21,6 +21,96 @@ namespace Umbraco.Core
///
public static partial class ReflectionUtilities
{
+ #region Fields
+
+ ///
+ /// Emits a field getter.
+ ///
+ /// The declaring type.
+ /// The field type.
+ /// The name of the field.
+ /// A field getter function.
+ /// Occurs when is null or empty.
+ /// Occurs when the field does not exist.
+ /// Occurs when does not match the type of the field.
+ public static Func EmitFieldGetter(string fieldName)
+ {
+ var field = GetField(fieldName);
+ return EmitFieldGetter(field);
+ }
+
+ ///
+ /// Emits a field setter.
+ ///
+ /// The declaring type.
+ /// The field type.
+ /// The name of the field.
+ /// A field setter action.
+ /// Occurs when is null or empty.
+ /// Occurs when the field does not exist.
+ /// Occurs when does not match the type of the field.
+ public static Action EmitFieldSetter(string fieldName)
+ {
+ var field = GetField(fieldName);
+ return EmitFieldSetter(field);
+ }
+
+ ///
+ /// Emits a field getter and setter.
+ ///
+ /// The declaring type.
+ /// The field type.
+ /// The name of the field.
+ /// A field getter and setter functions.
+ /// Occurs when is null or empty.
+ /// Occurs when the field does not exist.
+ /// Occurs when does not match the type of the field.
+ public static (Func, Action) EmitFieldGetterAndSetter(string fieldName)
+ {
+ var field = GetField(fieldName);
+ return (EmitFieldGetter(field), EmitFieldSetter(field));
+ }
+
+ private static FieldInfo GetField(string fieldName)
+ {
+ if (string.IsNullOrWhiteSpace(fieldName)) throw new ArgumentNullOrEmptyException(nameof(fieldName));
+
+ // get the field
+ var field = typeof(TDeclaring).GetField(fieldName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
+ if (field == null) throw new InvalidOperationException($"Could not find field {typeof(TDeclaring)}.{fieldName}.");
+
+ // validate field type
+ if (field.FieldType != typeof(TValue)) // strict
+ throw new ArgumentException($"Value type {typeof(TValue)} does not match field {typeof(TDeclaring)}.{fieldName} type {field.FieldType}.");
+
+ return field;
+ }
+
+ private static Func EmitFieldGetter(FieldInfo field)
+ {
+ // emit
+ var (dm, ilgen) = CreateIlGenerator(field.DeclaringType?.Module, new [] { typeof(TDeclaring) }, typeof(TValue));
+ ilgen.Emit(OpCodes.Ldarg_0);
+ ilgen.Emit(OpCodes.Ldfld, field);
+ ilgen.Return();
+
+ return (Func) (object) dm.CreateDelegate(typeof(Func));
+ }
+
+ private static Action EmitFieldSetter(FieldInfo field)
+ {
+ // emit
+ var (dm, ilgen) = CreateIlGenerator(field.DeclaringType?.Module, new [] { typeof(TDeclaring), typeof(TValue) }, typeof(void));
+ ilgen.Emit(OpCodes.Ldarg_0);
+ ilgen.Emit(OpCodes.Ldarg_1);
+ ilgen.Emit(OpCodes.Stfld, field);
+ ilgen.Return();
+
+ return (Action) (object) dm.CreateDelegate(typeof(Action));
+ }
+
+ #endregion
+
#region Properties
///
@@ -207,7 +297,7 @@ namespace Umbraco.Core
/// is specified and does not match the function's returned type.
public static TLambda EmitCtor(bool mustExist = true, Type declaring = null)
{
- (_, var lambdaParameters, var lambdaReturned) = AnalyzeLambda(true, true);
+ var (_, lambdaParameters, lambdaReturned) = AnalyzeLambda(true, true);
// determine returned / declaring type
if (declaring == null) declaring = lambdaReturned;
@@ -239,7 +329,7 @@ namespace Umbraco.Core
{
if (ctor == null) throw new ArgumentNullException(nameof(ctor));
- (_, var lambdaParameters, var lambdaReturned) = AnalyzeLambda(true, true);
+ var (_, lambdaParameters, lambdaReturned) = AnalyzeLambda(true, true);
return EmitCtorSafe(lambdaParameters, lambdaReturned, ctor);
}
@@ -281,7 +371,7 @@ namespace Umbraco.Core
{
if (ctor == null) throw new ArgumentNullException(nameof(ctor));
- (_, var lambdaParameters, var lambdaReturned) = AnalyzeLambda(true, true);
+ var (_, lambdaParameters, lambdaReturned) = AnalyzeLambda(true, true);
// emit - unsafe - use lambda's args and assume they are correct
return EmitCtor(lambdaReturned, lambdaParameters, ctor);
@@ -293,7 +383,7 @@ namespace Umbraco.Core
var ctorParameters = GetParameters(ctor);
// emit
- (var dm, var ilgen) = CreateIlGenerator(ctor.DeclaringType?.Module, lambdaParameters, declaring);
+ var (dm, ilgen) = CreateIlGenerator(ctor.DeclaringType?.Module, lambdaParameters, declaring);
EmitLdargs(ilgen, lambdaParameters, ctorParameters);
ilgen.Emit(OpCodes.Newobj, ctor); // ok to just return, it's only objects
ilgen.Return();
@@ -342,7 +432,7 @@ namespace Umbraco.Core
{
if (string.IsNullOrWhiteSpace(methodName)) throw new ArgumentNullOrEmptyException(nameof(methodName));
- (var lambdaDeclaring, var lambdaParameters, var lambdaReturned) = AnalyzeLambda(true, out var isFunction);
+ var (lambdaDeclaring, lambdaParameters, lambdaReturned) = AnalyzeLambda(true, out var isFunction);
// get the method infos
var method = declaring.GetMethod(methodName, BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Static, null, lambdaParameters, null);
@@ -374,7 +464,7 @@ namespace Umbraco.Core
var methodParameters = method.GetParameters().Select(x => x.ParameterType).ToArray();
var isStatic = method.IsStatic;
- (var lambdaDeclaring, var lambdaParameters, var lambdaReturned) = AnalyzeLambda(isStatic, out var isFunction);
+ var (lambdaDeclaring, lambdaParameters, lambdaReturned) = AnalyzeLambda(isStatic, out var isFunction);
// if not static, then the first lambda arg must be the method declaring type
if (!isStatic && (methodDeclaring == null || !methodDeclaring.IsAssignableFrom(lambdaDeclaring)))
@@ -408,7 +498,7 @@ namespace Umbraco.Core
if (method == null) throw new ArgumentNullException(nameof(method));
var isStatic = method.IsStatic;
- (var lambdaDeclaring, var lambdaParameters, var lambdaReturned) = AnalyzeLambda(isStatic, out _);
+ var (lambdaDeclaring, lambdaParameters, lambdaReturned) = AnalyzeLambda(isStatic, out _);
// emit - unsafe - use lambda's args and assume they are correct
return EmitMethod(lambdaDeclaring, lambdaReturned, lambdaParameters, method);
@@ -433,7 +523,7 @@ namespace Umbraco.Core
throw new ArgumentNullOrEmptyException(nameof(methodName));
// validate lambda type
- (var lambdaDeclaring, var lambdaParameters, var lambdaReturned) = AnalyzeLambda(false, out var isFunction);
+ var (lambdaDeclaring, lambdaParameters, lambdaReturned) = AnalyzeLambda(false, out var isFunction);
// get the method infos
var method = lambdaDeclaring.GetMethod(methodName, BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance, null, lambdaParameters, null);
@@ -464,7 +554,7 @@ namespace Umbraco.Core
var methodArgTypes = GetParameters(method, withDeclaring: !method.IsStatic);
// emit IL
- (var dm, var ilgen) = CreateIlGenerator(method.DeclaringType?.Module, parameters, lambdaReturned);
+ var (dm, ilgen) = CreateIlGenerator(method.DeclaringType?.Module, parameters, lambdaReturned);
EmitLdargs(ilgen, parameters, methodArgTypes);
ilgen.CallMethod(method);
EmitOutputAdapter(ilgen, lambdaReturned, method.ReturnType);
@@ -486,7 +576,7 @@ namespace Umbraco.Core
{
var typeLambda = typeof(TLambda);
- (var declaring, var parameters, var returned) = AnalyzeLambda(isStatic, out var maybeFunction);
+ var (declaring, parameters, returned) = AnalyzeLambda(isStatic, out var maybeFunction);
if (isFunction)
{
diff --git a/src/Umbraco.Core/Runtime/CoreRuntime.cs b/src/Umbraco.Core/Runtime/CoreRuntime.cs
index 35ac5aff86..a3652b3330 100644
--- a/src/Umbraco.Core/Runtime/CoreRuntime.cs
+++ b/src/Umbraco.Core/Runtime/CoreRuntime.cs
@@ -45,8 +45,8 @@ namespace Umbraco.Core.Runtime
public virtual void Boot(ServiceContainer container)
{
// some components may want to initialize with the UmbracoApplicationBase
- // well, they should not - we should not do this - however, Compat7 wants
- // it, so let's do it, but we should remove this eventually.
+ // well, they should not - we should not do this
+ // TODO remove this eventually.
container.RegisterInstance(_app);
Compose(container);
diff --git a/src/Umbraco.Core/Strings/CleanStringType.cs b/src/Umbraco.Core/Strings/CleanStringType.cs
index c8c99be869..7367aa8b4b 100644
--- a/src/Umbraco.Core/Strings/CleanStringType.cs
+++ b/src/Umbraco.Core/Strings/CleanStringType.cs
@@ -68,13 +68,10 @@ namespace Umbraco.Core.Strings
///
/// Flag mask for encoding.
///
- CodeMask = Unicode | Utf8 | Ascii | TryAscii,
-
- ///
- /// Unicode encoding.
- ///
- [Obsolete("Use .Utf8 instead.")]
- Unicode = 0x0100,
+ CodeMask = Utf8 | Ascii | TryAscii,
+
+ // Unicode encoding is obsolete, use Utf8
+ //Unicode = 0x0100,
///
/// Utf8 encoding.
diff --git a/src/Umbraco.Core/UmbracoApplicationBase.cs b/src/Umbraco.Core/UmbracoApplicationBase.cs
index 353879ec61..06847d0a5a 100644
--- a/src/Umbraco.Core/UmbracoApplicationBase.cs
+++ b/src/Umbraco.Core/UmbracoApplicationBase.cs
@@ -160,7 +160,10 @@ namespace Umbraco.Core
_runtime = null;
}
- Current.Reset(); // dispose the container and everything
+ // dispose the container and everything
+ // but first, capture the looger!
+ var logger = Current.Logger;
+ Current.Reset();
if (SystemUtilities.GetCurrentTrustLevel() != AspNetHostingPermissionLevel.Unrestricted) return;
@@ -183,12 +186,12 @@ namespace Umbraco.Core
var shutdownMsg = $"Application shutdown. Details: {HostingEnvironment.ShutdownReason}\r\n\r\n_shutDownMessage={shutDownMessage}\r\n\r\n_shutDownStack={shutDownStack}";
- Current.Logger.Info(shutdownMsg);
+ logger.Info(shutdownMsg);
}
catch (Exception)
{
//if for some reason that fails, then log the normal output
- Current.Logger.Info("Application shutdown. Reason: " + HostingEnvironment.ShutdownReason);
+ logger.Info("Application shutdown. Reason: " + HostingEnvironment.ShutdownReason);
}
}
diff --git a/src/Umbraco.Examine/Config/IndexSets.cs b/src/Umbraco.Examine/Config/IndexSets.cs
index 4aa90b99d7..c6ad1476c3 100644
--- a/src/Umbraco.Examine/Config/IndexSets.cs
+++ b/src/Umbraco.Examine/Config/IndexSets.cs
@@ -4,16 +4,11 @@ namespace Umbraco.Examine.Config
{
public sealed class IndexSets : ConfigurationSection
{
-
#region Singleton definition
- protected IndexSets() { }
- static IndexSets()
- {
- Instance = ConfigurationManager.GetSection(SectionName) as IndexSets;
+ private IndexSets() { }
- }
- public static IndexSets Instance { get; }
+ public static IndexSets Instance { get; } = ConfigurationManager.GetSection(SectionName) as IndexSets;
#endregion
@@ -23,4 +18,4 @@ namespace Umbraco.Examine.Config
[ConfigurationProperty("", IsDefaultCollection = true, IsRequired = true)]
public IndexSetCollection Sets => (IndexSetCollection)base[""];
}
-}
\ No newline at end of file
+}
diff --git a/src/Umbraco.Examine/Properties/AssemblyInfo.cs b/src/Umbraco.Examine/Properties/AssemblyInfo.cs
index c08fd23daf..6713111968 100644
--- a/src/Umbraco.Examine/Properties/AssemblyInfo.cs
+++ b/src/Umbraco.Examine/Properties/AssemblyInfo.cs
@@ -8,3 +8,7 @@ using System.Runtime.CompilerServices;
// Umbraco Cms
[assembly: InternalsVisibleTo("Umbraco.Tests")]
+
+// code analysis
+// IDE1006 is broken, wants _value syntax for consts, etc - and it's even confusing ppl at MS, kill it
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Style", "IDE1006:Naming Styles", Justification = "~_~")]
diff --git a/src/Umbraco.Examine/UmbracoContentIndexer.cs b/src/Umbraco.Examine/UmbracoContentIndexer.cs
index 487d238c25..bdbaf04a32 100644
--- a/src/Umbraco.Examine/UmbracoContentIndexer.cs
+++ b/src/Umbraco.Examine/UmbracoContentIndexer.cs
@@ -294,8 +294,7 @@ namespace Umbraco.Examine
do
{
- long total;
- var descendants = MediaService.GetPagedDescendants(mediaParentId, pageIndex, pageSize, out total);
+ var descendants = MediaService.GetPagedDescendants(mediaParentId, pageIndex, pageSize, out _);
//if specific types are declared we need to post filter them
//TODO: Update the service layer to join the cmsContentType table so we can query by content type too
diff --git a/src/Umbraco.ModelsBuilder/Api/ApiHelper.cs b/src/Umbraco.ModelsBuilder/Api/ApiHelper.cs
index 3d9f94bbd4..fa6492fe3f 100644
--- a/src/Umbraco.ModelsBuilder/Api/ApiHelper.cs
+++ b/src/Umbraco.ModelsBuilder/Api/ApiHelper.cs
@@ -5,13 +5,11 @@ using Umbraco.ModelsBuilder.Umbraco;
namespace Umbraco.ModelsBuilder.Api
{
- // internal to be used by Umbraco.ModelsBuilder.Api project
internal static class ApiHelper
{
- public static Dictionary GetModels(string modelsNamespace, IDictionary files)
+ public static Dictionary GetModels(UmbracoServices umbracoServices, string modelsNamespace, IDictionary files)
{
- var umbraco = ModelsBuilderComponent.Umbraco;
- var typeModels = umbraco.GetAllTypes();
+ var typeModels = umbracoServices.GetAllTypes();
var parseResult = new CodeParser().ParseWithReferencedAssemblies(files);
var builder = new TextBuilder(typeModels, parseResult, modelsNamespace);
diff --git a/src/Umbraco.ModelsBuilder/Api/ModelsBuilderApiController.cs b/src/Umbraco.ModelsBuilder/Api/ModelsBuilderApiController.cs
index d74006c50f..444910b069 100644
--- a/src/Umbraco.ModelsBuilder/Api/ModelsBuilderApiController.cs
+++ b/src/Umbraco.ModelsBuilder/Api/ModelsBuilderApiController.cs
@@ -1,16 +1,12 @@
using System;
-using System.Collections.Generic;
using System.Net;
using System.Net.Http;
-using System.Text;
using Umbraco.Core;
using Umbraco.Core.Configuration;
-using Umbraco.ModelsBuilder.Building;
using Umbraco.ModelsBuilder.Configuration;
+using Umbraco.ModelsBuilder.Umbraco;
using Umbraco.Web.Mvc;
using Umbraco.Web.WebApi;
-using Umbraco.Web.WebApi.Filters;
-using Constants = Umbraco.Core.Constants;
namespace Umbraco.ModelsBuilder.Api
{
@@ -28,6 +24,13 @@ namespace Umbraco.ModelsBuilder.Api
{
public const string ControllerArea = "ModelsBuilder";
+ private readonly UmbracoServices _umbracoServices;
+
+ public ModelsBuilderApiController(UmbracoServices umbracoServices)
+ {
+ _umbracoServices = umbracoServices;
+ }
+
// invoked by the API
[System.Web.Http.HttpPost] // use the http one, not mvc, with api controllers!
[ApiBasicAuthFilter("developer")] // have to use our own, non-cookie-based, auth
@@ -60,7 +63,7 @@ namespace Umbraco.ModelsBuilder.Api
if (!checkResult.Success)
return checkResult.Result;
- var models = ApiHelper.GetModels(data.Namespace, data.Files);
+ var models = ApiHelper.GetModels(_umbracoServices, data.Namespace, data.Files);
return Request.CreateResponse(HttpStatusCode.OK, models, Configuration.Formatters.JsonFormatter);
}
diff --git a/src/Umbraco.ModelsBuilder/Properties/AssemblyInfo.cs b/src/Umbraco.ModelsBuilder/Properties/AssemblyInfo.cs
index a0a395a8a8..a2f8d1ae1e 100644
--- a/src/Umbraco.ModelsBuilder/Properties/AssemblyInfo.cs
+++ b/src/Umbraco.ModelsBuilder/Properties/AssemblyInfo.cs
@@ -8,3 +8,7 @@ using System.Runtime.InteropServices;
[assembly: ComVisible(false)]
[assembly: Guid("7020a059-c0d1-43a0-8efd-23591a0c9af6")]
+
+// code analysis
+// IDE1006 is broken, wants _value syntax for consts, etc - and it's even confusing ppl at MS, kill it
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Style", "IDE1006:Naming Styles", Justification = "~_~")]
diff --git a/src/Umbraco.ModelsBuilder/Umbraco.ModelsBuilder.csproj b/src/Umbraco.ModelsBuilder/Umbraco.ModelsBuilder.csproj
index 0279878b93..b9a5890d57 100644
--- a/src/Umbraco.ModelsBuilder/Umbraco.ModelsBuilder.csproj
+++ b/src/Umbraco.ModelsBuilder/Umbraco.ModelsBuilder.csproj
@@ -87,11 +87,10 @@
-
+
-
diff --git a/src/Umbraco.ModelsBuilder/Umbraco/LiveModelsProvider.cs b/src/Umbraco.ModelsBuilder/Umbraco/LiveModelsProvider.cs
index 1172fee59c..b6c37a3558 100644
--- a/src/Umbraco.ModelsBuilder/Umbraco/LiveModelsProvider.cs
+++ b/src/Umbraco.ModelsBuilder/Umbraco/LiveModelsProvider.cs
@@ -17,6 +17,7 @@ namespace Umbraco.ModelsBuilder.Umbraco
// supports LiveDll and LiveAppData - but not PureLive
public sealed class LiveModelsProvider
{
+ private static UmbracoServices _umbracoServices;
private static Mutex _mutex;
private static int _req;
@@ -30,12 +31,14 @@ namespace Umbraco.ModelsBuilder.Umbraco
}
}
- internal static void Install()
+ internal static void Install(UmbracoServices umbracoServices)
{
// just be sure
if (!IsEnabled)
return;
+ _umbracoServices = umbracoServices;
+
// initialize mutex
// ApplicationId will look like "/LM/W3SVC/1/Root/AppName"
// name is system-wide and must be less than 260 chars
@@ -110,11 +113,11 @@ namespace Umbraco.ModelsBuilder.Umbraco
var config = UmbracoConfig.For.ModelsBuilder();
// EnableDllModels will recycle the app domain - but this request will end properly
- ModelsBuilderBackOfficeController.GenerateModels(modelsDirectory, config.ModelsMode.IsAnyDll() ? bin : null);
+ ModelsBuilderBackOfficeController.GenerateModels(_umbracoServices, modelsDirectory, config.ModelsMode.IsAnyDll() ? bin : null);
}
}
- // have to do this because it's the only way to subscribe to EndRequest
+ // have to do this because it's the only way to subscribe to EndRequest,
// module is installed by assembly attribute at the top of this file
public class LiveModelsProviderModule : IHttpModule
{
diff --git a/src/Umbraco.ModelsBuilder/Umbraco/ModelsBuilderApplication.cs b/src/Umbraco.ModelsBuilder/Umbraco/ModelsBuilderApplication.cs
deleted file mode 100644
index bf650804c7..0000000000
--- a/src/Umbraco.ModelsBuilder/Umbraco/ModelsBuilderApplication.cs
+++ /dev/null
@@ -1,175 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Web;
-using System.Web.Mvc;
-using System.Web.Routing;
-using LightInject;
-using Umbraco.Core;
-using Umbraco.Core.Components;
-using Umbraco.Core.Composing;
-using Umbraco.Core.Configuration;
-using Umbraco.Core.IO;
-using Umbraco.Core.Models.PublishedContent;
-using Umbraco.Core.Services;
-using Umbraco.Core.Services.Implement;
-using Umbraco.ModelsBuilder.Configuration;
-using Umbraco.Web;
-using Umbraco.Web.UI.JavaScript;
-
-namespace Umbraco.ModelsBuilder.Umbraco
-{
- ///
- /// Installs ModelsBuilder into the Umbraco site.
- ///
- ///
- /// Don't bother installing at all, if not RuntimeLevel.Run.
- ///
- [RuntimeLevel(MinLevel = RuntimeLevel.Run)]
- public class ModelsBuilderApplication : UmbracoComponentBase, IUmbracoCoreComponent
- {
- private IRuntimeState _runtimeState;
-
- public override void Compose(Composition composition)
- {
- var config = UmbracoConfig.For.ModelsBuilder();
-
- if (config.ModelsMode == ModelsMode.PureLive)
- InstallLiveModels(composition.Container);
- else if (config.EnableFactory)
- InstallDefaultModelsFactory(composition.Container);
-
- // always setup the dashboard
- InstallServerVars();
- }
-
- public void Initialize(IRuntimeState runtimeState)
- {
- _runtimeState = runtimeState;
-
- var config = UmbracoConfig.For.ModelsBuilder();
-
- if (config.Enable)
- FileService.SavingTemplate += FileService_SavingTemplate;
-
- if (config.ModelsMode.IsLiveNotPure())
- LiveModelsProvider.Install();
-
- if (config.FlagOutOfDateModels)
- OutOfDateModelsStatus.Install();
- }
-
- private void InstallDefaultModelsFactory(IServiceContainer container)
- {
- var types = Current.TypeLoader.GetTypes();
- var factory = new PublishedModelFactory(types);
- container.RegisterSingleton(_ => factory);
- }
-
- private void InstallLiveModels(IServiceContainer container)
- {
- container.RegisterSingleton();
-
- // the following would add @using statement in every view so user's don't
- // have to do it - however, then noone understands where the @using statement
- // comes from, and it cannot be avoided / removed --- DISABLED
- //
- /*
- // no need for @using in views
- // note:
- // we are NOT using the in-code attribute here, config is required
- // because that would require parsing the code... and what if it changes?
- // we can AddGlobalImport not sure we can remove one anyways
- var modelsNamespace = Configuration.Config.ModelsNamespace;
- if (string.IsNullOrWhiteSpace(modelsNamespace))
- modelsNamespace = Configuration.Config.DefaultModelsNamespace;
- System.Web.WebPages.Razor.WebPageRazorHost.AddGlobalImport(modelsNamespace);
- */
- }
-
- private void InstallServerVars()
- {
- // register our url - for the backoffice api
- ServerVariablesParser.Parsing += (sender, serverVars) =>
- {
- if (!serverVars.ContainsKey("umbracoUrls"))
- throw new Exception("Missing umbracoUrls.");
- var umbracoUrlsObject = serverVars["umbracoUrls"];
- if (umbracoUrlsObject == null)
- throw new Exception("Null umbracoUrls");
- if (!(umbracoUrlsObject is Dictionary umbracoUrls))
- throw new Exception("Invalid umbracoUrls");
-
- if (!serverVars.ContainsKey("umbracoPlugins"))
- throw new Exception("Missing umbracoPlugins.");
- if (!(serverVars["umbracoPlugins"] is Dictionary umbracoPlugins))
- throw new Exception("Invalid umbracoPlugins");
-
- if (HttpContext.Current == null) throw new InvalidOperationException("HttpContext is null");
- var urlHelper = new UrlHelper(new RequestContext(new HttpContextWrapper(HttpContext.Current), new RouteData()));
-
- umbracoUrls["modelsBuilderBaseUrl"] = urlHelper.GetUmbracoApiServiceBaseUrl(controller => controller.BuildModels());
- umbracoPlugins["modelsBuilder"] = GetModelsBuilderSettings();
- };
- }
-
- private Dictionary GetModelsBuilderSettings()
- {
- if (_runtimeState.Level != RuntimeLevel.Run)
- return null;
-
- var settings = new Dictionary
- {
- {"enabled", UmbracoConfig.For.ModelsBuilder().Enable}
- };
-
- return settings;
- }
-
- ///
- /// Used to check if a template is being created based on a document type, in this case we need to
- /// ensure the template markup is correct based on the model name of the document type
- ///
- ///
- ///
- private void FileService_SavingTemplate(IFileService sender, Core.Events.SaveEventArgs e)
- {
- // don't do anything if the factory is not enabled
- // because, no factory = no models (even if generation is enabled)
- if (!UmbracoConfig.For.ModelsBuilder().EnableFactory) return;
-
- // don't do anything if this special key is not found
- if (!e.AdditionalData.ContainsKey("CreateTemplateForContentType")) return;
-
- // ensure we have the content type alias
- if (!e.AdditionalData.ContainsKey("ContentTypeAlias"))
- throw new InvalidOperationException("The additionalData key: ContentTypeAlias was not found");
-
- foreach (var template in e.SavedEntities)
- {
- // if it is in fact a new entity (not been saved yet) and the "CreateTemplateForContentType" key
- // is found, then it means a new template is being created based on the creation of a document type
- if (!template.HasIdentity && template.Content.IsNullOrWhiteSpace())
- {
- // ensure is safe and always pascal cased, per razor standard
- // + this is how we get the default model name in Umbraco.ModelsBuilder.Umbraco.Application
- var alias = e.AdditionalData["ContentTypeAlias"].ToString();
- var name = template.Name; // will be the name of the content type since we are creating
- var className = Application.GetClrName(name, alias);
-
- var modelNamespace = UmbracoConfig.For.ModelsBuilder().ModelsNamespace;
-
- // we do not support configuring this at the moment, so just let Umbraco use its default value
- //var modelNamespaceAlias = ...;
-
- var markup = ViewHelper.GetDefaultFileContent(
- modelClassName: className,
- modelNamespace: modelNamespace/*,
- modelNamespaceAlias: modelNamespaceAlias*/);
-
- //set the template content to the new markup
- template.Content = markup;
- }
- }
- }
- }
-}
diff --git a/src/Umbraco.ModelsBuilder/Umbraco/ModelsBuilderBackOfficeController.cs b/src/Umbraco.ModelsBuilder/Umbraco/ModelsBuilderBackOfficeController.cs
index 0a586fa16b..19c9bda5da 100644
--- a/src/Umbraco.ModelsBuilder/Umbraco/ModelsBuilderBackOfficeController.cs
+++ b/src/Umbraco.ModelsBuilder/Umbraco/ModelsBuilderBackOfficeController.cs
@@ -11,6 +11,7 @@ using Umbraco.ModelsBuilder.Building;
using Umbraco.ModelsBuilder.Configuration;
using Umbraco.ModelsBuilder.Dashboard;
using Umbraco.Web.Editors;
+using Umbraco.Web.WebApi.Filters;
namespace Umbraco.ModelsBuilder.Umbraco
{
@@ -22,8 +23,16 @@ namespace Umbraco.ModelsBuilder.Umbraco
/// correct CSRF security is adhered to for angular and it also ensures that this controller is not subseptipal to
/// global WebApi formatters being changed since this is always forced to only return Angular JSON Specific formats.
///
+ [UmbracoApplicationAuthorize(Core.Constants.Applications.Developer)]
public class ModelsBuilderBackOfficeController : UmbracoAuthorizedJsonController
{
+ private readonly UmbracoServices _umbracoServices;
+
+ public ModelsBuilderBackOfficeController(UmbracoServices umbracoServices)
+ {
+ _umbracoServices = umbracoServices;
+ }
+
// invoked by the dashboard
// requires that the user is logged into the backoffice and has access to the developer section
// beware! the name of the method appears in modelsbuilder.controller.js
@@ -93,7 +102,12 @@ namespace Umbraco.ModelsBuilder.Umbraco
};
}
- internal static void GenerateModels(string modelsDirectory, string bin)
+ private void GenerateModels(string modelsDirectory, string bin)
+ {
+ GenerateModels(_umbracoServices, modelsDirectory, bin);
+ }
+
+ internal static void GenerateModels(UmbracoServices umbracoServices, string modelsDirectory, string bin)
{
if (!Directory.Exists(modelsDirectory))
Directory.CreateDirectory(modelsDirectory);
@@ -101,8 +115,7 @@ namespace Umbraco.ModelsBuilder.Umbraco
foreach (var file in Directory.GetFiles(modelsDirectory, "*.generated.cs"))
File.Delete(file);
- var umbraco = ModelsBuilderComponent.Umbraco;
- var typeModels = umbraco.GetAllTypes();
+ var typeModels = umbracoServices.GetAllTypes();
var ourFiles = Directory.GetFiles(modelsDirectory, "*.cs").ToDictionary(x => x, File.ReadAllText);
var parseResult = new CodeParser().ParseWithReferencedAssemblies(ourFiles);
@@ -178,4 +191,4 @@ namespace Umbraco.ModelsBuilder.Umbraco
public OutOfDateType Status { get; set; }
}
}
-}
\ No newline at end of file
+}
diff --git a/src/Umbraco.ModelsBuilder/Umbraco/ModelsBuilderComponent.cs b/src/Umbraco.ModelsBuilder/Umbraco/ModelsBuilderComponent.cs
index ba75b59578..a581319ba5 100644
--- a/src/Umbraco.ModelsBuilder/Umbraco/ModelsBuilderComponent.cs
+++ b/src/Umbraco.ModelsBuilder/Umbraco/ModelsBuilderComponent.cs
@@ -12,6 +12,7 @@ using Umbraco.Core.IO;
using Umbraco.Core.Models.PublishedContent;
using Umbraco.Core.Services;
using Umbraco.Core.Services.Implement;
+using Umbraco.ModelsBuilder.Api;
using Umbraco.ModelsBuilder.Configuration;
using Umbraco.Web;
using Umbraco.Web.PublishedCache.NuCache;
@@ -19,59 +20,55 @@ using Umbraco.Web.UI.JavaScript;
namespace Umbraco.ModelsBuilder.Umbraco
{
- // fixme
- // nucache components wants models so we need to setup models before
- // however for some reason, this creates a cyclic dependency? => need better debugging info
- // cos nucache is Core so we need to be Core too
- // also... should have a generic "modelsbuilder" and "contentcache" components for dependencies!
-
[RequiredComponent(typeof(NuCacheComponent))]
+ [RuntimeLevel(MinLevel = RuntimeLevel.Run)]
public class ModelsBuilderComponent : UmbracoComponentBase, IUmbracoCoreComponent
{
public override void Compose(Composition composition)
{
base.Compose(composition);
- composition.Container.Register(new PerContainerLifetime());
+
+ composition.Container.Register(new PerContainerLifetime());
var config = UmbracoConfig.For.ModelsBuilder();
if (config.ModelsMode == ModelsMode.PureLive)
- InstallLiveModels(composition.Container);
+ ComposeForLiveModels(composition.Container);
else if (config.EnableFactory)
- InstallDefaultModelsFactory(composition.Container);
+ ComposeForDefaultModelsFactory(composition.Container);
// always setup the dashboard
InstallServerVars(composition.Container.GetInstance().Level);
+ composition.Container.Register(typeof(ModelsBuilderBackOfficeController), new PerRequestLifeTime());
- // need to do it here 'cos NuCache wants it during compose?
- Umbraco = composition.Container.GetInstance();
+ // setup the API if enabled (and in debug mode)
+ if (config.ApiServer)
+ composition.Container.Register(typeof(ModelsBuilderApiController), new PerRequestLifeTime());
}
- public void Initialize(Application application)
+ public void Initialize(UmbracoServices umbracoServices)
{
- Umbraco = application;
-
var config = UmbracoConfig.For.ModelsBuilder();
if (config.Enable)
FileService.SavingTemplate += FileService_SavingTemplate;
+ // fixme LiveModelsProvider should not be static
if (config.ModelsMode.IsLiveNotPure())
- LiveModelsProvider.Install();
+ LiveModelsProvider.Install(umbracoServices);
+ // fixme OutOfDateModelsStatus should not be static
if (config.FlagOutOfDateModels)
OutOfDateModelsStatus.Install();
}
- public static Application Umbraco { get; private set; }
-
- private void InstallDefaultModelsFactory(IServiceContainer container)
+ private void ComposeForDefaultModelsFactory(IServiceContainer container)
{
container.RegisterSingleton(factory
=> new PublishedModelFactory(factory.GetInstance().GetTypes()));
}
- private void InstallLiveModels(IServiceContainer container)
+ private void ComposeForLiveModels(IServiceContainer container)
{
container.RegisterSingleton();
@@ -102,14 +99,12 @@ namespace Umbraco.ModelsBuilder.Umbraco
var umbracoUrlsObject = serverVars["umbracoUrls"];
if (umbracoUrlsObject == null)
throw new Exception("Null umbracoUrls");
- var umbracoUrls = umbracoUrlsObject as Dictionary;
- if (umbracoUrls == null)
+ if (!(umbracoUrlsObject is Dictionary umbracoUrls))
throw new Exception("Invalid umbracoUrls");
if (!serverVars.ContainsKey("umbracoPlugins"))
throw new Exception("Missing umbracoPlugins.");
- var umbracoPlugins = serverVars["umbracoPlugins"] as Dictionary;
- if (umbracoPlugins == null)
+ if (!(serverVars["umbracoPlugins"] is Dictionary umbracoPlugins))
throw new Exception("Invalid umbracoPlugins");
if (HttpContext.Current == null) throw new InvalidOperationException("HttpContext is null");
@@ -162,7 +157,7 @@ namespace Umbraco.ModelsBuilder.Umbraco
// + this is how we get the default model name in Umbraco.ModelsBuilder.Umbraco.Application
var alias = e.AdditionalData["ContentTypeAlias"].ToString();
var name = template.Name; // will be the name of the content type since we are creating
- var className = Application.GetClrName(name, alias);
+ var className = UmbracoServices.GetClrName(name, alias);
var modelNamespace = UmbracoConfig.For.ModelsBuilder().ModelsNamespace;
@@ -180,4 +175,4 @@ namespace Umbraco.ModelsBuilder.Umbraco
}
}
}
-}
\ No newline at end of file
+}
diff --git a/src/Umbraco.ModelsBuilder/Umbraco/OutOfDateModelsStatus.cs b/src/Umbraco.ModelsBuilder/Umbraco/OutOfDateModelsStatus.cs
index a5f21f2b2a..a047f21edb 100644
--- a/src/Umbraco.ModelsBuilder/Umbraco/OutOfDateModelsStatus.cs
+++ b/src/Umbraco.ModelsBuilder/Umbraco/OutOfDateModelsStatus.cs
@@ -43,10 +43,7 @@ namespace Umbraco.ModelsBuilder.Umbraco
File.Delete(path);
}
- public static bool IsEnabled
- {
- get { return UmbracoConfig.For.ModelsBuilder().FlagOutOfDateModels; }
- }
+ public static bool IsEnabled => UmbracoConfig.For.ModelsBuilder().FlagOutOfDateModels;
public static bool IsOutOfDate
{
diff --git a/src/Umbraco.ModelsBuilder/Umbraco/PureLiveModelFactory.cs b/src/Umbraco.ModelsBuilder/Umbraco/PureLiveModelFactory.cs
index c216c92b03..9558c0140e 100644
--- a/src/Umbraco.ModelsBuilder/Umbraco/PureLiveModelFactory.cs
+++ b/src/Umbraco.ModelsBuilder/Umbraco/PureLiveModelFactory.cs
@@ -36,13 +36,16 @@ namespace Umbraco.ModelsBuilder.Umbraco
private int _ver, _skipver;
private readonly int _debugLevel;
private BuildManager _theBuildManager;
+ private readonly Lazy _umbracoServices;
+ private UmbracoServices UmbracoServices => _umbracoServices.Value;
private static readonly Regex AssemblyVersionRegex = new Regex("AssemblyVersion\\(\"[0-9]+.[0-9]+.[0-9]+.[0-9]+\"\\)", RegexOptions.Compiled);
private const string ProjVirt = "~/App_Data/Models/all.generated.cs";
private static readonly string[] OurFiles = { "models.hash", "models.generated.cs", "all.generated.cs", "all.dll.path", "models.err" };
- public PureLiveModelFactory(ProfilingLogger logger)
+ public PureLiveModelFactory(Lazy umbracoServices, ProfilingLogger logger)
{
+ _umbracoServices = umbracoServices;
_logger = logger;
_ver = 1; // zero is for when we had no version
_skipver = -1; // nothing to skip
@@ -161,8 +164,7 @@ namespace Umbraco.ModelsBuilder.Umbraco
if (_debugLevel > 0)
_logger.Logger.Debug("RazorBuildProvider.CodeGenerationStarted");
- var provider = sender as RazorBuildProvider;
- if (provider == null) return;
+ if (!(sender is RazorBuildProvider provider)) return;
// add the assembly, and add a dependency to a text file that will change on each
// compilation as in some environments (could not figure which/why) the BuildManager
@@ -309,8 +311,7 @@ namespace Umbraco.ModelsBuilder.Umbraco
.ToDictionary(x => x, File.ReadAllText)
: new Dictionary();
- var umbraco = ModelsBuilderComponent.Umbraco;
- var typeModels = umbraco.GetAllTypes();
+ var typeModels = UmbracoServices.GetAllTypes();
var currentHash = HashHelper.Hash(ourFiles, typeModels);
var modelsHashFile = Path.Combine(modelsDirectory, "models.hash");
var modelsSrcFile = Path.Combine(modelsDirectory, "models.generated.cs");
@@ -598,4 +599,4 @@ namespace Umbraco.ModelsBuilder.Umbraco
#endregion
}
-}
\ No newline at end of file
+}
diff --git a/src/Umbraco.ModelsBuilder/Umbraco/Application.cs b/src/Umbraco.ModelsBuilder/Umbraco/UmbracoServices.cs
similarity index 97%
rename from src/Umbraco.ModelsBuilder/Umbraco/Application.cs
rename to src/Umbraco.ModelsBuilder/Umbraco/UmbracoServices.cs
index df4549cc5c..f0347d9194 100644
--- a/src/Umbraco.ModelsBuilder/Umbraco/Application.cs
+++ b/src/Umbraco.ModelsBuilder/Umbraco/UmbracoServices.cs
@@ -12,14 +12,14 @@ using Umbraco.ModelsBuilder.Configuration;
namespace Umbraco.ModelsBuilder.Umbraco
{
- public class Application
+ public class UmbracoServices
{
private readonly IContentTypeService _contentTypeService;
private readonly IMediaTypeService _mediaTypeService;
private readonly IMemberTypeService _memberTypeService;
private readonly IPublishedContentTypeFactory _publishedContentTypeFactory;
- public Application(IContentTypeService contentTypeService, IMediaTypeService mediaTypeService, IMemberTypeService memberTypeService, IPublishedContentTypeFactory publishedContentTypeFactory)
+ public UmbracoServices(IContentTypeService contentTypeService, IMediaTypeService mediaTypeService, IMemberTypeService memberTypeService, IPublishedContentTypeFactory publishedContentTypeFactory)
{
_contentTypeService = contentTypeService;
_mediaTypeService = mediaTypeService;
diff --git a/src/Umbraco.Tests.Benchmarks/Umbraco.Tests.Benchmarks.csproj b/src/Umbraco.Tests.Benchmarks/Umbraco.Tests.Benchmarks.csproj
index 1ef1851ae1..19236e0163 100644
--- a/src/Umbraco.Tests.Benchmarks/Umbraco.Tests.Benchmarks.csproj
+++ b/src/Umbraco.Tests.Benchmarks/Umbraco.Tests.Benchmarks.csproj
@@ -14,9 +14,7 @@
-
+ false
AnyCPU
diff --git a/src/Umbraco.Tests.Benchmarks/app.config b/src/Umbraco.Tests.Benchmarks/app.config
index d9d475681a..d71468cbdb 100644
--- a/src/Umbraco.Tests.Benchmarks/app.config
+++ b/src/Umbraco.Tests.Benchmarks/app.config
@@ -11,11 +11,11 @@
-
+
-
+
@@ -275,11 +275,11 @@
-
+
-
+
diff --git a/src/Umbraco.Tests/App.config b/src/Umbraco.Tests/App.config
index 6339a1ced4..c197ee9bf7 100644
--- a/src/Umbraco.Tests/App.config
+++ b/src/Umbraco.Tests/App.config
@@ -113,11 +113,11 @@
-
+
-
+
@@ -157,11 +157,11 @@
-
+
-
+
diff --git a/src/Umbraco.Tests/Clr/ReflectionUtilitiesTests.cs b/src/Umbraco.Tests/Clr/ReflectionUtilitiesTests.cs
index 0b3d5235c8..31f936213d 100644
--- a/src/Umbraco.Tests/Clr/ReflectionUtilitiesTests.cs
+++ b/src/Umbraco.Tests/Clr/ReflectionUtilitiesTests.cs
@@ -528,6 +528,26 @@ namespace Umbraco.Tests.Clr
Assert.AreEqual(1, values5D["intValue2"]); // JsonProperty changes property name
}
+ [Test]
+ public void EmitFieldGetterSetterEmits()
+ {
+ var getter1 = ReflectionUtilities.EmitFieldGetter("Field1");
+ var getter2 = ReflectionUtilities.EmitFieldGetter("Field2");
+ var c = new Class1();
+ Assert.AreEqual(33, getter1(c));
+ Assert.AreEqual(66, getter2(c));
+
+ var setter2 = ReflectionUtilities.EmitFieldSetter("Field2");
+ setter2(c, 99);
+ Assert.AreEqual(99, getter2(c));
+
+ // works on readonly fields!
+ var (getter3, setter3) = ReflectionUtilities.EmitFieldGetterAndSetter("Field3");
+ Assert.AreEqual(22, getter3(c));
+ setter3(c, 44);
+ Assert.AreEqual(44, getter3(c));
+ }
+
// fixme - missing tests specifying 'returned' on method, property
#region IL Code
@@ -550,6 +570,12 @@ namespace Umbraco.Tests.Clr
// conv.i4
public void SetIntValue2(Class4 object4, object d) => object4.IntValue = (int) (double) d;
+ // get field
+ public int GetIntField(Class1 object1) => object1.Field1;
+
+ // set field
+ public void SetIntField(Class1 object1, int i) => object1.Field1 = i;
+
#endregion
#region Test Objects
@@ -583,6 +609,10 @@ namespace Umbraco.Tests.Clr
public int Value2 { set { } }
public int Value3 { get { return 42; } set { } }
private int ValueP1 => 42;
+
+ public int Field1 = 33;
+ private int Field2 = 66;
+ public readonly int Field3 = 22;
}
public class Class2 { }
diff --git a/src/Umbraco.Tests/Persistence/NPocoTests/NPocoSqlTests.cs b/src/Umbraco.Tests/Persistence/NPocoTests/NPocoSqlTests.cs
index a7b75cbd6d..6fa2af74cf 100644
--- a/src/Umbraco.Tests/Persistence/NPocoTests/NPocoSqlTests.cs
+++ b/src/Umbraco.Tests/Persistence/NPocoTests/NPocoSqlTests.cs
@@ -1,4 +1,5 @@
-using System.Diagnostics;
+using System;
+using System.Diagnostics;
using NUnit.Framework;
using Umbraco.Core;
using Umbraco.Core.Persistence;
@@ -293,5 +294,24 @@ namespace Umbraco.Tests.Persistence.NPocoTests
Debug.Print(sql.SQL);
}
+
+ [Test]
+ public void ForUpdate()
+ {
+ var sessionId = Guid.NewGuid();
+
+ var sql = Sql()
+ .SelectAll()
+ .From()
+ .Where(x => x.SessionId == sessionId);
+
+ sql.WriteToConsole();
+ Assert.AreEqual("SELECT * FROM [umbracoUserLogin] WHERE (([umbracoUserLogin].[sessionId] = @0))", sql.SQL.NoCrLf());
+
+ sql = sql.ForUpdate();
+
+ sql.WriteToConsole();
+ Assert.AreEqual("SELECT * FROM [umbracoUserLogin] WITH (UPDLOCK) WHERE (([umbracoUserLogin].[sessionId] = @0))", sql.SQL.NoCrLf());
+ }
}
}
diff --git a/src/Umbraco.Web/Properties/AssemblyInfo.cs b/src/Umbraco.Web/Properties/AssemblyInfo.cs
index 2e8c612aba..84ffe1e2f4 100644
--- a/src/Umbraco.Web/Properties/AssemblyInfo.cs
+++ b/src/Umbraco.Web/Properties/AssemblyInfo.cs
@@ -36,9 +36,6 @@ using System.Runtime.InteropServices;
// Umbraco Headless
[assembly: InternalsVisibleTo("Umbraco.Headless")]
-// v8
-[assembly: InternalsVisibleTo("Umbraco.Compat7")]
-
// code analysis
// IDE1006 is broken, wants _value syntax for consts, etc - and it's even confusing ppl at MS, kill it
[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Style", "IDE1006:Naming Styles", Justification = "~_~")]
diff --git a/src/Umbraco.Web/UmbracoModule.cs b/src/Umbraco.Web/UmbracoModule.cs
index 8c78ead696..d5fb8dee92 100644
--- a/src/Umbraco.Web/UmbracoModule.cs
+++ b/src/Umbraco.Web/UmbracoModule.cs
@@ -356,7 +356,7 @@ namespace Umbraco.Web
logger.Debug(() => $"Response status: Redirect={(pcr.IsRedirect ? (pcr.IsRedirectPermanent ? "permanent" : "redirect") : "none")}, Is404={(pcr.Is404 ? "true" : "false")}, StatusCode={pcr.ResponseStatusCode}");
- if(pcr.Cacheability != default(HttpCacheability))
+ if(pcr.Cacheability != default)
response.Cache.SetCacheability(pcr.Cacheability);
foreach (var cacheExtension in pcr.CacheExtensions)