Try your search with a different keyword or use * as a wildcard.
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Filters;
using Nop.Core.Events;
using Nop.Core.Http.Extensions;
using Nop.Web.Framework.Events;
using Nop.Web.Framework.Models;
namespace Nop.Web.Framework.Mvc.Filters;
///
/// Represents filter attribute that publish ModelReceived event before the action executes, after model binding is complete
/// and publish ModelPrepared event after the action executes, before the action result
///
public sealed class PublishModelEventsAttribute : TypeFilterAttribute
{
#region Ctor
///
/// Create instance of the filter attribute
///
/// Whether to ignore the execution of filter actions
public PublishModelEventsAttribute(bool ignore = false) : base(typeof(PublishModelEventsFilter))
{
IgnoreFilter = ignore;
Arguments = [ignore];
}
#endregion
#region Properties
///
/// Gets a value indicating whether to ignore the execution of filter actions
///
public bool IgnoreFilter { get; }
#endregion
#region Nested filter
///
/// Represents filter that publish ModelReceived event before the action executes, after model binding is complete
/// and publish ModelPrepared event after the action executes, before the action result
///
private class PublishModelEventsFilter : IAsyncActionFilter, IAsyncResultFilter
{
#region Fields
protected readonly bool _ignoreFilter;
protected readonly IEventPublisher _eventPublisher;
#endregion
#region Ctor
public PublishModelEventsFilter(bool ignoreFilter,
IEventPublisher eventPublisher)
{
_ignoreFilter = ignoreFilter;
_eventPublisher = eventPublisher;
}
#endregion
#region Utilities
///
/// Whether to ignore this filter
///
/// A context for action filters
/// Result
protected virtual bool IgnoreFilter(FilterContext context)
{
//check whether this filter has been overridden for the Action
var actionFilter = context.ActionDescriptor.FilterDescriptors
.Where(filterDescriptor => filterDescriptor.Scope == FilterScope.Action)
.Select(filterDescriptor => filterDescriptor.Filter)
.OfType()
.FirstOrDefault();
return actionFilter?.IgnoreFilter ?? _ignoreFilter;
}
///
/// Publish model prepared event
///
/// Model
/// A task that represents the asynchronous operation
protected virtual async Task PublishModelPreparedEventAsync(object model)
{
//we publish the ModelPrepared event for all models as the BaseNopModel,
//so you need to implement IConsumer> interface to handle this event
if (model is BaseNopModel nopModel)
await _eventPublisher.ModelPreparedAsync(nopModel);
//we publish the ModelPrepared event for collection as the IEnumerable,
//so you need to implement IConsumer>> interface to handle this event
if (model is IEnumerable nopModelCollection)
await _eventPublisher.ModelPreparedAsync(nopModelCollection);
}
///
/// Called asynchronously before the action, after model binding is complete.
///
/// A context for action filters
/// A task that represents the asynchronous operation
private async Task PublishModelReceivedEventAsync(ActionExecutingContext context)
{
ArgumentNullException.ThrowIfNull(context);
//only in POST requests
if (!context.HttpContext.Request.IsPostRequest())
return;
if (IgnoreFilter(context))
return;
//model received event
foreach (var model in context.ActionArguments.Values.OfType())
{
//we publish the ModelReceived event for all models as the BaseNopModel,
//so you need to implement IConsumer> interface to handle this event
await _eventPublisher.ModelReceivedAsync(model, context.ModelState);
}
}
///
/// Called asynchronously before the action, after model binding is complete.
///
/// A context for action filters
/// A task that represents the asynchronous operation
private async Task PublishModelPreparedEventAsync(ActionExecutingContext context)
{
ArgumentNullException.ThrowIfNull(context);
if (IgnoreFilter(context))
return;
//model prepared event
if (context.Controller is Controller controller)
await PublishModelPreparedEventAsync(controller.ViewData.Model);
}
#endregion
#region Methods
///
/// Called asynchronously before the action, after model binding is complete.
///
/// A context for action filters
/// A delegate invoked to execute the next action filter or the action itself
/// A task that represents the asynchronous operation
public async Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next)
{
await PublishModelReceivedEventAsync(context);
if (context.Result == null)
await next();
await PublishModelPreparedEventAsync(context);
}
/// Called asynchronously before the action result.
/// A context for action filters
/// A delegate invoked to execute the next action filter or the action itself
/// A task that represents the asynchronous operation
public async Task OnResultExecutionAsync(ResultExecutingContext context, ResultExecutionDelegate next)
{
ArgumentNullException.ThrowIfNull(context);
if (IgnoreFilter(context))
return;
//model prepared event
if (context.Result is JsonResult result)
await PublishModelPreparedEventAsync(result.Value);
await next();
}
#endregion
}
#endregion
}