makes MB event an INotification
This commit is contained in:
@@ -102,8 +102,4 @@
|
||||
<ProjectReference Include="..\Umbraco.Core\Umbraco.Core.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Folder Include="Scheduling" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
||||
@@ -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<UmbracoApplicationStarting, ModelsBuilderNotificationHandler>();
|
||||
builder.AddNotificationHandler<ServerVariablesParsing, ModelsBuilderNotificationHandler>();
|
||||
builder.AddNotificationHandler<ModelBindingError, ModelsBuilderNotificationHandler>();
|
||||
builder.AddNotificationHandler<UmbracoApplicationStarting, LiveModelsProvider>();
|
||||
builder.AddNotificationHandler<UmbracoRequestEnd, LiveModelsProvider>();
|
||||
builder.AddNotificationHandler<UmbracoApplicationStarting, OutOfDateModelsStatus>();
|
||||
|
||||
@@ -22,24 +22,21 @@ namespace Umbraco.ModelsBuilder.Embedded
|
||||
/// <summary>
|
||||
/// Handles <see cref="UmbracoApplicationStarting"/> and <see cref="ServerVariablesParsing"/> notifications to initialize MB
|
||||
/// </summary>
|
||||
internal class ModelsBuilderNotificationHandler : INotificationHandler<UmbracoApplicationStarting>, INotificationHandler<ServerVariablesParsing>
|
||||
internal class ModelsBuilderNotificationHandler : INotificationHandler<UmbracoApplicationStarting>, INotificationHandler<ServerVariablesParsing>, INotificationHandler<ModelBindingError>
|
||||
{
|
||||
private readonly ModelsBuilderSettings _config;
|
||||
private readonly IShortStringHelper _shortStringHelper;
|
||||
private readonly LinkGenerator _linkGenerator;
|
||||
private readonly ContentModelBinder _modelBinder;
|
||||
|
||||
public ModelsBuilderNotificationHandler(
|
||||
IOptions<ModelsBuilderSettings> config,
|
||||
IShortStringHelper shortStringHelper,
|
||||
LinkGenerator linkGenerator,
|
||||
ContentModelBinder modelBinder)
|
||||
LinkGenerator linkGenerator)
|
||||
{
|
||||
_config = config.Value;
|
||||
_shortStringHelper = shortStringHelper;
|
||||
_shortStringHelper = shortStringHelper;
|
||||
_linkGenerator = linkGenerator;
|
||||
_modelBinder = modelBinder;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -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)
|
||||
/// <summary>
|
||||
/// Handles when a model binding error occurs
|
||||
/// </summary>
|
||||
public void Handle(ModelBindingError notification)
|
||||
{
|
||||
ModelsBuilderAssemblyAttribute sourceAttr = args.SourceType.Assembly.GetCustomAttribute<ModelsBuilderAssemblyAttribute>();
|
||||
ModelsBuilderAssemblyAttribute modelAttr = args.ModelType.Assembly.GetCustomAttribute<ModelsBuilderAssemblyAttribute>();
|
||||
ModelsBuilderAssemblyAttribute sourceAttr = notification.SourceType.Assembly.GetCustomAttribute<ModelsBuilderAssemblyAttribute>();
|
||||
ModelsBuilderAssemblyAttribute modelAttr = notification.ModelType.Assembly.GetCustomAttribute<ModelsBuilderAssemblyAttribute>();
|
||||
|
||||
// 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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<IEventAggregator>());
|
||||
|
||||
[Test]
|
||||
[TestCase(typeof(IPublishedContent), false)]
|
||||
|
||||
@@ -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<TModel> : UmbracoViewPage<TModel>
|
||||
{
|
||||
private readonly ContentModelBinder _modelBinder = new ContentModelBinder();
|
||||
private readonly ContentModelBinder _modelBinder = new ContentModelBinder(Mock.Of<IEventAggregator>());
|
||||
|
||||
public override Task ExecuteAsync() => throw new NotImplementedException();
|
||||
|
||||
|
||||
@@ -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
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// Maps view models, supporting mapping to and from any <see cref="IPublishedContent"/> or <see cref="IContentModel"/>.
|
||||
/// </summary>
|
||||
public class ContentModelBinder : IModelBinder
|
||||
{
|
||||
private readonly IEventAggregator _eventAggregator;
|
||||
|
||||
/// <summary>
|
||||
/// Occurs on model binding exceptions.
|
||||
/// Initializes a new instance of the <see cref="ContentModelBinder"/> class.
|
||||
/// </summary>
|
||||
public event EventHandler<ModelBindingArgs> ModelBindingException; // TODO: This cannot use IEventAggregator currently because it cannot be async
|
||||
public ContentModelBinder(IEventAggregator eventAggregator) => _eventAggregator = eventAggregator;
|
||||
|
||||
/// <inheritdoc/>
|
||||
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());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Contains event data for the <see cref="ModelBindingException"/> event.
|
||||
/// </summary>
|
||||
public class ModelBindingArgs : EventArgs
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="ModelBindingArgs"/> class.
|
||||
/// </summary>
|
||||
public ModelBindingArgs(Type sourceType, Type modelType, StringBuilder message)
|
||||
{
|
||||
SourceType = sourceType;
|
||||
ModelType = modelType;
|
||||
Message = message;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the type of the source object.
|
||||
/// </summary>
|
||||
public Type SourceType { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the type of the view model.
|
||||
/// </summary>
|
||||
public Type ModelType { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the message string builder.
|
||||
/// </summary>
|
||||
/// <remarks>Handlers of the event can append text to the message.</remarks>
|
||||
public StringBuilder Message { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether the application should restart.
|
||||
/// </summary>
|
||||
public bool Restart { get; set; }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
43
src/Umbraco.Web.Common/ModelBinders/ModelBindingError.cs
Normal file
43
src/Umbraco.Web.Common/ModelBinders/ModelBindingError.cs
Normal file
@@ -0,0 +1,43 @@
|
||||
using System;
|
||||
using System.Text;
|
||||
using Umbraco.Core.Events;
|
||||
|
||||
namespace Umbraco.Web.Common.ModelBinders
|
||||
{
|
||||
/// <summary>
|
||||
/// Contains event data for the <see cref="ModelBindingException"/> event.
|
||||
/// </summary>
|
||||
public class ModelBindingError : INotification
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="ModelBindingError"/> class.
|
||||
/// </summary>
|
||||
public ModelBindingError(Type sourceType, Type modelType, StringBuilder message)
|
||||
{
|
||||
SourceType = sourceType;
|
||||
ModelType = modelType;
|
||||
Message = message;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the type of the source object.
|
||||
/// </summary>
|
||||
public Type SourceType { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the type of the view model.
|
||||
/// </summary>
|
||||
public Type ModelType { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the message string builder.
|
||||
/// </summary>
|
||||
/// <remarks>Handlers of the event can append text to the message.</remarks>
|
||||
public StringBuilder Message { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether the application should restart.
|
||||
/// </summary>
|
||||
public bool Restart { get; set; }
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user