nopcommerce的挂件技术之二

上一篇新建了一个插件的demo(http://www.cnblogs.com/SecondSun/p/7422036.html),里面还有些问题没讲清楚,这篇,我将详细的讲解下。

关于 “ @Html.Widget("home_page_helloworld")”这个问题,这里面的参数需要和plugin中GetWidgetZones返回参数一致,否则无法加载插件。这个“home_page_helloworld”相当于一个ID,区分不同的插件,下面,我们来了解下是如何实现的。

首先@Html.Widget是HtmlHelper方法的扩展,代码如下:

  public static MvcHtmlString Widget(this HtmlHelper helper, string widgetZone, object additionalData = null, string area = null)
        {
            return helper.Action("WidgetsByZone", "Widget", new { widgetZone = widgetZone, additionalData = additionalData, area = area });
            //return helper.Action("WidgetsByZone", "Home", new { widgetZone = widgetZone, additionalData = additionalData, area = area });
        }

可以看到,该方法主要是调用“WidgetController”中的“WidgetsByZone”方法,真正的处理逻辑也是在这里的。具体的实现:

 1  [ChildActionOnly]
 2         public ActionResult WidgetsByZone(string widgetZone, object additionalData = null)
 3         {
 4             var cacheKey = string.Format(ModelCacheEventConsumer.WIDGET_MODEL_KEY, widgetZone);
 5             var cacheModel = _cacheManager.Get(cacheKey, () =>
 6             {
 7                 //model
 8                 var model = new List<RenderWidgetModel>();
 9 
10                 var widgets = _widgetService.LoadActiveWidgetsByWidgetZone(widgetZone);
11                 foreach (var widget in widgets)
12                 {
13                     var widgetModel = new RenderWidgetModel();
14 
15                     string actionName;
16                     string controllerName;
17                     RouteValueDictionary routeValues;
18                     widget.GetDisplayWidgetRoute(widgetZone, out actionName, out controllerName, out routeValues);
19                     widgetModel.ActionName = actionName;
20                     widgetModel.ControllerName = controllerName;
21                     widgetModel.RouteValues = routeValues;
22 
23                     model.Add(widgetModel);
24                 }
25                 return model;
26             });
27 
28             //如果没有Model返回为空字符串
29             if (!cacheModel.Any())
30                 return Content("");
34             var clonedModel = new List<RenderWidgetModel>();
35             foreach (var widgetModel in cacheModel)
36             {
37                 var clonedWidgetModel = new RenderWidgetModel();
38                 clonedWidgetModel.ActionName = widgetModel.ActionName;
39                 clonedWidgetModel.ControllerName = widgetModel.ControllerName;
40                 if (widgetModel.RouteValues != null)
41                     clonedWidgetModel.RouteValues = new RouteValueDictionary(widgetModel.RouteValues);
42 
43                 if (additionalData != null)
44                 {
45                     if (clonedWidgetModel.RouteValues == null)
46                         clonedWidgetModel.RouteValues = new RouteValueDictionary();
47                     clonedWidgetModel.RouteValues.Add("additionalData", additionalData);
48                 }
49 
50                 clonedModel.Add(clonedWidgetModel);
51             }
52 
53             return PartialView(clonedModel);
54         }

首先,根据键值对从缓存中读取数据,如果缓存中没有,则根据名称查找活动的组件LoadActiveWidgetsByWidgetZone(widgetZone)。查找返回实体。最后,我们需要在修改之前克隆缓存的模型(更新的模型不应被缓存),返回克隆的模型。

WidgetsByZone的视图如下所示:

@model List<RenderWidgetModel>
@using NopFramework.Web.Models.Cms;
@foreach (var widget in Model)
{
    @Html.Action(widget.ActionName, widget.ControllerName, widget.RouteValues)
}

遍历Model中的数据,并执行widget中指定Controller中的Action。该例子中的action、controller分别对应PublicInfo和WidgetsHelloWorld即直接加载插件,执行publicInfo方法,这样插件就显示出来了。

posted @ 2017-08-24 14:51  波峰浪尖  阅读(250)  评论(0编辑  收藏  举报