NopCommerce源码架构详解-教你写一个简单的NopCommerce插件2

上一篇文章写了要开发一个NopCommerce插件的基本准备工作。现在我们就来看看要让插件正常的显示到页面上还要需要做哪些呢?

NopCommerce源码架构详解概述

文章目录

概述

NopCommerce源码架构详解-教你写一个简单的NopCommerce插件2。

内容

上一篇文章写了要开发一个NopCommerce插件的基本准备工作。现在我们就来看看要让插件正常的显示到页面上还要需要做哪些呢?

1、检查mvc版本

首先要检查之前我们创建的项目nop].Plugin.Widgets.HelloWorld引用的MVC版本是否和Nop.Web的一致,如果更高或更低就要使用nuget安装相应的版本。我用的这个Nop源码在Nop.Web中使用的MVC版本是5.2.0,因此在我们的插件项目也要使用MVC的版本为5.2.0,不然最终调用插件时,运行的时候会报错的。

2、同理也要添加相应版本的Autofac和其它dll的引用,如下图,请依次对照检查。

2020-04-23-03-45-27

上面的引用可一个都不能少哦。

3、添加项目所需要文件夹和文件

添加好引用之后,我们就可以放心添加文件夹和类文件了。如下图:

2020-04-23-03-45-34

这是一个Nop插件规范的文件结构。Controllers、Models、Views这三个文件夹我想我不用说它们的作用,你懂得^_^。Infrastructure下面有一个DependencyRegistrar类它是用来做依赖注入了。这个类可以从其它插件中拷过来,做一些修改:

using Autofac;
using Autofac.Core;
using Nop.Core.Caching;
using Nop.Core.Infrastructure;
using Nop.Core.Infrastructure.DependencyManagement;
using Nop.Plugin.Widgets.HelloWorld.Controllers;

namespace Nop.Plugin.Widgets.HelloWorld.Infrastructure
{
    public class DependencyRegistrar : IDependencyRegistrar
    {
        public virtual void Register(ContainerBuilder builder, ITypeFinder typeFinder)
        {
            //we cache presentation models between requests
            //builder.RegisterType<WidgetsHelloWorldController>()
            //    .WithParameter(ResolvedParameter.ForNamed<ICacheManager>("nop_cache_static"));
        }

        public int Order
        {
            get { return 2; }
        }
    }
}

本例比较简单,还用不上高大上的依赖注入,所以把这个类的Register方法代码先注释掉。同样的Models下面的两个model分别是ConfigurationModel和PublicInfoModel也先不用管。因为本例先不用model传值到视图,就输出一段固定的html。

注意:打起精神来,下面可是这个插件的重头戏了。

WidgetsHelloWorldController.cs:

using System.Web.Mvc;
using Nop.Core;
using Nop.Core.Caching;
using Nop.Plugin.Widgets.HelloWorld.Infrastructure.Cache;
using Nop.Plugin.Widgets.HelloWorld.Models;
using Nop.Services.Configuration;
using Nop.Services.Media;
using Nop.Services.Stores;
using Nop.Web.Framework.Controllers;

namespace Nop.Plugin.Widgets.HelloWorld.Controllers
{
    public class WidgetsHelloWorldController : BasePluginController
    {
        public WidgetsHelloWorldController()
        {
        }

        [AdminAuthorize]
        [ChildActionOnly]
        public ActionResult Configure()
        {
            return View("~/Plugins/Widgets.HelloWorld/Views/WidgetsHelloWorld/Configure.cshtml");
        }

        [HttpPost]
        [AdminAuthorize]
        [ChildActionOnly]
        public ActionResult Configure(ConfigurationModel model)
        {
            return Configure();
        }

        [ChildActionOnly]
        public ActionResult PublicInfo(string widgetZone, object additionalData = null)
        {
            return View("~/Plugins/Widgets.HelloWorld/Views/WidgetsHelloWorld/PublicInfo.cshtml",null);
        }
    }
}

上面是控制器,也是提供给Nop调用的控制器,并返回相应的内容。我们可以看到上面有两个Action方法。Configure是插件配置用的,PublicInfo是用来前台显示用的。注意:这两个Action最后返回视图都是通过视图的全路径,不然到时是找不到视图文件的。 接下来来添加视图文件。

Configure.cshtml:

@{
    Layout = "";
}
@model Nop.Plugin.Widgets.HelloWorld.Models.ConfigurationModel
@using Nop.Web.Framework;
@using (Html.BeginForm())
{
    <table class="adminContent">
        <tr>
            <td colspan="2">
                <input type="submit" name="save" class="k-button" value="@T("Admin.Common.Save")" />
            </td>
        </tr>
    </table>
}

这里配置视图是随便写的,因为暂时还用不上。

PublicInfo.cshtml:

@model Nop.Plugin.Widgets.HelloWorld.Models.PublicInfoModel
@{
    Layout = "";

}
@using System
@using Nop.Web.Framework.UI

