一、基础介绍

  ——In computing, a plug-in (or plugin) is a set of software components that add specific abilities to a larger software application (Wikipedia).

  Plugin,即插件,用来做NopCommerce的功能扩展。NopCommerce源码本身提供了一些插件供参考使用。本篇文章通过阅读官方文档进行实践总结,主要讲解如何编写一个数据持久化的NopCommerce插件。

二、效果展示

  当打开前台产品详细时,系统会自动追踪并记录用户访问的产品信息、访问的用户信息及其IP地址信息等。

  

三、编写步骤

  1.新建项目,项目名为Nop.Plugin.Other.ProductViewTracker,注意项目位置需统一放置在..\plugins\下,与输出位置保持统一。

  

  2.添加Description.txt文件,该文件为必备文件,且格式需保持统一。该文件描述插件相关信息,并作为系统识别插件依据。

  

  3.添加必要的文件夹,名称可根据个人习惯,这里为保持命名规则统一,命名如下Controllers、Data、Domain、Services。

  

  4.添加dll引用,且设置属性"Copy Local"为False。本项目引用如图所示。

   

  5.添加实体类及其数据库映射,添加数据库访问上下文。

    5.1 实体类TrackingRecord,继承基类BaseEntity

 using Nop.Core;

 namespace Nop.Plugin.Other.ProductViewTracker.Domain
{
public class TrackingRecord : BaseEntity
{
public virtual int ProductId { get; set; }
public virtual string ProductName { get; set; }
public virtual int CustomerId { get; set; }
public virtual string IpAddress { get; set; }
public virtual bool IsRegistered { get; set; }
}
}

    5.2 数据库表映射类TrackingRecordMap,继承EntityTypeConfiguration<T>

 using Nop.Plugin.Other.ProductViewTracker.Domain;
using System.Data.Entity.ModelConfiguration; namespace Nop.Plugin.Other.ProductViewTracker.Data
{
public class TrackingRecordMap : EntityTypeConfiguration<TrackingRecord>
{
public TrackingRecordMap()
{
ToTable("ProductViewTracking"); HasKey(m => m.Id);
Property(m => m.ProductId);
Property(m => m.ProductName).HasMaxLength();
Property(m => m.IpAddress);
Property(m => m.CustomerId);
Property(m => m.IsRegistered);
}
}
}

    5.3 数据库访问上下文,安装插件时生成并执行建表脚本,卸载插件时删除该表

 using Nop.Data;
using System;
using System.Collections.Generic;
using System.Data.Entity;
using Nop.Core;
using System.Data.Entity.Infrastructure; namespace Nop.Plugin.Other.ProductViewTracker.Data
{
public class TrackingRecordObjectContext : DbContext, IDbContext
{
public TrackingRecordObjectContext(string nameOrConnectionString) : base(nameOrConnectionString) { } #region Implementation of IDbContext public bool AutoDetectChangesEnabled
{
get
{
throw new NotImplementedException();
} set
{
throw new NotImplementedException();
}
} public bool ProxyCreationEnabled
{
get
{
throw new NotImplementedException();
} set
{
throw new NotImplementedException();
}
} public void Detach(object entity)
{
throw new NotImplementedException();
} public int ExecuteSqlCommand(string sql, bool doNotEnsureTransaction = false, int? timeout = default(int?), params object[] parameters)
{
throw new NotImplementedException();
} public IList<TEntity> ExecuteStoredProcedureList<TEntity>(string commandText, params object[] parameters) where TEntity : BaseEntity, new()
{
throw new NotImplementedException();
} public IEnumerable<TElement> SqlQuery<TElement>(string sql, params object[] parameters)
{
throw new NotImplementedException();
} public new IDbSet<TEntity> Set<TEntity>() where TEntity : BaseEntity
{
return base.Set<TEntity>();
} protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Configurations.Add(new TrackingRecordMap()); base.OnModelCreating(modelBuilder);
} #endregion public string CreateDatabaseInstallationScript()
{
return ((IObjectContextAdapter)this).ObjectContext.CreateDatabaseScript();
} public void Install()
{
Database.SetInitializer<TrackingRecordObjectContext>(null); Database.ExecuteSqlCommand(CreateDatabaseInstallationScript());
SaveChanges();
} public void Uninstall()
{
var dbScript = "DROP TABLE ProductViewTracking";
Database.ExecuteSqlCommand(dbScript);
SaveChanges();
}
}
}

  6.添加业务服务类。

    6.1 服务接口

 using Nop.Plugin.Other.ProductViewTracker.Domain;

 namespace Nop.Plugin.Other.ProductViewTracker.Services
{
public interface IViewTrackingService
{
/// <summary>
/// Logs the specified record.
/// </summary>
/// <param name="record">The record.</param>
void Log(TrackingRecord record);
}
}

    6.2 业务服务类

 using Nop.Core.Data;
