nopCommerce 3.9 大波浪系列 之 開發支持多店的插件

来源:http://www.cnblogs.com/yaoshangjin/archive/2017/07/31/7264414.html
-Advertisement-
Play Games

nop支持多店,結合NivoSlider插件介紹下如何開發支持多商城的小部件 ...


一.基礎介紹

       nop支持多店及多語言,本篇結合NivoSlider插件介紹下如何開發支持多商城的小部件。

       主要介面如下:

ISettingService 介面:設置介面,可實現多店配置。

ILocalizationService 介面:本地化資源介面,配合語言,實現多語言的顯示。

二.插件安裝、卸載

      我們在上一篇介紹了小部件如何使用(點擊這裡),這裡介紹下如何安裝、卸載插件。

【後臺管理】【插件管理】【本地插件】可以對插件進行安裝、卸載

Nop.Admin.Controllers.PluginController控制器用於插件的管理。Install負責安裝插件、Uninstall負責卸載插件。

     所有插件都繼承IPlugin介面,Install(),Uninstall()分別用於安裝及卸載。

  1 namespace Nop.Core.Plugins
  2 {
  3     /// <summary>
  4     /// Interface denoting plug-in attributes that are displayed throughout 
  5     /// the editing interface.
  6     /// </summary>
  7     public interface IPlugin
  8     {
  9         /// <summary>
 10         /// Gets or sets the plugin descriptor
 11         /// </summary>
 12         PluginDescriptor PluginDescriptor { get; set; }
 13 
 14         /// <summary>
 15         /// Install plugin
 16         /// </summary>
 17         void Install();
 18 
 19         /// <summary>
 20         /// Uninstall plugin
 21         /// </summary>
 22         void Uninstall();
 23     }
 24 }
 25 

       BasePlugin抽象類繼承了IPlugin介面,並實現了 Install(),Uninstall()方法,當安裝時在"~/App_Data/InstalledPlugins.txt"文件中寫入插件的SystemName,卸載時則在文件中刪除。

  1 namespace Nop.Core.Plugins
  2 {
  3     /// <summary>
  4     /// Base plugin
  5     /// </summary>
  6     public abstract class BasePlugin : IPlugin
  7     {
  8         /// <summary>
  9         /// Gets or sets the plugin descriptor
 10         /// </summary>
 11         public virtual PluginDescriptor PluginDescriptor { get; set; }
 12 
 13         /// <summary>
 14         /// Install plugin
 15         /// </summary>
 16         public virtual void Install()
 17         {
 18             PluginManager.MarkPluginAsInstalled(this.PluginDescriptor.SystemName);
 19         }
 20 
 21         /// <summary>
 22         /// Uninstall plugin
 23         /// </summary>
 24         public virtual void Uninstall()
 25         {
 26             PluginManager.MarkPluginAsUninstalled(this.PluginDescriptor.SystemName);
 27         }
 28 
 29     }
 30 }
 31 

       我們看下NivoSlider插件在安裝時都做了哪些操作。

  1 using System.Collections.Generic;
  2 using System.IO;
  3 using System.Web.Routing;
  4 using Nop.Core;
  5 using Nop.Core.Plugins;
  6 using Nop.Services.Cms;
  7 using Nop.Services.Configuration;
  8 using Nop.Services.Localization;
  9 using Nop.Services.Media;
 10 
 11 namespace Nop.Plugin.Widgets.NivoSlider
 12 {
 13     /// <summary>
 14     /// PLugin
 15     /// </summary>
 16     public class NivoSliderPlugin : BasePlugin, IWidgetPlugin
 17     {
 18         private readonly IPictureService _pictureService;
 19         private readonly ISettingService _settingService;
 20         private readonly IWebHelper _webHelper;
 21 
 22         public NivoSliderPlugin(IPictureService pictureService,
 23             ISettingService settingService, IWebHelper webHelper)
 24         {
 25             this._pictureService = pictureService;
 26             this._settingService = settingService;
 27             this._webHelper = webHelper;
 28         }
 29 
 30         /// <summary>
 31         /// Gets widget zones where this widget should be rendered
 32         /// </summary>
 33         /// <returns>Widget zones</returns>
 34         public IList<string> GetWidgetZones()
 35         {
 36             return new List<string> { "home_page_top" };
 37         }
 38 
 39         /// <summary>
 40         /// Gets a route for provider configuration
 41         /// </summary>
 42         /// <param name="actionName">Action name</param>
 43         /// <param name="controllerName">Controller name</param>
 44         /// <param name="routeValues">Route values</param>
 45         public void GetConfigurationRoute(out string actionName, out string controllerName, out RouteValueDictionary routeValues)
 46         {
 47             actionName = "Configure";
 48             controllerName = "WidgetsNivoSlider";
 49             routeValues = new RouteValueDictionary { { "Namespaces", "Nop.Plugin.Widgets.NivoSlider.Controllers" }, { "area", null } };
 50         }
 51 
 52         /// <summary>
 53         /// Gets a route for displaying widget
 54         /// </summary>
 55         /// <param name="widgetZone">Widget zone where it's displayed</param>
 56         /// <param name="actionName">Action name</param>
 57         /// <param name="controllerName">Controller name</param>
 58         /// <param name="routeValues">Route values</param>
 59         public void GetDisplayWidgetRoute(string widgetZone, out string actionName, out string controllerName, out RouteValueDictionary routeValues)
 60         {
 61             actionName = "PublicInfo";
 62             controllerName = "WidgetsNivoSlider";
 63             routeValues = new RouteValueDictionary
 64             {
 65                 {"Namespaces", "Nop.Plugin.Widgets.NivoSlider.Controllers"},
 66                 {"area", null},
 67                 {"widgetZone", widgetZone}
 68             };
 69         }
 70 
 71         /// <summary>
 72         /// Install plugin
 73         /// </summary>
 74         public override void Install()
 75         {
 76             //pictures
 77             var sampleImagesPath = CommonHelper.MapPath("~/Plugins/Widgets.NivoSlider/Content/nivoslider/sample-images/");
 78 
 79 
 80             //settings
 81             var settings = new NivoSliderSettings
 82             {
 83                 Picture1Id = _pictureService.InsertPicture(File.ReadAllBytes(sampleImagesPath + "banner1.jpg"), MimeTypes.ImagePJpeg, "banner_1").Id,
 84                 Text1 = "",
 85                 Link1 = _webHelper.GetStoreLocation(false),
 86                 Picture2Id = _pictureService.InsertPicture(File.ReadAllBytes(sampleImagesPath + "banner2.jpg"), MimeTypes.ImagePJpeg, "banner_2").Id,
 87                 Text2 = "",
 88                 Link2 = _webHelper.GetStoreLocation(false),
 89                 //Picture3Id = _pictureService.InsertPicture(File.ReadAllBytes(sampleImagesPath + "banner3.jpg"), MimeTypes.ImagePJpeg, "banner_3").Id,
 90                 //Text3 = "",
 91                 //Link3 = _webHelper.GetStoreLocation(false),
 92             };
 93             _settingService.SaveSetting(settings);
 94 
 95 
 96             this.AddOrUpdatePluginLocaleResource("Plugins.Widgets.NivoSlider.Picture1", "Picture 1");
 97             this.AddOrUpdatePluginLocaleResource("Plugins.Widgets.NivoSlider.Picture2", "Picture 2");
 98             this.AddOrUpdatePluginLocaleResource("Plugins.Widgets.NivoSlider.Picture3", "Picture 3");
 99             this.AddOrUpdatePluginLocaleResource("Plugins.Widgets.NivoSlider.Picture4", "Picture 4");
100             this.AddOrUpdatePluginLocaleResource("Plugins.Widgets.NivoSlider.Picture5", "Picture 5");
101             this.AddOrUpdatePluginLocaleResource("Plugins.Widgets.NivoSlider.Picture", "Picture");
102             this.AddOrUpdatePluginLocaleResource("Plugins.Widgets.NivoSlider.Picture.Hint", "Upload picture.");
103             this.AddOrUpdatePluginLocaleResource("Plugins.Widgets.NivoSlider.Text", "Comment");
104             this.AddOrUpdatePluginLocaleResource("Plugins.Widgets.NivoSlider.Text.Hint", "Enter comment for picture. Leave empty if you don't want to display any text.");
105             this.AddOrUpdatePluginLocaleResource("Plugins.Widgets.NivoSlider.Link", "URL");
106             this.AddOrUpdatePluginLocaleResource("Plugins.Widgets.NivoSlider.Link.Hint", "Enter URL. Leave empty if you don't want this picture to be clickable.");
107 
108             base.Install();
109         }
110 
111         /// <summary>
112         /// Uninstall plugin
113         /// </summary>
114         public override void Uninstall()
115         {
116             //settings
117             _settingService.DeleteSetting<NivoSliderSettings>();
118 
119             //locales
120             this.DeletePluginLocaleResource("Plugins.Widgets.NivoSlider.Picture1");
121             this.DeletePluginLocaleResource("Plugins.Widgets.NivoSlider.Picture2");
122             this.DeletePluginLocaleResource("Plugins.Widgets.NivoSlider.Picture3");
123             this.DeletePluginLocaleResource("Plugins.Widgets.NivoSlider.Picture4");
124             this.DeletePluginLocaleResource("Plugins.Widgets.NivoSlider.Picture5");
125             this.DeletePluginLocaleResource("Plugins.Widgets.NivoSlider.Picture");
126             this.DeletePluginLocaleResource("Plugins.Widgets.NivoSlider.Picture.Hint");
127             this.DeletePluginLocaleResource("Plugins.Widgets.NivoSlider.Text");
128             this.DeletePluginLocaleResource("Plugins.Widgets.NivoSlider.Text.Hint");
129             this.DeletePluginLocaleResource("Plugins.Widgets.NivoSlider.Link");
130             this.DeletePluginLocaleResource("Plugins.Widgets.NivoSlider.Link.Hint");
131 
132             base.Uninstall();
133         }
134     }
135 }
136 
Nop.Plugin.Widgets.NivoSlider

     在上邊源代碼中我們看到安裝時調用Install()方法進行瞭如下操作

