Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
#282 Add filter attribute for publishing ModelReceived and ModelPrep…
…ared events
- Loading branch information
Showing
5 changed files
with
203 additions
and
14 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
23 changes: 17 additions & 6 deletions
23
src/Presentation/Nop.Web.Framework/Events/ModelPrepared.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,18 +1,29 @@ | ||
using System; | ||
using System.Collections.Generic; | ||
using System.Linq; | ||
using System.Text; | ||
using System.Threading.Tasks; | ||
using Nop.Web.Framework.Mvc.Models; | ||
using Nop.Web.Framework.Mvc.Models; | ||
|
||
namespace Nop.Web.Framework.Events | ||
{ | ||
/// <summary> | ||
/// Represents an event that occurs after the model is prepared for view | ||
/// </summary> | ||
/// <typeparam name="T">Type of the model</typeparam> | ||
public class ModelPrepared<T> where T : BaseNopModel | ||
{ | ||
#region Ctor | ||
|
||
public ModelPrepared(T model) | ||
{ | ||
this.Model = model; | ||
} | ||
|
||
#endregion | ||
|
||
#region Properties | ||
|
||
/// <summary> | ||
/// Gets a model | ||
/// </summary> | ||
public T Model { get; private set; } | ||
|
||
#endregion | ||
} | ||
} |
26 changes: 20 additions & 6 deletions
26
src/Presentation/Nop.Web.Framework/Events/ModelReceived.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,22 +1,36 @@ | ||
using System; | ||
using System.Collections.Generic; | ||
using System.Linq; | ||
using System.Text; | ||
using System.Threading.Tasks; | ||
using Microsoft.AspNetCore.Mvc.ModelBinding; | ||
using Microsoft.AspNetCore.Mvc.ModelBinding; | ||
using Nop.Web.Framework.Mvc.Models; | ||
|
||
namespace Nop.Web.Framework.Events | ||
{ | ||
/// <summary> | ||
/// Represents an event that occurs after the model is receved from the view | ||
/// </summary> | ||
/// <typeparam name="T">Type of the model</typeparam> | ||
public class ModelReceived<T> where T : BaseNopModel | ||
{ | ||
#region Ctor | ||
|
||
public ModelReceived(T model, ModelStateDictionary modelState) | ||
{ | ||
this.Model = model; | ||
this.ModelState = modelState; | ||
} | ||
|
||
#endregion | ||
|
||
#region Properties | ||
|
||
/// <summary> | ||
/// Gets a model | ||
/// </summary> | ||
public T Model { get; private set; } | ||
|
||
/// <summary> | ||
/// Gets a model state | ||
/// </summary> | ||
public ModelStateDictionary ModelState { get; private set; } | ||
|
||
#endregion | ||
} | ||
} |
148 changes: 148 additions & 0 deletions
148
src/Presentation/Nop.Web.Framework/Mvc/Filters/PublishModelEventsAttribute.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,148 @@ | ||
using System; | ||
using System.Linq; | ||
using System.Net; | ||
using Microsoft.AspNetCore.Mvc; | ||
using Microsoft.AspNetCore.Mvc.Filters; | ||
using Nop.Services.Events; | ||
using Nop.Web.Framework.Events; | ||
using Nop.Web.Framework.Mvc.Models; | ||
|
||
namespace Nop.Web.Framework.Mvc.Filters | ||
{ | ||
/// <summary> | ||
/// 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 | ||
/// </summary> | ||
public class PublishModelEventsAttribute : TypeFilterAttribute | ||
{ | ||
#region Fields | ||
|
||
private readonly bool _ignoreFilter; | ||
|
||
#endregion | ||
|
||
#region Ctor | ||
|
||
/// <summary> | ||
/// Create instance of the filter attribute | ||
/// </summary> | ||
/// <param name="ignore">Whether to ignore the execution of filter actions</param> | ||
public PublishModelEventsAttribute(bool ignore = false) : base(typeof(PublishModelEventsFilter)) | ||
{ | ||
this._ignoreFilter = ignore; | ||
this.Arguments = new object[] { ignore }; | ||
} | ||
|
||
#endregion | ||
|
||
#region Properties | ||
|
||
/// <summary> | ||
/// Gets a value indicating whether to ignore the execution of filter actions | ||
/// </summary> | ||
public bool IgnoreFilter => _ignoreFilter; | ||
|
||
#endregion | ||
|
||
#region Nested filter | ||
|
||
/// <summary> | ||
/// 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 | ||
/// </summary> | ||
private class PublishModelEventsFilter : IActionFilter | ||
{ | ||
#region Fields | ||
|
||
private readonly bool _ignoreFilter; | ||
private readonly IEventPublisher _eventPublisher; | ||
|
||
#endregion | ||
|
||
#region Ctor | ||
|
||
public PublishModelEventsFilter(bool ignoreFilter, | ||
IEventPublisher eventPublisher) | ||
{ | ||
this._ignoreFilter = ignoreFilter; | ||
this._eventPublisher = eventPublisher; | ||
} | ||
|
||
#endregion | ||
|
||
#region Methods | ||
|
||
/// <summary> | ||
/// Called before the action executes, after model binding is complete | ||
/// </summary> | ||
/// <param name="context">A context for action filters</param> | ||
public void OnActionExecuting(ActionExecutingContext context) | ||
{ | ||
if (context == null) | ||
throw new ArgumentNullException(nameof(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<PublishModelEventsAttribute>().FirstOrDefault(); | ||
|
||
//whether to ignore this filter | ||
if (actionFilter?.IgnoreFilter ?? _ignoreFilter) | ||
return; | ||
|
||
if (context.HttpContext.Request == null) | ||
return; | ||
|
||
//only in POST requests | ||
if (!context.HttpContext.Request.Method.Equals(WebRequestMethods.Http.Post, StringComparison.InvariantCultureIgnoreCase)) | ||
return; | ||
|
||
//model received event | ||
foreach (var model in context.ActionArguments.Values.OfType<BaseNopModel>()) | ||
{ | ||
//we publish the ModelReceived event for all models as the BaseNopModel, | ||
//so you need to implement IConsumer<ModelReceived<BaseNopModel>> interface to handle this event | ||
_eventPublisher.ModelReceived(model, context.ModelState); | ||
} | ||
} | ||
|
||
/// <summary> | ||
/// Called after the action executes, before the action result | ||
/// </summary> | ||
/// <param name="context">A context for action filters</param> | ||
public void OnActionExecuted(ActionExecutedContext context) | ||
{ | ||
if (context == null) | ||
throw new ArgumentNullException(nameof(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<PublishModelEventsAttribute>().FirstOrDefault(); | ||
|
||
//whether to ignore this filter | ||
if (actionFilter?.IgnoreFilter ?? _ignoreFilter) | ||
return; | ||
|
||
if (context.HttpContext.Request == null) | ||
return; | ||
|
||
//only in GET requests | ||
if (!context.HttpContext.Request.Method.Equals(WebRequestMethods.Http.Get, StringComparison.InvariantCultureIgnoreCase)) | ||
return; | ||
|
||
//model prepared event | ||
if (context.Controller is Controller controller && controller.ViewData.Model is BaseNopModel model) | ||
{ | ||
//we publish the ModelPrepared event for all models as the BaseNopModel, | ||
//so you need to implement IConsumer<ModelPrepared<BaseNopModel>> interface to handle this event | ||
_eventPublisher.ModelPrepared(model); | ||
} | ||
} | ||
|
||
#endregion | ||
} | ||
|
||
#endregion | ||
} | ||
} |