using Nop.Plugin.Other.ProductViewTracker.Domain; namespace Nop.Plugin.Other.ProductViewTracker.Services
{
public class ViewTrackingService : IViewTrackingService
{
private readonly IRepository<TrackingRecord> _trackingRecordRepository; public ViewTrackingService(IRepository<TrackingRecord> trackingRecordRepository)
{
_trackingRecordRepository = trackingRecordRepository;
} public void Log(TrackingRecord record)
{
_trackingRecordRepository.Insert(record);
}
}
}

  7.实现依赖注入的注册接口。

 using Nop.Core.Infrastructure.DependencyManagement;
using Autofac;
using Nop.Core.Configuration;
using Nop.Core.Infrastructure;
using Nop.Plugin.Other.ProductViewTracker.Services;
using Nop.Web.Framework.Mvc;
using Nop.Plugin.Other.ProductViewTracker.Data;
using Nop.Data;
using Nop.Plugin.Other.ProductViewTracker.Domain;
using Nop.Core.Data;
using Autofac.Core; namespace Nop.Plugin.Other.ProductViewTracker
{
public class DependencyRegistrar : IDependencyRegistrar
{
private const string CONTEXT_NAME = "nop_object_context_product_view_tracker"; public void Register(ContainerBuilder builder, ITypeFinder typeFinder, NopConfig config)
{
builder.RegisterType<ViewTrackingService>().As<IViewTrackingService>().InstancePerLifetimeScope(); //data context
this.RegisterPluginDataContext<TrackingRecordObjectContext>(builder, CONTEXT_NAME); //override required repository with our custom context
builder.RegisterType<EfRepository<TrackingRecord>>()
.As<IRepository<TrackingRecord>>()
.WithParameter(ResolvedParameter.ForNamed<IDbContext>(CONTEXT_NAME))
.InstancePerLifetimeScope();
} public int Order
{
get { return ; }
}
}
}

  8.添加MVC Controller。

 using Nop.Core;
using Nop.Core.Domain.Catalog;
using Nop.Core.Domain.Customers;
using Nop.Core.Plugins;
using Nop.Plugin.Other.ProductViewTracker.Domain;
using Nop.Plugin.Other.ProductViewTracker.Services;
using Nop.Services.Catalog;
using Nop.Web.Framework.Controllers;
using System.Web.Mvc; namespace Nop.Plugin.Other.ProductViewTracker.Controllers
{
public class TrackingController : BasePluginController
{
private readonly IProductService _productService;
private readonly IViewTrackingService _viewTrackingService;
private readonly IWorkContext _workContext; public TrackingController(IWorkContext workContext,
IViewTrackingService viewTrackingService,
IProductService productService,
IPluginFinder pluginFinder)
{
_workContext = workContext;
_viewTrackingService = viewTrackingService;
_productService = productService;
} [ChildActionOnly]
public ActionResult Index(int productId)
{
//Read from the product service
Product productById = _productService.GetProductById(productId); //If the product exists we will log it
if (productById != null)
{
//Setup the product to save
var record = new TrackingRecord();
record.ProductId = productId;
record.ProductName = productById.Name;
record.CustomerId = _workContext.CurrentCustomer.Id;
record.IpAddress = _workContext.CurrentCustomer.LastIpAddress;
record.IsRegistered = _workContext.CurrentCustomer.IsRegistered(); //Map the values we're interested in to our new entity
_viewTrackingService.Log(record);
} //Return the view, it doesn't need a model
return Content("");
}
}
}

  9.实现路由接口。

 using Nop.Web.Framework.Mvc.Routes;
using System.Web.Mvc;
using System.Web.Routing; namespace Nop.Plugin.Other.ProductViewTracker
{
public class RouteProvider : IRouteProvider
{
public int Priority
{
get
{
return ;
}
} public void RegisterRoutes(RouteCollection routes)
{
routes.MapRoute("Nop.Plugin.Other.ProductViewTracker.Log",
"tracking/productviews/{productId}",
new { controller = "Tracking", action = "Index" },
new[] { "Nop.Plugin.Other.ProductViewTracker.Controllers" }
);
}
}
}

  10.添加插件类,继承插件基类,重载安装和卸载方法。

 using Nop.Core.Plugins;
using Nop.Plugin.Other.ProductViewTracker.Data; namespace Nop.Plugin.Other.ProductViewTracker
{
public class ProductViewTrackerPlugin : BasePlugin
{
private readonly TrackingRecordObjectContext _context; public ProductViewTrackerPlugin(TrackingRecordObjectContext context)
{
_context = context;
} public override void Install()
{
_context.Install();
base.Install();
} public override void Uninstall()
{
_context.Uninstall();
base.Uninstall();
}
}
}

  11.在NopCommerce的前台,加入插件的应用代码。这里,我们在页面Nop.Web\Views\Product\ProductTemplate.Simple.cshtml中插入应用代码。

@Html.Action("Index", "Tracking", new { productId = Model.Id })

  如图

  