1.定義NivoSliderSettings類,該類繼承ISettings,用於保存幻燈片的配置。將初始化的配置保存到資料庫Setting表中。

2.this.AddOrUpdatePluginLocaleResource方法添加本地資源,主要用於配置資源在多語言支持。

3.base.Install() 進行插件安裝。

     卸載插件時調用Uninstall()方法對配置進行刪除,對本地資源進行刪除同時卸載插件。

     以上就是在插件安裝、卸載時調用的方法介紹,在二次開發時可在相關時間點進行插件的配置。

三.插件配置路由

      不同插件有屬於自己的配置項,例如支付寶插件和微信支付插件同是支付插件但是配置卻不一樣。為了實現不同配置引入了配置路由。小部件IWidgetPlugin介面GetConfigurationRoute方法用於返回配置介面的路由信息。我們看下NivoSlider插件

  1    /// <summary>
  2         /// Gets a route for provider configuration
  3         /// </summary>
  4         /// <param name="actionName">Action name</param>
  5         /// <param name="controllerName">Controller name</param>
  6         /// <param name="routeValues">Route values</param>
  7         public void GetConfigurationRoute(out string actionName, out string controllerName, out RouteValueDictionary routeValues)
  8         {
  9             actionName = "Configure";
 10             controllerName = "WidgetsNivoSlider";
 11             routeValues = new RouteValueDictionary { { "Namespaces", "Nop.Plugin.Widgets.NivoSlider.Controllers" }, { "area", null } };
 12         }

      當點擊配置時路由到WidgetsNivoSlider控制器Configure()方法,顯示插件配置頁面

