diff --git a/src/Umbraco.Infrastructure/Umbraco.Infrastructure.csproj b/src/Umbraco.Infrastructure/Umbraco.Infrastructure.csproj
index f3b6e0973a..5361d6ae4b 100644
--- a/src/Umbraco.Infrastructure/Umbraco.Infrastructure.csproj
+++ b/src/Umbraco.Infrastructure/Umbraco.Infrastructure.csproj
@@ -102,8 +102,4 @@
-
-
-
-
diff --git a/src/Umbraco.ModelsBuilder.Embedded/DependencyInjection/UmbracoBuilderExtensions.cs b/src/Umbraco.ModelsBuilder.Embedded/DependencyInjection/UmbracoBuilderExtensions.cs
index f67a9e22c9..764ae9ab60 100644
--- a/src/Umbraco.ModelsBuilder.Embedded/DependencyInjection/UmbracoBuilderExtensions.cs
+++ b/src/Umbraco.ModelsBuilder.Embedded/DependencyInjection/UmbracoBuilderExtensions.cs
@@ -12,6 +12,7 @@ using Umbraco.Core.DependencyInjection;
using Umbraco.Core.Events;
using Umbraco.Core.Models.PublishedContent;
using Umbraco.ModelsBuilder.Embedded.Building;
+using Umbraco.Web.Common.ModelBinders;
using Umbraco.Web.WebAssets;
/*
@@ -91,6 +92,7 @@ namespace Umbraco.ModelsBuilder.Embedded.DependencyInjection
// would automatically just register for all implemented INotificationHandler{T}?
builder.AddNotificationHandler();
builder.AddNotificationHandler();
+ builder.AddNotificationHandler();
builder.AddNotificationHandler();
builder.AddNotificationHandler();
builder.AddNotificationHandler();
diff --git a/src/Umbraco.ModelsBuilder.Embedded/ModelsBuilderNotificationHandler.cs b/src/Umbraco.ModelsBuilder.Embedded/ModelsBuilderNotificationHandler.cs
index 9e11a9808d..db2a76abcb 100644
--- a/src/Umbraco.ModelsBuilder.Embedded/ModelsBuilderNotificationHandler.cs
+++ b/src/Umbraco.ModelsBuilder.Embedded/ModelsBuilderNotificationHandler.cs
@@ -22,24 +22,21 @@ namespace Umbraco.ModelsBuilder.Embedded
///
/// Handles and notifications to initialize MB
///
- internal class ModelsBuilderNotificationHandler : INotificationHandler, INotificationHandler
+ internal class ModelsBuilderNotificationHandler : INotificationHandler, INotificationHandler, INotificationHandler
{
private readonly ModelsBuilderSettings _config;
private readonly IShortStringHelper _shortStringHelper;
private readonly LinkGenerator _linkGenerator;
- private readonly ContentModelBinder _modelBinder;
public ModelsBuilderNotificationHandler(
IOptions config,
IShortStringHelper shortStringHelper,
- LinkGenerator linkGenerator,
- ContentModelBinder modelBinder)
+ LinkGenerator linkGenerator)
{
_config = config.Value;
_shortStringHelper = shortStringHelper;
_shortStringHelper = shortStringHelper;
_linkGenerator = linkGenerator;
- _modelBinder = modelBinder;
}
///
@@ -49,8 +46,6 @@ namespace Umbraco.ModelsBuilder.Embedded
{
// always setup the dashboard
// note: UmbracoApiController instances are automatically registered
- _modelBinder.ModelBindingException += ContentModelBinder_ModelBindingException;
-
if (_config.ModelsMode != ModelsMode.Nothing)
{
FileService.SavingTemplate += FileService_SavingTemplate;
@@ -149,10 +144,13 @@ namespace Umbraco.ModelsBuilder.Embedded
}
}
- private void ContentModelBinder_ModelBindingException(object sender, ContentModelBinder.ModelBindingArgs args)
+ ///
+ /// Handles when a model binding error occurs
+ ///
+ public void Handle(ModelBindingError notification)
{
- ModelsBuilderAssemblyAttribute sourceAttr = args.SourceType.Assembly.GetCustomAttribute();
- ModelsBuilderAssemblyAttribute modelAttr = args.ModelType.Assembly.GetCustomAttribute();
+ ModelsBuilderAssemblyAttribute sourceAttr = notification.SourceType.Assembly.GetCustomAttribute();
+ ModelsBuilderAssemblyAttribute modelAttr = notification.ModelType.Assembly.GetCustomAttribute();
// if source or model is not a ModelsBuider type...
if (sourceAttr == null || modelAttr == null)
@@ -164,11 +162,11 @@ namespace Umbraco.ModelsBuilder.Embedded
}
// else report, but better not restart (loops?)
- args.Message.Append(" The ");
- args.Message.Append(sourceAttr == null ? "view model" : "source");
- args.Message.Append(" is a ModelsBuilder type, but the ");
- args.Message.Append(sourceAttr != null ? "view model" : "source");
- args.Message.Append(" is not. The application is in an unstable state and should be restarted.");
+ notification.Message.Append(" The ");
+ notification.Message.Append(sourceAttr == null ? "view model" : "source");
+ notification.Message.Append(" is a ModelsBuilder type, but the ");
+ notification.Message.Append(sourceAttr != null ? "view model" : "source");
+ notification.Message.Append(" is not. The application is in an unstable state and should be restarted.");
return;
}
@@ -181,22 +179,22 @@ namespace Umbraco.ModelsBuilder.Embedded
if (pureSource == false || pureModel == false)
{
// only one is pure - report, but better not restart (loops?)
- args.Message.Append(pureSource
+ notification.Message.Append(pureSource
? " The content model is PureLive, but the view model is not."
: " The view model is PureLive, but the content model is not.");
- args.Message.Append(" The application is in an unstable state and should be restarted.");
+ notification.Message.Append(" The application is in an unstable state and should be restarted.");
}
else
{
// both are pure - report, and if different versions, restart
// if same version... makes no sense... and better not restart (loops?)
- var sourceVersion = args.SourceType.Assembly.GetName().Version;
- var modelVersion = args.ModelType.Assembly.GetName().Version;
- args.Message.Append(" Both view and content models are PureLive, with ");
- args.Message.Append(sourceVersion == modelVersion
+ var sourceVersion = notification.SourceType.Assembly.GetName().Version;
+ var modelVersion = notification.ModelType.Assembly.GetName().Version;
+ notification.Message.Append(" Both view and content models are PureLive, with ");
+ notification.Message.Append(sourceVersion == modelVersion
? "same version. The application is in an unstable state and should be restarted."
: "different versions. The application is in an unstable state and is going to be restarted.");
- args.Restart = sourceVersion != modelVersion;
+ notification.Restart = sourceVersion != modelVersion;
}
}
}
diff --git a/src/Umbraco.Tests.UnitTests/Umbraco.Web.Common/ModelBinders/ContentModelBinderTests.cs b/src/Umbraco.Tests.UnitTests/Umbraco.Web.Common/ModelBinders/ContentModelBinderTests.cs
index d62497b173..01b6032c36 100644
--- a/src/Umbraco.Tests.UnitTests/Umbraco.Web.Common/ModelBinders/ContentModelBinderTests.cs
+++ b/src/Umbraco.Tests.UnitTests/Umbraco.Web.Common/ModelBinders/ContentModelBinderTests.cs
@@ -11,6 +11,7 @@ using Microsoft.AspNetCore.Routing;
using Moq;
using NUnit.Framework;
using Umbraco.Core;
+using Umbraco.Core.Events;
using Umbraco.Core.Models.PublishedContent;
using Umbraco.Core.Services;
using Umbraco.Web.Common.ModelBinders;
@@ -26,7 +27,7 @@ namespace Umbraco.Tests.UnitTests.Umbraco.Web.Common.ModelBinders
private ContentModelBinder _contentModelBinder;
[SetUp]
- public void SetUp() => _contentModelBinder = new ContentModelBinder();
+ public void SetUp() => _contentModelBinder = new ContentModelBinder(Mock.Of());
[Test]
[TestCase(typeof(IPublishedContent), false)]
diff --git a/src/Umbraco.Tests.UnitTests/Umbraco.Web.Common/Views/UmbracoViewPageTests.cs b/src/Umbraco.Tests.UnitTests/Umbraco.Web.Common/Views/UmbracoViewPageTests.cs
index f6f7eaa2d5..b227d8a903 100644
--- a/src/Umbraco.Tests.UnitTests/Umbraco.Web.Common/Views/UmbracoViewPageTests.cs
+++ b/src/Umbraco.Tests.UnitTests/Umbraco.Web.Common/Views/UmbracoViewPageTests.cs
@@ -6,7 +6,9 @@ using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc.ModelBinding;
using Microsoft.AspNetCore.Mvc.Rendering;
using Microsoft.AspNetCore.Mvc.ViewFeatures;
+using Moq;
using NUnit.Framework;
+using Umbraco.Core.Events;
using Umbraco.Core.Models.PublishedContent;
using Umbraco.Web.Common.AspNetCore;
using Umbraco.Web.Common.ModelBinders;
@@ -311,7 +313,7 @@ namespace Umbraco.Tests.UnitTests.Umbraco.Web.Common.Views
public class TestPage : UmbracoViewPage
{
- private readonly ContentModelBinder _modelBinder = new ContentModelBinder();
+ private readonly ContentModelBinder _modelBinder = new ContentModelBinder(Mock.Of());
public override Task ExecuteAsync() => throw new NotImplementedException();
diff --git a/src/Umbraco.Web.Common/ModelBinders/ContentModelBinder.cs b/src/Umbraco.Web.Common/ModelBinders/ContentModelBinder.cs
index 47ca49f014..cc6678abfc 100644
--- a/src/Umbraco.Web.Common/ModelBinders/ContentModelBinder.cs
+++ b/src/Umbraco.Web.Common/ModelBinders/ContentModelBinder.cs
@@ -3,21 +3,25 @@ using System.Text;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc.ModelBinding;
using Umbraco.Core;
+using Umbraco.Core.Events;
using Umbraco.Core.Models.PublishedContent;
using Umbraco.Web.Common.Routing;
using Umbraco.Web.Models;
namespace Umbraco.Web.Common.ModelBinders
{
+
///
/// Maps view models, supporting mapping to and from any or .
///
public class ContentModelBinder : IModelBinder
{
+ private readonly IEventAggregator _eventAggregator;
+
///
- /// Occurs on model binding exceptions.
+ /// Initializes a new instance of the class.
///
- public event EventHandler ModelBindingException; // TODO: This cannot use IEventAggregator currently because it cannot be async
+ public ContentModelBinder(IEventAggregator eventAggregator) => _eventAggregator = eventAggregator;
///
public Task BindModelAsync(ModelBindingContext bindingContext)
@@ -156,47 +160,10 @@ namespace Umbraco.Web.Common.ModelBinders
// raise event, to give model factories a chance at reporting
// the error with more details, and optionally request that
// the application restarts.
- var args = new ModelBindingArgs(sourceType, modelType, msg);
- ModelBindingException?.Invoke(this, args);
+ var args = new ModelBindingError(sourceType, modelType, msg);
+ _eventAggregator.Publish(args);
throw new ModelBindingException(msg.ToString());
}
-
- ///
- /// Contains event data for the event.
- ///
- public class ModelBindingArgs : EventArgs
- {
- ///
- /// Initializes a new instance of the class.
- ///
- public ModelBindingArgs(Type sourceType, Type modelType, StringBuilder message)
- {
- SourceType = sourceType;
- ModelType = modelType;
- Message = message;
- }
-
- ///
- /// Gets the type of the source object.
- ///
- public Type SourceType { get; set; }
-
- ///
- /// Gets the type of the view model.
- ///
- public Type ModelType { get; set; }
-
- ///
- /// Gets the message string builder.
- ///
- /// Handlers of the event can append text to the message.
- public StringBuilder Message { get; }
-
- ///
- /// Gets or sets a value indicating whether the application should restart.
- ///
- public bool Restart { get; set; }
- }
}
}
diff --git a/src/Umbraco.Web.Common/ModelBinders/ModelBindingError.cs b/src/Umbraco.Web.Common/ModelBinders/ModelBindingError.cs
new file mode 100644
index 0000000000..3da698df5f
--- /dev/null
+++ b/src/Umbraco.Web.Common/ModelBinders/ModelBindingError.cs
@@ -0,0 +1,43 @@
+using System;
+using System.Text;
+using Umbraco.Core.Events;
+
+namespace Umbraco.Web.Common.ModelBinders
+{
+ ///
+ /// Contains event data for the event.
+ ///
+ public class ModelBindingError : INotification
+ {
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ public ModelBindingError(Type sourceType, Type modelType, StringBuilder message)
+ {
+ SourceType = sourceType;
+ ModelType = modelType;
+ Message = message;
+ }
+
+ ///
+ /// Gets the type of the source object.
+ ///
+ public Type SourceType { get; set; }
+
+ ///
+ /// Gets the type of the view model.
+ ///
+ public Type ModelType { get; set; }
+
+ ///
+ /// Gets the message string builder.
+ ///
+ /// Handlers of the event can append text to the message.
+ public StringBuilder Message { get; }
+
+ ///
+ /// Gets or sets a value indicating whether the application should restart.
+ ///
+ public bool Restart { get; set; }
+ }
+}