我的NopCommerce之旅(9): 编写Plugin实例的更多相关文章

  1. 我的NopCommerce之旅(8): 路由分析

    一.导图和基础介绍 本文主要介绍NopCommerce的路由机制,网上有一篇不错的文章,有兴趣的可以看看NopCommerce源码架构详解--对seo友好Url的路由机制实现源码分析 SEO,Sear ...

  2. [转]NopCommerce之旅: 应用启动

    本文转自:http://www.cnblogs.com/devilsky/p/5359881.html 我的NopCommerce之旅(6): 应用启动   一.基础介绍 Global.asax 文件 ...

  3. 初探webpack之编写plugin

    初探webpack之编写plugin webpack通过plugin机制让其使用更加灵活,以适应各种应用场景,当然也大大增加了webpack的复杂性,在webpack运行的生命周期中会广播出许多事件, ...

  4. 【小白的CFD之旅】13 敲门实例【续3】

    接上文[小白的CFD之旅]12 敲门实例[续2] 4 Results4.1 计算监测图形4.2 Graphics4.2.1 壁面温度分布4.2.2 创建截面4.2.3 显示截面物理量4.2.4 Pat ...

  5. 【小白的CFD之旅】11 敲门实例【续】

    主要内容: 接上文[小白的CFD之旅]10 敲门实例 2.4 Materials设置2.5 Cell Zone Conditions2.6 Boundary Conditons2.7 Dynamic ...

  6. [转]nopcommerce商城系统--如何编写一个插件

    本文转自:http://www.cnblogs.com/ganqiyin/p/3680771.html 原址:http://www.nopcommerce.com/docs/77/how-to-wri ...

  7. nopcommerce商城系统--如何编写一个插件

    原址:http://www.nopcommerce.com/docs/77/how-to-write-a-nopcommerce-plugin.aspx plug-in (或 plugin)是一个为更 ...

  8. 我的NopCommerce之旅(7): 依赖注入(IOC/DI)

    一.基础介绍 依赖注入,Dependency Injection,权威解释及说明请自己查阅资料. 这里简单说一下常见使用:在mvc的controller的构造方法中定义参数,如ICountryServ ...

  9. 我的NopCommerce之旅(5): 缓存

    一.基础介绍 1.什么是cache      Web缓存是指一个Web资源(如html页面,图片,js,数据等)存在于Web服务器和客户端(浏览器)之间的副本. 2.为什么要用cache      即 ...

随机推荐

  1. C#评分小系统练习

    一个经理类 using System; using System.Collections.Generic; using System.Linq; using System.Text; using Sy ...

  2. 组合优化学习笔记<之>从贪心算法到子集系统再到拟阵

    贪心算法是用的比较多的一种优化算法,因为它过程简洁优美,而且结果有效.有些优化问题如最大权森林(MWF)是可以用贪心问题求解的,由于最小支撑树(MST)问题与MWF是等价的,所以MST也是可以用贪心算 ...

  3. C语言中数组做函数参数的问题

    数组做函数参数,会退化成为一个指针变量.因此在进行数组参数传递的同时,需要传递一个数组长度的参数变量. 数组长度可以通过sizeof(arr)/siezof(arr[0])来得到.关于这个sizeof ...

  4. OpenCV——PS滤镜 水波效果

    // define head function #ifndef PS_ALGORITHM_H_INCLUDED #define PS_ALGORITHM_H_INCLUDED #include < ...

  5. Chapter3——进入Android Dalvik虚拟机(二)

    Dalvik汇编语言基础 Dalvik虚拟机为自己设计了一套指令集,并制定了自己的指令格式和调用规范. 位描述约定如下: 每16位的字采用空格分隔开来 每个字母表示4位,每个字母按顺序从高字节开始,排 ...

  6. springboot开启远程调试

    远程调试maven设置 The run goal forks a process for the boot application. It is possible to specify jvm arg ...

  7. vs缩进多行,vs2013测试可用

    vs缩进多行,vs2013测试可用 选中要缩进的行,然后点击tab会直接在选中行增大缩进 快捷键 功能 描述 tab 增大缩进 选中要缩进的行,可多行 shift + table 减小缩进 选中要缩进 ...

  8. eclipse编辑窗口不见了(打开左边的java、xml文件,中间不会显示代码)

    转自:https://blog.csdn.net/u012062810/article/details/46729779?utm_source=blogxgwz4 1. windows-->re ...

  9. java 内存管理机制

    垃圾收集算法 1.标记清理算法:效率不高(标记和清理过程效率都不高).会形成内存碎片 2.复制算法:把内存分为两部分,当进行回收时,把使用部分的存活对象复制到未使用部分,然后两部分内存角色互换(一个为 ...

  10. C# 计算时间日期

    System.DateTime datetime = System.DateTime.Now.AddSeconds(fixtime); // fixtime 是往后的秒数 : datetime是现在时 ...