<div class="con" style="font-weight:bold; color:red;">
    <ul>
        <li>HelloWorld</li>
        <li>HelloWorld</li>
        <li>HelloWorld</li>
        <li>HelloWorld</li>
        <li>HelloWorld</li>
        <li>HelloWorld</li>
        <li>HelloWorld</li>
        <li>HelloWorld</li>
        <li>HelloWorld</li>
        <li>HelloWorld</li>
    </ul>
</div>

从上面的视图PublicInfo就可以看到我们这个插件是输出由div、ul、li 组成的几行HelloWorld,非常之简单。

然后,添加一个插件的核心类HelloWorldPlugin.cs,这个类要实现接口IWidgetPlugin和继承类BasePlugin。

HelloWorldPlugin.cs:

using System.Collections.Generic;
using System.IO;
using System.Web.Routing;
using Nop.Core;
using Nop.Core.Plugins;
using Nop.Services.Cms;
using Nop.Services.Configuration;
using Nop.Services.Localization;
using Nop.Services.Media;

namespace Nop.Plugin.Widgets.HelloWorld
{
    /// <summary>
    /// PLugin
    /// </summary>
    public class HelloWorldPlugin : BasePlugin, IWidgetPlugin
    {
        public HelloWorldPlugin()
        {

        }

        /// <summary>
        /// Gets widget zones where this widget should be rendered
        /// </summary>
        /// <returns>Widget zones</returns>
        public IList<string> GetWidgetZones()
        {
            return new List<string>() { "home_page_helloworld" };
        }

        /// <summary>
        /// Gets a route for provider configuration
        /// </summary>
        /// <param name="actionName">Action name</param>
        /// <param name="controllerName">Controller name</param>
        /// <param name="routeValues">Route values</param>
        public void GetConfigurationRoute(out string actionName, out string controllerName, out RouteValueDictionary routeValues)
        {
            actionName = "Configure";
            controllerName = "WidgetsHelloWorld";
            routeValues = new RouteValueDictionary() { { "Namespaces", "Nop.Plugin.Widgets.HelloWorld.Controllers" }, { "area", null } };
        }

        /// <summary>
        /// Gets a route for displaying widget
        /// </summary>
        /// <param name="widgetZone">Widget zone where it's displayed</param>
        /// <param name="actionName">Action name</param>
        /// <param name="controllerName">Controller name</param>
        /// <param name="routeValues">Route values</param>
        public void GetDisplayWidgetRoute(string widgetZone, out string actionName, out string controllerName, out RouteValueDictionary routeValues)
        {
            actionName = "PublicInfo";
            controllerName = "WidgetsHelloWorld";
            routeValues = new RouteValueDictionary()
            {
                {"Namespaces", "Nop.Plugin.Widgets.HelloWorld.Controllers"},
                {"area", null},
                {"widgetZone", widgetZone}
            };
        }

        /// <summary>
        /// Install plugin
        /// </summary>
        public override void Install()
        {
            base.Install();
        }

        /// <summary>
        /// Uninstall plugin
        /// </summary>
        public override void Uninstall()
        {
            base.Uninstall();
        }
    }
}

这个HelloWorldPlugin类定义了插件调用的名字为home_page_helloworld,通过GetWidgetZones属性调用,以及配置GetConfigurationRoute和前台显示GetDisplayWidgetRoute时的路由信息(Controller和Action相关)。除此之外还有插件的安装Install和卸载Uninstall操作。这里的插件安装和卸载直接调用的基类的方法,当然你也可以在里面写些你个性化的东西。

4、Web.Config配置

这一步也很关键,我就是之前没有注意这点,导致运行一直报下面的报错。这个问题还真浪费了朕一点点时间。^_^

当前上下文中不存在名称“model”

2020-04-23-03-45-44

后来找了原因,因为我当初创建的是一个类库项目,是插件项目中只有一个app.config,没有Web.config。于是我从项目Nop.Plugin.Widgets.NivoSlider中把它的Web.config拷过来,重新生成运行就没有问题。Web.config里面的pageBaseType很关键,如下图:

2020-04-23-03-45-52

5、安装插件并启用

在Nop后台安装插件并启用我们的插件。点击安装Intall插件之后会在\App_Data下面的InstalledPlugins.txt里面多上一行是我们的插件信息。你可以打开InstalledPlugins.txt检查一下。

2020-04-23-03-45-58

安装插件成功后,还要记得启用我们的插件哦,不然Nop是不会显示未被启用的插件的。

2020-04-23-03-46-06

6、调用插件

我们把这个HelloWorld插件显示在前台的首页上,看看效果。找到Nop.Web项目下的Views\Home\Index.cshtml,加上代码:@Html.Widget(home_page_helloworld)

2020-04-23-03-47-38

最后页面显示的效果如下:

2020-04-23-03-47-44

至此,一个很简单的NopCommerce插件就大功告成了。此时此刻,我相信你对Nop的插件开发有了一定的了解了,下次我会讲解一个复杂的例子,开发一个友情链接的Nop插件,可以在后台动态的添加数据。

原文出处:蓝狐软件工作室【蓝狐】

原文链接:http://m.lanhusoft.com/Article/349.html

本文观点不代表 .Net中文网 立场,转载请联系原作者。

发表评论

登录后才能评论