我的NopCommerce之旅(9): 编写Plugin实例
——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
1 using Nop.Core; 2 3 namespace Nop.Plugin.Other.ProductViewTracker.Domain 4 { 5 public class TrackingRecord : BaseEntity 6 { 7 public virtual int ProductId { get; set; } 8 public virtual string ProductName { get; set; } 9 public virtual int CustomerId { get; set; } 10 public virtual string IpAddress { get; set; } 11 public virtual bool IsRegistered { get; set; } 12 } 13 }5.2 数据库表映射类TrackingRecordMap,继承EntityTypeConfiguration<T>
1 using Nop.Plugin.Other.ProductViewTracker.Domain; 2 using System.Data.Entity.ModelConfiguration; 3 4 namespace Nop.Plugin.Other.ProductViewTracker.Data 5 { 6 public class TrackingRecordMap : EntityTypeConfiguration<TrackingRecord> 7 { 8 public TrackingRecordMap() 9 { 10 ToTable('ProductViewTracking'); 11 12 HasKey(m => m.Id); 13 Property(m => m.ProductId); 14 Property(m => m.ProductName).HasMaxLength(400); 15 Property(m => m.IpAddress); 16 Property(m => m.CustomerId); 17 Property(m => m.IsRegistered); 18 } 19 } 20 }5.3 数据库访问上下文,安装插件时生成并执行建表脚本,卸载插件时删除该表
1 using Nop.Data; 2 using System; 3 using System.Collections.Generic; 4 using System.Data.Entity; 5 using Nop.Core; 6 using System.Data.Entity.Infrastructure; 7 8 namespace Nop.Plugin.Other.ProductViewTracker.Data 9 { 10 public class TrackingRecordObjectContext : DbContext, IDbContext 11 { 12 public TrackingRecordObjectContext(string nameOrConnectionString) : base(nameOrConnectionString) { } 13 14 #region Implementation of IDbContext 15 16 public bool AutoDetectChangesEnabled 17 { 18 get 19 { 20 throw new NotImplementedException(); 21 } 22 23 set 24 { 25 throw new NotImplementedException(); 26 } 27 } 28 29 public bool ProxyCreationEnabled 30 { 31 get 32 { 33 throw new NotImplementedException(); 34 } 35 36 set 37 { 38 throw new NotImplementedException(); 39 } 40 } 41 42 public void Detach(object entity) 43 { 44 throw new NotImplementedException(); 45 } 46 47 public int ExecuteSqlCommand(string sql, bool doNotEnsureTransaction = false, int? timeout = default(int?), params object[] parameters) 48 { 49 throw new NotImplementedException(); 50 } 51 52 public IList<TEntity> ExecuteStoredProcedureList<TEntity>(string commandText, params object[] parameters) where TEntity : BaseEntity, new() 53 { 54 throw new NotImplementedException(); 55 } 56 57 public IEnumerable<TElement> SqlQuery<TElement>(string sql, params object[] parameters) 58 { 59 throw new NotImplementedException(); 60 } 61 62 public new IDbSet<TEntity> Set<TEntity>() where TEntity : BaseEntity 63 { 64 return base.Set<TEntity>(); 65 } 66 67 protected override void OnModelCreating(DbModelBuilder modelBuilder) 68 { 69 modelBuilder.Configurations.Add(new TrackingRecordMap()); 70 71 base.OnModelCreating(modelBuilder); 72 } 73 74 #endregion 75 76 public string CreateDatabaseInstallationScript() 77 { 78 return ((IObjectContextAdapter)this).ObjectContext.CreateDatabaseScript(); 79 } 80 81 public void Install() 82 { 83 Database.SetInitializer<TrackingRecordObjectContext>(null); 84 85 Database.ExecuteSqlCommand(CreateDatabaseInstallationScript()); 86 SaveChanges(); 87 } 88 89 public void Uninstall() 90 { 91 var dbScript = 'DROP TABLE ProductViewTracking'; 92 Database.ExecuteSqlCommand(dbScript); 93 SaveChanges(); 94 } 95 } 96 }6.添加业务服务类。
6.1 服务接口
1 using Nop.Plugin.Other.ProductViewTracker.Domain; 2 3 namespace Nop.Plugin.Other.ProductViewTracker.Services 4 { 5 public interface IViewTrackingService 6 { 7 /// <summary> 8 /// Logs the specified record. 9 /// </summary> 10 /// <param name='record'>The record.</param> 11 void Log(TrackingRecord record); 12 } 13 }6.2 业务服务类
1 using Nop.Core.Data; 2 using Nop.Plugin.Other.ProductViewTracker.Domain; 3 4 namespace Nop.Plugin.Other.ProductViewTracker.Services 5 { 6 public class ViewTrackingService : IViewTrackingService 7 { 8 private readonly IRepository<TrackingRecord> _trackingRecordRepository; 9 10 public ViewTrackingService(IRepository<TrackingRecord> trackingRecordRepository) 11 { 12 _trackingRecordRepository = trackingRecordRepository; 13 } 14 15 public void Log(TrackingRecord record) 16 { 17 _trackingRecordRepository.Insert(record); 18 } 19 } 20 }7.实现依赖注入的注册接口。
1 using Nop.Core.Infrastructure.DependencyManagement; 2 using Autofac; 3 using Nop.Core.Configuration; 4 using Nop.Core.Infrastructure; 5 using Nop.Plugin.Other.ProductViewTracker.Services; 6 using Nop.Web.Framework.Mvc; 7 using Nop.Plugin.Other.ProductViewTracker.Data; 8 using Nop.Data; 9 using Nop.Plugin.Other.ProductViewTracker.Domain; 10 using Nop.Core.Data; 11 using Autofac.Core; 12 13 namespace Nop.Plugin.Other.ProductViewTracker 14 { 15 public class DependencyRegistrar : IDependencyRegistrar 16 { 17 private const string CONTEXT_NAME = 'nop_object_context_product_view_tracker'; 18 19 public void Register(ContainerBuilder builder, ITypeFinder typeFinder, NopConfig config) 20 { 21 builder.RegisterType<ViewTrackingService>().As<IViewTrackingService>().InstancePerLifetimeScope(); 22 23 //data context 24 this.RegisterPluginDataContext<TrackingRecordObjectContext>(builder, CONTEXT_NAME); 25 26 //override required repository with our custom context 27 builder.RegisterType<EfRepository<TrackingRecord>>() 28 .As<IRepository<TrackingRecord>>() 29 .WithParameter(ResolvedParameter.ForNamed<IDbContext>(CONTEXT_NAME)) 30 .InstancePerLifetimeScope(); 31 } 32 33 public int Order 34 { 35 get { return 1; } 36 } 37 } 38 }8.添加MVC Controller。
1 using Nop.Core; 2 using Nop.Core.Domain.Catalog; 3 using Nop.Core.Domain.Customers; 4 using Nop.Core.Plugins; 5 using Nop.Plugin.Other.ProductViewTracker.Domain; 6 using Nop.Plugin.Other.ProductViewTracker.Services; 7 using Nop.Services.Catalog; 8 using Nop.Web.Framework.Controllers; 9 using System.Web.Mvc; 10 11 namespace Nop.Plugin.Other.ProductViewTracker.Controllers 12 { 13 public class TrackingController : BasePluginController 14 { 15 private readonly IProductService _productService; 16 private readonly IViewTrackingService _viewTrackingService; 17 private readonly IWorkContext _workContext; 18 19 public TrackingController(IWorkContext workContext, 20 IViewTrackingService viewTrackingService, 21 IProductService productService, 22 IPluginFinder pluginFinder) 23 { 24 _workContext = workContext; 25 _viewTrackingService = viewTrackingService; 26 _productService = productService; 27 } 28 29 [ChildActionOnly] 30 public ActionResult Index(int productId) 31 { 32 //Read from the product service 33 Product productById = _productService.GetProductById(productId); 34 35 //If the product exists we will log it 36 if (productById != null) 37 { 38 //Setup the product to save 39 var record = new TrackingRecord(); 40 record.ProductId = productId; 41 record.ProductName = productById.Name; 42 record.CustomerId = _workContext.CurrentCustomer.Id; 43 record.IpAddress = _workContext.CurrentCustomer.LastIpAddress; 44 record.IsRegistered = _workContext.CurrentCustomer.IsRegistered(); 45 46 //Map the values we're interested in to our new entity 47 _viewTrackingService.Log(record); 48 } 49 50 //Return the view, it doesn't need a model 51 return Content(''); 52 } 53 } 54 }9.实现路由接口。
1 using Nop.Web.Framework.Mvc.Routes; 2 using System.Web.Mvc; 3 using System.Web.Routing; 4 5 namespace Nop.Plugin.Other.ProductViewTracker 6 { 7 public class RouteProvider : IRouteProvider 8 { 9 public int Priority 10 { 11 get 12 { 13 return 0; 14 } 15 } 16 17 public void RegisterRoutes(RouteCollection routes) 18 { 19 routes.MapRoute('Nop.Plugin.Other.ProductViewTracker.Log', 20 'tracking/productviews/{productId}', 21 new { controller = 'Tracking', action = 'Index' }, 22 new[] { 'Nop.Plugin.Other.ProductViewTracker.Controllers' } 23 ); 24 } 25 } 26 }10.添加插件类,继承插件基类,重载安装和卸载方法。
1 using Nop.Core.Plugins; 2 using Nop.Plugin.Other.ProductViewTracker.Data; 3 4 namespace Nop.Plugin.Other.ProductViewTracker 5 { 6 public class ProductViewTrackerPlugin : BasePlugin 7 { 8 private readonly TrackingRecordObjectContext _context; 9 10 public ProductViewTrackerPlugin(TrackingRecordObjectContext context) 11 { 12 _context = context; 13 } 14 15 public override void Install() 16 { 17 _context.Install(); 18 base.Install(); 19 } 20 21 public override void Uninstall() 22 { 23 _context.Uninstall(); 24 base.Uninstall(); 25 } 26 } 27 }11.在NopCommerce的前台,加入插件的应用代码。这里,我们在页面Nop.WebViewsProductProductTemplate.Simple.cshtml中插入应用代码。
@Html.Action('Index', 'Tracking', new { productId = Model.Id })如图

相关热词:
本站内容来源于网络,如有侵权请与我们联系,我们会及时删除,我们深感抱歉!
注:本站所有信息仅供用于网络技术学习参考,学习中请遵循相关法律法规!
本文地址: https://v30.fanwenzhu.com/sql/mssql/12155.shtml
相关文章
热门TAG
win10 ecshop 主机 阿里云 解决 配置 C# C++ 解析 SQL语句 命令 Go语言 方法 CSS3 HTML5 CSS win7 MSSQL 服务器配置 IIS7.5 IIS7 IIS6 IIS CentOS 7 Linux oracle数据库 oracle phpcms discuz discuz教程最新文章
-
SQL基本教程之行转列Pivo
时间:2021-01-20
-
region from hr.Employees union
时间:2021-01-20
-
有时候需要调整用户权限
时间:2021-01-19
-
(但使用 ORDER BY 子句并不
时间:2021-01-19
-
RAND()*10000)insert into Detail
时间:2021-01-19
-
OR 运算符:在两侧的查询
时间:2021-01-19
-
放假之前老大跟我提起了
时间:2021-01-19
-
数据库的运维计策剧本篇
时间:2021-01-19
热门文章
-
4.与聚合函数和 GROUP BY 子句有关的常见错
时间:2021-01-19
-
SQL Server安全(11/11):审核(Auditing)
时间:2021-01-09
-
sqlserver中查询横表变竖表的sql语句简析
时间:2020-12-08
-
SQL Server简单模式下误删除堆表记录恢复方
时间:2020-12-12
-
关于SQL Server查询语句的使用
时间:2020-12-13
-
MSSQL教程_mssql数据库教程_MSSQL基础教程_第
时间:2020-12-13
-
jdbc连接sql server数据库问题分析
时间:2020-12-10
-
详解SQL游标的用法
时间:2020-12-27
-
sql server 关于设置null的一些建议
时间:2020-12-28
-
mssql关于一个表格结构的另外一种显示(表
时间:2020-12-11