C08]NI@_X%HO_J$H{VC$B53

四.多店配置實現

MYRGDJGMO~MSD@G{MC6$YEO

如果配置了兩個以上的商城就會出現上邊的多店設置。可針對不同商店進行不同的配置。

  1 [AdminAuthorize]
  2         [ChildActionOnly]
  3         public ActionResult Configure()
  4         {
  5             //載入可用商店的範圍
  6             var storeScope = this.GetActiveStoreScopeConfiguration(_storeService, _workContext);
  7             var nivoSliderSettings = _settingService.LoadSetting<NivoSliderSettings>(storeScope);//載入可用商店的配置
  8             var model = new ConfigurationModel();
  9             model.Picture1Id = nivoSliderSettings.Picture1Id;
 10             model.Text1 = nivoSliderSettings.Text1;
 11             model.Link1 = nivoSliderSettings.Link1;
 12             model.Picture2Id = nivoSliderSettings.Picture2Id;
 13             model.Text2 = nivoSliderSettings.Text2;
 14             model.Link2 = nivoSliderSettings.Link2;
 15             model.Picture3Id = nivoSliderSettings.Picture3Id;
 16             model.Text3 = nivoSliderSettings.Text3;
 17             model.Link3 = nivoSliderSettings.Link3;
 18             model.Picture4Id = nivoSliderSettings.Picture4Id;
 19             model.Text4 = nivoSliderSettings.Text4;
 20             model.Link4 = nivoSliderSettings.Link4;
 21             model.Picture5Id = nivoSliderSettings.Picture5Id;
 22             model.Text5 = nivoSliderSettings.Text5;
 23             model.Link5 = nivoSliderSettings.Link5;
 24             model.ActiveStoreScopeConfiguration = storeScope;
 25             if (storeScope > 0)
 26             {
 27                 model.Picture1Id_OverrideForStore = _settingService.SettingExists(nivoSliderSettings, x => x.Picture1Id, storeScope);
 28                 model.Text1_OverrideForStore = _settingService.SettingExists(nivoSliderSettings, x => x.Text1, storeScope);
 29                 model.Link1_OverrideForStore = _settingService.SettingExists(nivoSliderSettings, x => x.Link1, storeScope);
 30                 model.Picture2Id_OverrideForStore = _settingService.SettingExists(nivoSliderSettings, x => x.Picture2Id, storeScope);
 31                 model.Text2_OverrideForStore = _settingService.SettingExists(nivoSliderSettings, x => x.Text2, storeScope);
 32                 model.Link2_OverrideForStore = _settingService.SettingExists(nivoSliderSettings, x => x.Link2, storeScope);
 33                 model.Picture3Id_OverrideForStore = _settingService.SettingExists(nivoSliderSettings, x => x.Picture3Id, storeScope);
 34                 model.Text3_OverrideForStore = _settingService.SettingExists(nivoSliderSettings, x => x.Text3, storeScope);
 35                 model.Link3_OverrideForStore = _settingService.SettingExists(nivoSliderSettings, x => x.Link3, storeScope);
 36                 model.Picture4Id_OverrideForStore = _settingService.SettingExists(nivoSliderSettings, x => x.Picture4Id, storeScope);
 37                 model.Text4_OverrideForStore = _settingService.SettingExists(nivoSliderSettings, x => x.Text4, storeScope);
 38                 model.Link4_OverrideForStore = _settingService.SettingExists(nivoSliderSettings, x => x.Link4, storeScope);
 39                 model.Picture5Id_OverrideForStore = _settingService.SettingExists(nivoSliderSettings, x => x.Picture5Id, storeScope);
 40                 model.Text5_OverrideForStore = _settingService.SettingExists(nivoSliderSettings, x => x.Text5, storeScope);
 41                 model.Link5_OverrideForStore = _settingService.SettingExists(nivoSliderSettings, x => x.Link5, storeScope);
 42             }
 43 
 44             return View("~/Plugins/Widgets.NivoSlider/Views/Configure.cshtml", model);
 45         }
配置源碼

查看源碼我們會發現這兩句是控制多店配置的

  1  //載入可用商店的範圍
  2  var storeScope = this.GetActiveStoreScopeConfiguration(_storeService, _workContext);
  3  var nivoSliderSettings = _settingService.LoadSetting<NivoSliderSettings>(storeScope);//載入可用商店的配置

首先載入當前配置的商店。獲取到 storeScope後載入該商店NivoSliderSetting配置項的設置。

這樣當選擇不同的商城就可以獲取到選擇商城中配置的值了。

     我們再來看下Configure.cshtml視圖

     @Html.Action("StoreScopeConfiguration", "Setting", new { area = "Admin" })

     該路由用於生成nop多店設置模塊image,選擇不同商城會調用Setting控制器,ChangeStoreScopeConfiguration方法,該方法會將用戶選擇的商城id 保存在GenericaAttribute表中如下圖。

(IDL)4E2P@]U8JOP_628@)I

     SystemCustomerAttributeNames.AdminAreaStoreScopeConfiguration變數對應的就是Key值,Velue保存為商城的Id。

