propertyGroup = model.Groups.Single(x => x.Properties.Contains(prop));
if (model.Alias.ToLowerInvariant() == prop.Alias.ToLowerInvariant())
- yield return new ValidationResult(string.Format("With Models Builder enabled, you can't have a property with a the alias \"{0}\" when the content type alias is also \"{0}\".", prop.Alias), new[]
- {
- $"Groups[{model.Groups.IndexOf(propertyGroup)}].Properties[{propertyGroup.Properties.IndexOf(prop)}].Alias"
- });
+ {
+ string[] memberNames = new[]
+ {
+ $"Groups[{model.Groups.IndexOf(propertyGroup)}].Properties[{propertyGroup.Properties.IndexOf(prop)}].Alias"
+ };
- //we need to return the field name with an index so it's wired up correctly
+ yield return new ValidationResult(
+ string.Format("With Models Builder enabled, you can't have a property with a the alias \"{0}\" when the content type alias is also \"{0}\".", prop.Alias),
+ memberNames);
+ }
+
+ // we need to return the field name with an index so it's wired up correctly
var groupIndex = model.Groups.IndexOf(propertyGroup);
var propertyIndex = propertyGroup.Properties.IndexOf(prop);
- var validationResult = ValidateProperty(prop, groupIndex, propertyIndex);
+ ValidationResult validationResult = ValidateProperty(prop, groupIndex, propertyIndex);
if (validationResult != null)
+ {
yield return validationResult;
+ }
}
}
private ValidationResult ValidateProperty(PropertyTypeBasic property, int groupIndex, int propertyIndex)
{
- //don't let them match any properties or methods in IPublishedContent
- //TODO: There are probably more!
+ // don't let them match any properties or methods in IPublishedContent
+ // TODO: There are probably more!
var reservedProperties = typeof(IPublishedContent).GetProperties().Select(x => x.Name).ToArray();
var reservedMethods = typeof(IPublishedContent).GetMethods().Select(x => x.Name).ToArray();
var alias = property.Alias;
if (reservedProperties.InvariantContains(alias) || reservedMethods.InvariantContains(alias))
- return new ValidationResult(
- $"The alias {alias} is a reserved term and cannot be used", new[]
+ {
+ string[] memberNames = new[]
{
$"Groups[{groupIndex}].Properties[{propertyIndex}].Alias"
- });
+ };
+
+ return new ValidationResult(
+ $"The alias {alias} is a reserved term and cannot be used",
+ memberNames);
+ }
return null;
}
diff --git a/src/Umbraco.ModelsBuilder.Embedded/BackOffice/DashboardReport.cs b/src/Umbraco.ModelsBuilder.Embedded/BackOffice/DashboardReport.cs
index 6b413ad4a1..e03df097e8 100644
--- a/src/Umbraco.ModelsBuilder.Embedded/BackOffice/DashboardReport.cs
+++ b/src/Umbraco.ModelsBuilder.Embedded/BackOffice/DashboardReport.cs
@@ -27,38 +27,46 @@ namespace Umbraco.ModelsBuilder.Embedded.BackOffice
public string Text()
{
- if (!_config.Enable)
- return "Version: " + ApiVersion.Current.Version + "
ModelsBuilder is disabled
(the .Enable key is missing, or its value is not 'true').";
-
var sb = new StringBuilder();
- sb.Append("Version: ");
+ sb.Append("Version: ");
sb.Append(ApiVersion.Current.Version);
- sb.Append("
");
+ sb.Append("
");
- sb.Append("ModelsBuilder is enabled, with the following configuration:");
+ sb.Append("ModelsBuilder is enabled, with the following configuration:
");
sb.Append("");
- sb.Append("- The models factory is ");
+ sb.Append("
- The models mode is '");
+ sb.Append(_config.ModelsMode.ToString());
+ sb.Append("'. ");
- // TODO: Test this - if models factory is entirely disabled will umbraco work at all?
- // if not, is there a point to this?
- sb.Append(_config.EnableFactory || _config.ModelsMode == ModelsMode.PureLive
- ? "enabled"
- : "not enabled. Umbraco will not use models");
+ switch (_config.ModelsMode)
+ {
+ case ModelsMode.Nothing:
+ sb.Append("Strongly typed models are not generated. All content and cache will operate from instance of IPublishedContent only.");
+ break;
+ case ModelsMode.PureLive:
+ sb.Append("Strongly typed models are re-generated on startup and anytime schema changes (i.e. Content Type) are made. No recompilation necessary but the generated models are not available to code outside of Razor.");
+ break;
+ case ModelsMode.AppData:
+ sb.Append("Strongly typed models are generated on demand. Recompilation is necessary and models are available to all CSharp code.");
+ break;
+ case ModelsMode.LiveAppData:
+ sb.Append("Strong typed models are generated on demand and anytime schema changes (i.e. Content Type) are made. Recompilation is necessary and models are available to all CSharp code.");
+ break;
+ }
- sb.Append(".
");
+ sb.Append("");
- sb.Append(_config.ModelsMode != ModelsMode.Nothing
- ? $"- {_config.ModelsMode} models are enabled.
"
- : "- No models mode is specified: models will not be generated.
");
+ if (_config.ModelsMode != ModelsMode.Nothing)
+ {
+ sb.Append($"- Models namespace is {_config.ModelsNamespace}.
");
- sb.Append($"- Models namespace is {_config.ModelsNamespace}.
");
-
- sb.Append("- Tracking of out-of-date models is ");
- sb.Append(_config.FlagOutOfDateModels ? "enabled" : "not enabled");
- sb.Append(".
");
+ sb.Append("- Tracking of out-of-date models is ");
+ sb.Append(_config.FlagOutOfDateModels ? "enabled" : "not enabled");
+ sb.Append(".
");
+ }
sb.Append("
");
diff --git a/src/Umbraco.ModelsBuilder.Embedded/BackOffice/ModelsBuilderDashboardController.cs b/src/Umbraco.ModelsBuilder.Embedded/BackOffice/ModelsBuilderDashboardController.cs
index 0b67498f01..9c12e9b649 100644
--- a/src/Umbraco.ModelsBuilder.Embedded/BackOffice/ModelsBuilderDashboardController.cs
+++ b/src/Umbraco.ModelsBuilder.Embedded/BackOffice/ModelsBuilderDashboardController.cs
@@ -4,6 +4,7 @@ using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Options;
using Umbraco.Configuration;
+using Umbraco.Core.Configuration;
using Umbraco.Core.Configuration.Models;
using Umbraco.Core.Exceptions;
using Umbraco.Core.Hosting;
@@ -98,17 +99,14 @@ namespace Umbraco.ModelsBuilder.Embedded.BackOffice
return GetDashboardResult();
}
- private Dashboard GetDashboardResult()
+ private Dashboard GetDashboardResult() => new Dashboard
{
- return new Dashboard
- {
- Enable = _config.Enable,
- Text = _dashboardReport.Text(),
- CanGenerate = _dashboardReport.CanGenerate(),
- OutOfDateModels = _dashboardReport.AreModelsOutOfDate(),
- LastError = _dashboardReport.LastError(),
- };
- }
+ Mode = _config.ModelsMode,
+ Text = _dashboardReport.Text(),
+ CanGenerate = _dashboardReport.CanGenerate(),
+ OutOfDateModels = _dashboardReport.AreModelsOutOfDate(),
+ LastError = _dashboardReport.LastError(),
+ };
[DataContract]
public class BuildResult
@@ -122,8 +120,8 @@ namespace Umbraco.ModelsBuilder.Embedded.BackOffice
[DataContract]
public class Dashboard
{
- [DataMember(Name = "enable")]
- public bool Enable;
+ [DataMember(Name = "mode")]
+ public ModelsMode Mode;
[DataMember(Name = "text")]
public string Text;
[DataMember(Name = "canGenerate")]
diff --git a/src/Umbraco.ModelsBuilder.Embedded/DependencyInjection/UmbracoBuilderExtensions.cs b/src/Umbraco.ModelsBuilder.Embedded/DependencyInjection/UmbracoBuilderExtensions.cs
index 45ca4a9078..0c01dad0fb 100644
--- a/src/Umbraco.ModelsBuilder.Embedded/DependencyInjection/UmbracoBuilderExtensions.cs
+++ b/src/Umbraco.ModelsBuilder.Embedded/DependencyInjection/UmbracoBuilderExtensions.cs
@@ -105,7 +105,7 @@ namespace Umbraco.ModelsBuilder.Embedded.DependencyInjection
{
return factory.GetRequiredService();
}
- else if (config.EnableFactory)
+ else
{
TypeLoader typeLoader = factory.GetRequiredService();
IPublishedValueFallback publishedValueFallback = factory.GetRequiredService();
@@ -114,8 +114,6 @@ namespace Umbraco.ModelsBuilder.Embedded.DependencyInjection
.Concat(typeLoader.GetTypes()); // content models
return new PublishedModelFactory(types, publishedValueFallback);
}
-
- return null;
});
return builder;
diff --git a/src/Umbraco.ModelsBuilder.Embedded/LiveModelsProvider.cs b/src/Umbraco.ModelsBuilder.Embedded/LiveModelsProvider.cs
index d7fc051500..9ee4d96482 100644
--- a/src/Umbraco.ModelsBuilder.Embedded/LiveModelsProvider.cs
+++ b/src/Umbraco.ModelsBuilder.Embedded/LiveModelsProvider.cs
@@ -1,34 +1,31 @@
using System;
using System.Threading;
using Microsoft.AspNetCore.Http;
-using Microsoft.AspNetCore.Http.Extensions;
using Microsoft.Extensions.Logging;
-using Umbraco.Core.Configuration;
+using Microsoft.Extensions.Options;
using Umbraco.Configuration;
-using Umbraco.Core;
+using Umbraco.Core.Configuration.Models;
using Umbraco.Core.Hosting;
+using Umbraco.Extensions;
using Umbraco.ModelsBuilder.Embedded.Building;
using Umbraco.Web.Cache;
-using Umbraco.Core.Configuration.Models;
-using Microsoft.Extensions.Options;
-using Umbraco.Extensions;
namespace Umbraco.ModelsBuilder.Embedded
{
// supports LiveAppData - but not PureLive
public sealed class LiveModelsProvider
{
- private static Mutex _mutex;
- private static int _req;
+ private static Mutex s_mutex;
+ private static int s_req;
private readonly ILogger _logger;
private readonly ModelsBuilderSettings _config;
private readonly ModelsGenerator _modelGenerator;
private readonly ModelsGenerationError _mbErrors;
private readonly IHostingEnvironment _hostingEnvironment;
- // we do not manage pure live here
- internal bool IsEnabled => _config.ModelsMode.IsLiveNotPure();
-
+ ///
+ /// Initializes a new instance of the class.
+ ///
public LiveModelsProvider(ILogger logger, IOptions config, ModelsGenerator modelGenerator, ModelsGenerationError mbErrors, IHostingEnvironment hostingEnvironment)
{
_logger = logger;
@@ -38,18 +35,23 @@ namespace Umbraco.ModelsBuilder.Embedded
_hostingEnvironment = hostingEnvironment;
}
+ // we do not manage pure live here
+ internal bool IsEnabled => _config.ModelsMode.IsLiveNotPure();
+
internal void Install()
{
// just be sure
if (!IsEnabled)
+ {
return;
+ }
// initialize mutex
// ApplicationId will look like "/LM/W3SVC/1/Root/AppName"
// name is system-wide and must be less than 260 chars
var name = _hostingEnvironment.ApplicationId + "/UmbracoLiveModelsProvider";
- _mutex = new Mutex(false, name); //TODO: Replace this with MainDom? Seems we now have 2x implementations of almost the same thing
+ s_mutex = new Mutex(false, name); //TODO: Replace this with MainDom? Seems we now have 2x implementations of almost the same thing
// anything changes, and we want to re-generate models.
ContentTypeCacheRefresher.CacheUpdated += RequestModelsGeneration;
@@ -72,13 +74,13 @@ namespace Umbraco.ModelsBuilder.Embedded
{
//HttpContext.Current.Items[this] = true;
_logger.LogDebug("Requested to generate models.");
- Interlocked.Exchange(ref _req, 1);
+ Interlocked.Exchange(ref s_req, 1);
}
public void GenerateModelsIfRequested()
{
//if (HttpContext.Current.Items[this] == null) return;
- if (Interlocked.Exchange(ref _req, 0) == 0) return;
+ if (Interlocked.Exchange(ref s_req, 0) == 0) return;
// cannot use a simple lock here because we don't want another AppDomain
// to generate while we do... and there could be 2 AppDomains if the app restarts.
@@ -87,7 +89,7 @@ namespace Umbraco.ModelsBuilder.Embedded
{
_logger.LogDebug("Generate models...");
const int timeout = 2 * 60 * 1000; // 2 mins
- _mutex.WaitOne(timeout); // wait until it is safe, and acquire
+ s_mutex.WaitOne(timeout); // wait until it is safe, and acquire
_logger.LogInformation("Generate models now.");
GenerateModels();
_mbErrors.Clear();
@@ -104,7 +106,7 @@ namespace Umbraco.ModelsBuilder.Embedded
}
finally
{
- _mutex.ReleaseMutex(); // release
+ s_mutex.ReleaseMutex(); // release
}
}
diff --git a/src/Umbraco.ModelsBuilder.Embedded/ModelsBuilderNotificationHandler.cs b/src/Umbraco.ModelsBuilder.Embedded/ModelsBuilderNotificationHandler.cs
index 2e969eae17..002ff67a4b 100644
--- a/src/Umbraco.ModelsBuilder.Embedded/ModelsBuilderNotificationHandler.cs
+++ b/src/Umbraco.ModelsBuilder.Embedded/ModelsBuilderNotificationHandler.cs
@@ -6,6 +6,7 @@ using System.Threading.Tasks;
using Microsoft.AspNetCore.Routing;
using Microsoft.Extensions.Options;
using Umbraco.Configuration;
+using Umbraco.Core.Configuration;
using Umbraco.Core.Configuration.Models;
using Umbraco.Core.Events;
using Umbraco.Core.IO;
@@ -65,7 +66,7 @@ namespace Umbraco.ModelsBuilder.Embedded
_modelBinder.ModelBindingException += ContentModelBinder_ModelBindingException;
- if (_config.Enable)
+ if (_config.ModelsMode != ModelsMode.Nothing)
{
FileService.SavingTemplate += FileService_SavingTemplate;
}
@@ -126,7 +127,7 @@ namespace Umbraco.ModelsBuilder.Embedded
{
var settings = new Dictionary
{
- {"enabled", _config.Enable}
+ {"mode", _config.ModelsMode.ToString()}
};
return settings;
@@ -138,13 +139,6 @@ namespace Umbraco.ModelsBuilder.Embedded
///
private void FileService_SavingTemplate(IFileService sender, SaveEventArgs e)
{
- // don't do anything if the factory is not enabled
- // because, no factory = no models (even if generation is enabled)
- if (!_config.EnableFactory)
- {
- return;
- }
-
// don't do anything if this special key is not found
if (!e.AdditionalData.ContainsKey("CreateTemplateForContentType"))
{
diff --git a/src/Umbraco.ModelsBuilder.Embedded/PureLiveModelFactory.cs b/src/Umbraco.ModelsBuilder.Embedded/PureLiveModelFactory.cs
index 3bb9660dcf..4e209cfb28 100644
--- a/src/Umbraco.ModelsBuilder.Embedded/PureLiveModelFactory.cs
+++ b/src/Umbraco.ModelsBuilder.Embedded/PureLiveModelFactory.cs
@@ -132,7 +132,7 @@ namespace Umbraco.ModelsBuilder.Embedded
}
///
- public bool Enabled => _config.Enable;
+ public bool Enabled => _config.ModelsMode == ModelsMode.PureLive;
///
/// Handle the event when a reference cannot be resolved from the default context and return our custom MB assembly reference if we have one
diff --git a/src/Umbraco.Web.Common/Filters/ModelBindingExceptionAttribute.cs b/src/Umbraco.Web.Common/Filters/ModelBindingExceptionAttribute.cs
index 6e9d6d29a7..d22ac70d8d 100644
--- a/src/Umbraco.Web.Common/Filters/ModelBindingExceptionAttribute.cs
+++ b/src/Umbraco.Web.Common/Filters/ModelBindingExceptionAttribute.cs
@@ -45,7 +45,7 @@ namespace Umbraco.Web.Common.Filters
public void OnException(ExceptionContext filterContext)
{
var disabled = _exceptionFilterSettings?.Disabled ?? false;
- if (_publishedModelFactory.IsLiveFactory()
+ if (_publishedModelFactory.IsLiveFactoryEnabled()
&& !disabled
&& !filterContext.ExceptionHandled
&& (filterContext.Exception is ModelBindingException || filterContext.Exception is InvalidCastException)
diff --git a/src/Umbraco.Web.UI.Client/src/common/services/contenttypehelper.service.js b/src/Umbraco.Web.UI.Client/src/common/services/contenttypehelper.service.js
index 9cec15d519..eb401ebe5f 100644
--- a/src/Umbraco.Web.UI.Client/src/common/services/contenttypehelper.service.js
+++ b/src/Umbraco.Web.UI.Client/src/common/services/contenttypehelper.service.js
@@ -28,7 +28,7 @@ function contentTypeHelper(contentTypeResource, dataTypeResource, $filter, $inje
generateModels: function () {
var deferred = $q.defer();
var modelsResource = $injector.has("modelsBuilderManagementResource") ? $injector.get("modelsBuilderManagementResource") : null;
- var modelsBuilderEnabled = Umbraco.Sys.ServerVariables.umbracoPlugins.modelsBuilder.enabled;
+ var modelsBuilderEnabled = Umbraco.Sys.ServerVariables.umbracoPlugins.modelsBuilder.mode !== "Nothing";
if (modelsBuilderEnabled && modelsResource) {
modelsResource.buildModels().then(function (result) {
deferred.resolve(result);
@@ -49,7 +49,7 @@ function contentTypeHelper(contentTypeResource, dataTypeResource, $filter, $inje
checkModelsBuilderStatus: function () {
var deferred = $q.defer();
var modelsResource = $injector.has("modelsBuilderManagementResource") ? $injector.get("modelsBuilderManagementResource") : null;
- var modelsBuilderEnabled = (Umbraco && Umbraco.Sys && Umbraco.Sys.ServerVariables && Umbraco.Sys.ServerVariables.umbracoPlugins && Umbraco.Sys.ServerVariables.umbracoPlugins.modelsBuilder && Umbraco.Sys.ServerVariables.umbracoPlugins.modelsBuilder.enabled === true);
+ var modelsBuilderEnabled = (Umbraco && Umbraco.Sys && Umbraco.Sys.ServerVariables && Umbraco.Sys.ServerVariables.umbracoPlugins && Umbraco.Sys.ServerVariables.umbracoPlugins.modelsBuilder && Umbraco.Sys.ServerVariables.umbracoPlugins.modelsBuilder.mode !== "Nothing");
if (modelsBuilderEnabled && modelsResource) {
modelsResource.getModelsOutOfDateStatus().then(function (result) {