Change ViewModel Property value using plugin in nopCommerce

272 Views Asked by At

I am working on nopCommerce v3.90. I have a requirement to a plugin which would update the original Price of the Product by some percentage ratio based on the settings performed within plugin settings section, without altering the existing nopCommerce model structure.

Hence, each time the product's price is displayed, one should be able to see the new updated price (based on the action performed in a plugin) instead of the price from the database.

Can anyone help me with this?

Existing Model class in nopCommerce

public partial class ProductPriceModel : BaseNopModel
{
    //block of statements

    public string Price { get; set; } //the property whose value need to be changed from plugin

    //block of statements
}
1

There are 1 best solutions below

1
Raphael On

In 3.9 the options I know are

  • Override PrepareProductPriceModel method in IProductModelFactory class and provide your custom implementation using dependency override
  • Implement an ActionFilter to customize the ProductPriceModel before it gets used in the view.

In 4.0 this is very easy. You only have to subscribe to ModelPreparedEvent and then customize the ProductPriceModel.


Override IProductModelFactory

public class CustomProductModelFactory : ProductModelFactory
{    
    // ctor ....

    protected override ProductDetailsModel.ProductPriceModel PrepareProductPriceModel(Product product)
    {
        // your own logic to prepare price model
    }    
}

In your plugin dependency registrar

builder.RegisterType<CustomProductModelFactory>()
       .As<IProductModelFactory>()
       .WithParameter(ResolvedParameter.ForNamed<ICacheManager>("nop_cache_static"))
       .InstancePerLifetimeScope();

Implement ActionFilter

public class PriceInterceptor : ActionFilterAttribute
{
    public override void OnActionExecuting(ActionExecutingContext filterContext)
    {
        if (filterContext == null) throw new ArgumentNullException(nameof(filterContext));    
        if (filterContext.HttpContext?.Request == null) return;

        if (filterContext.Controller is Controller controller)
        {
            if (controller.ViewData.Model is ProductDetailsModel model)
            {
                // your own logic to prepare price model
            }
        }
    }
}

And to dynamically provide your ActionFilter

public class PriceInterceptorFilterProvider : IFilterProvider
{
    public IEnumerable<Filter> GetFilters(ControllerContext controllerContext, ActionDescriptor actionDescriptor)
    {
        return new[] { new Filter(new PriceInterceptor(), FilterScope.Action, null) };
    }
}

In your plugin dependency registrar

builder.RegisterType<PriceInterceptorFilterProvider>()
       .As<IFilterProvider>();

Subscribe to ModelPreparedEvent<ProductDetailsModel> (nopCommerce 4.0)

public class PriceInterceptor : IConsumer<ModelPreparedEvent<ProductDetailsModel>>
{
    public void HandleEvent(ModelPreparedEvent<ProductDetailsModel> eventMessage)
    {
        // your own logic to prepare price model
    }
}