當頁面選擇不同的商城時,經過上邊方法的處理,再調用var storeScope = this.GetActiveStoreScopeConfiguration(_storeService, _workContext); 方法就可以獲取到指定的商城了。

     image

當指定商城時我們會發現配置項每一項都多出一個單選框,選擇則可針對該商城的該配置經進行設置,如果不選擇則使用預設項。

在視圖中如何生成這個單選項呢?看下源碼

@Html.OverrideStoreCheckboxFor(model => model.Picture2Id_OverrideForStore, model => model.Picture2Id, Model.ActiveStoreScopeConfiguration)

使用該Html擴展來實現商城配置的定製。OverrideStoreCheckboxFor擴展是Nop.Web.Framework.HtmlExtensions 類中的擴展。

model.Picture2Id_OverrideForStore為True時使用自定義商城配置,model.Picture2Id為配置屬性,model.ActiveStoreScopeConfiguration為當前商城id。

可以看出支持多店配置的model比普通model多出ActiveStoreScopeConfiguration屬性用於保存商城id,同時每個屬性多一個_OverrideForStore的bool方法用於判斷是否覆蓋店鋪預設值。

  1 @{
  2     Layout = "";
  3 }
  4 @model Nop.Plugin.Widgets.NivoSlider.Models.ConfigurationModel
  5 @using Nop.Web.Framework;
  6 
  7 @Html.Action("StoreScopeConfiguration", "Setting", new { area = "Admin" })
  8 
  9 @using (Html.BeginForm())
 10 {
 11     @Html.AntiForgeryToken()
 12     <div class="panel-group">
 13         <div class="panel panel-default">
 14             <div class="panel-heading">
 15                 @T("Plugins.Widgets.NivoSlider.Picture1")
 16             </div>
 17             <div class="panel-body">
 18                 <div class="form-group">
 19                     <div class="col-md-3">
 20                         @Html.OverrideStoreCheckboxFor(model => model.Picture1Id_OverrideForStore, model => model.Picture1Id, Model.ActiveStoreScopeConfiguration)
 21                         @Html.NopLabelFor(model => model.Picture1Id)
 22                     </div>
 23                     <div class="col-md-9">
 24                         @Html.NopEditorFor(model => model.Picture1Id)
 25                         @Html.ValidationMessageFor(model => model.Picture1Id)
 26                     </div>
 27                 </div>
 28                 <div class="form-group">
 29                     <div class="col-md-3">
 30                         @Html.OverrideStoreCheckboxFor(model => model.Text1_OverrideForStore, model => model.Text1, Model.ActiveStoreScopeConfiguration)
 31                         @Html.NopLabelFor(model => model.Text1)
 32                     </div>
 33                     <div class="col-md-9">
 34                         @Html.NopEditorFor(model => model.Text1)
 35                         @Html.ValidationMessageFor(model => model.Text1)
 36                     </div>
 37                 </div>
 38                 <div class="form-group">
 39                     <div class="col-md-3">
 40                         @Html.OverrideStoreCheckboxFor(model => model.Link1_OverrideForStore, model => model.Link1, Model.ActiveStoreScopeConfiguration)
 41                         @Html.NopLabelFor(model => model.Link1)
 42                     </div>
 43                     <div class="col-md-9">
 44                         @Html.NopEditorFor(model => model.Link1)
 45                         @Html.ValidationMessageFor(model => model.Link1)
 46                     </div>
 47                 </div>
 48             </div>
 49         </div>
 50         <div class="panel panel-default">
 51             <div class="panel-heading">
 52                 @T("Plugins.Widgets.NivoSlider.Picture2")
 53             </div>
 54             <div class="panel-body">
 55                 <div class="form-group">
 56                     <div class="col-md-3">
 57                         @Html.OverrideStoreCheckboxFor(model => model.Picture2Id_OverrideForStore, model => model.Picture2Id, Model.ActiveStoreScopeConfiguration)
 58                         @Html.NopLabelFor(model => model.Picture2Id)
 59                     </div>
 60                     <div class="col-md-9">
 61                         @Html.NopEditorFor(model => model.Picture2Id)
 62                         @Html.ValidationMessageFor(model => model.Picture2Id)
 63                     </div>
 64                 </div>
 65                 <div class="form-group">
 66                     <div class="col-md-3">
 67                         @Html.OverrideStoreCheckboxFor(model => model.Text2_OverrideForStore, model => model.Text2, Model.ActiveStoreScopeConfiguration)
 68                         @Html.NopLabelFor(model => model.Text2)
 69                     </div>
 70                     <div class="col-md-9">
 71                         @Html.NopEditorFor(model => model.Text2)
 72                         @Html.ValidationMessageFor(model => model.Text2)
 73                     </div>
 74                 </div>
 75                 <div class="form-group">
 76                     <div class="col-md-3">
 77                         @Html.OverrideStoreCheckboxFor(model => model.Link2_OverrideForStore, model => model.Link2, Model.ActiveStoreScopeConfiguration)
 78                         @Html.NopLabelFor(model => model.Link2)
 79                     </div>
 80                     <div class="col-md-9">
 81                         @Html.NopEditorFor(model => model.Link2)
 82                         @Html.ValidationMessageFor(model => model.Link2)
 83                     </div>
 84                 </div>
 85             </div>
 86         </div>
 87         <div class="panel panel-default">
 88             <div class="panel-heading">
 89                 @T("Plugins.Widgets.NivoSlider.Picture3")
 90             </div>
 91             <div class="panel-body">
 92                 <div class="form-group">
 93                     <div class="col-md-3">
 94                         @Html.OverrideStoreCheckboxFor(model => model.Picture3Id_OverrideForStore, model => model.Picture3Id, Model.ActiveStoreScopeConfiguration)
 95                         @Html.NopLabelFor(model => model.Picture3Id)
 96                     </div>
 97                     <div class="col-md-9">
 98                         @Html.NopEditorFor(model => model.Picture3Id)
 99                         @Html.ValidationMessageFor(model => model.Picture3Id)
100                     </div>
101                 </div>
102                 <div class="form-group">
103                     <div class="col-md-3">
104                         @Html.OverrideStoreCheckboxFor(model => model.Text3_OverrideForStore, model => model.Text3, Model.ActiveStoreScopeConfiguration)
105                         @Html.NopLabelFor(model => model.Text3)
106                     </div>
107                     <div class="col-md-9">
108                         @Html.NopEditorFor(model => model.Text3)
109                         @Html.ValidationMessageFor(model => model.Text3)
110                     </div>
111                 </div>
112                 <div class="form-group">
113                     <div class="col-md-3">
114                         @Html.OverrideStoreCheckboxFor(model => model.Link3_OverrideForStore, model => model.Link3, Model.ActiveStoreScopeConfiguration)
115                         @Html.NopLabelFor(model => model.Link3)
116                     </div>
117                     <div class="col-md-9">
118                         @Html.NopEditorFor(model => model.Link3)
119                         @Html.ValidationMessageFor(model => model.Link3)
120                     </div>
121                 </div>
122             </div>
123         </div>
124         <div class="panel panel-default">
125             <div class="panel-heading">
126                 @T("Plugins.Widgets.NivoSlider.Picture4")
127             </div>
128             <div class="panel-body">
129                 <div class="form-group">
130                     <div class="col-md-3">
131                         @Html.OverrideStoreCheckboxFor(model => model.Picture4Id_OverrideForStore, model => model.Picture4Id, Model.ActiveStoreScopeConfiguration)
132                         @Html.NopLabelFor(model => model.Picture4Id)
133                     </div>
134                     <div class="col-md-9">
135                         @Html.NopEditorFor(model => model.Picture4Id)
136                         @Html.ValidationMessageFor(model => model.Picture4Id)
137                     </div>
138                 </div>
139                 <div class="form-group">
140                     <div class="col-md-3">
141                         @Html.OverrideStoreCheckboxFor(model => model.Text4_OverrideForStore, model => model.Text4, Model.ActiveStoreScopeConfiguration)
142                         @Html.NopLabelFor(model => model.Text4)
143                     </div>
144                     <div class="col-md-9">
145                         @Html.NopEditorFor(model => model.Text4)
146                         @Html.ValidationMessageFor(model => model.Text4)
147                     </div>
148                 </div>
149                 <div class="form-group">
150                     <div class="col-md-3">
151                         @Html.OverrideStoreCheckboxFor(model => model.Link4_OverrideForStore, model => model.Link4, Model.ActiveStoreScopeConfiguration)
152                         @Html.NopLabelFor(model => model.Link4)
153                     </div>
154                     <div class="col-md-9">
155                         @Html.NopEditorFor(model => model.Link4)
156                         @Html.ValidationMessageFor(model => model.Link4)
157                     </div>
158                 </div>
159             </div>
160         </div>
161         <div class="panel panel-default">
162             <div class="panel-heading">
163                 @T("Plugins.Widgets.NivoSlider.Picture5")
164             </div>
165             <div class="panel-body">
166                 <div class="form-group">
167                     <div class="col-md-3">
168                         @Html.OverrideStoreCheckboxFor(model => model.Picture5Id_OverrideForStore, model => model.Picture5Id, Model.ActiveStoreScopeConfiguration)
169                         @Html.NopLabelFor(model => model.Picture5Id)
170                     </div>
171                     <div class="col-md-9">
172                         @Html.NopEditorFor(model => model.Picture5Id)
173                         @Html.ValidationMessageFor(model => model.Picture5Id)
174                     </div>
175                 </div>
176                 <div class="form-group">
177                     <div class="col-md-3">
178                         @Html.OverrideStoreCheckboxFor(model => model.Text5_OverrideForStore, model => model.Text5, Model.ActiveStoreScopeConfiguration)
179                         @Html.NopLabelFor(model => model.Text5)
180                     </div>
181                     <div class="col-md-9">
182                         @Html.NopEditorFor(model => model.Text5)
183                         @Html.ValidationMessageFor(model => model.Text5)
184                     </div>
185                 </div>
186                 <div class="form-group">
187                     <div class="col-md-3">
188                         @Html.OverrideStoreCheckboxFor(model => model.Link5_OverrideForStore, model => model.Link5, Model.ActiveStoreScopeConfiguration)
189                         @Html.NopLabelFor(model => model.Link5)
190                     </div>
191                     <div class="col-md-9">
192                         @Html.NopEditorFor(model => model.Link5)
193                         @Html.ValidationMessageFor(model => model.Link5)
194                     </div>
195                 </div>
196             </div>
197         </div>
198         <div class="panel panel-default">
	   

您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • Linux 操作系統的網卡設備的傳統命名方式是 eth0、eth1、eth2等,而 CentOS7 提供了不同的命名規則,預設是基於固件、拓撲、位置信息來分配。這樣做的優點是命名全自動的、可預知的,缺點是比 eth0、wlan0 更難讀,比如 ens33 。 一、命名規則策略 規則1: 對於板載設備 ...
  • VIm配置及使用筆記 ============================= 安裝 apt get install vim y 配置說明 vim /etc/vim/vimrc 在配置文件後加入這些配置項 使用說明 編輯模式 一般模式 + 跳轉行 + 移動游標 + 撤銷與恢復 + 複製與粘貼 命令 ...
  • 一.環境:發行版本:ubuntu 14.04 64bit 二.獲取要指定的用戶及組id 使用id命令 (筆者獲取的uid和gid都為1000) 三.獲取識別的硬碟路徑 sudo fdisk -l (筆者獲取的路徑是/dev/sdb1) 四.掛載 sudo mount /dev/sdb1 /media ...
  • 說明:本文示例使用的VS2017和MVC5。 系統無論大小、牛逼或屌絲,一般都離不開註冊、登錄。那麼接下來我們就來分析下用戶身份認證。 簡單實現登錄、註銷 以前在學習.net的時候不知道什麼Forms身份認證,直接用session實現登錄,效果也蠻好嘛。而且用戶信息存在服務端,安全。 前端代碼: 後 ...
  • 之前調用 WebService 都是直接添加服務引用,然後調用 WebService 方法的,最近發現還可以使用 Http 請求調用 WebService。這裡還想說一句,還是 web api 的調用簡單。 WebService 服務端代碼: 很簡單的代碼,只是用於演示。 客戶端調用代碼: 第一種讀 ...
  • IdentityServer4 是一個提供 認證服務,單點登錄/登出(SSO),API訪問控制,聯合認證通道的可定製、免費商業支持的框架。 ...
  • 異常簡介 C sharp中的異常用於處理系統級和應用程式級的錯誤狀態,它是一種結構化、統一的類型安全的處理機制。異常處理相對於返回錯誤代碼的一個最大優點在於,異常可以被自動傳遞,這樣,在編程時異常更加難以被忽視。 C#的異常機制非常類似於C++的異常處理機制,但是還是有一些重要的區別: 1,在C#中 ...
  • 安裝過程就簡單帶過: 1. 在看代碼前,我們需要將NpgSql和Petapoco 載入到當前項目中來,我將使用Nuget來添加到當前項目,分別如下: 2.下麵看一下Web.config中的重要代碼 1>資料庫連接字元串 2>NpgSql驅動配置文件 3.將 Npgsql.dll和 Mono.Secu ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...