上一篇新建了一個插件的demo(http://www.cnblogs.com/SecondSun/p/7422036.html),裏面還有些問題沒講清楚,這篇,我將詳細的講解下。html
關於 「 @Html.Widget("home_page_helloworld")」這個問題,這裏面的參數須要和plugin中GetWidgetZones返回參數一致,不然沒法加載插件。這個「home_page_helloworld」至關於一個ID,區分不一樣的插件,下面,咱們來了解下是如何實現的。緩存
首先@Html.Widget是HtmlHelper方法的擴展,代碼以下:this
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」方法,真正的處理邏輯也是在這裏的。具體的實現:spa
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的視圖以下所示:code
@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方法,這樣插件就顯示出來了。orm