Development of nopCommerce 3.9 Big Wave Series Plug-ins Supporting Multi-stores
I. Basic Introduction
nop supports multi-stores and multi-languages. This article introduces how to develop multi-stores widgets with NivoSlider plug-ins.
The main interfaces are as follows:
ISettingService Interface: Setting up the interface can realize multi-store configuration.
ILocalizationService interface: Localized resource interface, with language, to achieve multi-language display.
Installation and uninstallation of plug-ins
In the previous article, we introduced how to use the widget (click) Here Here is how to install and uninstall plug-ins.

[Background Management] [Plug-in Management] [Local Plug-ins] can install and uninstall plug-ins
Nop.Admin.Controllers.PluginController controller is used for plug-in management. Install is responsible for installing plug-ins and Uninstall is responsible for uninstalling plug-ins.
All plug-ins inherit the IPlugin interface, Install(), Uninstall() for installation and uninstall, respectively.
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
The BasePlugin abstract class inherits the IPlugin interface and implements Install(), Uninstall() methods. When installed, it writes the System Name of the plug-in in the'~/App_Data/InstalledPlugins.txt'file and deletes it when uninstalled.
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
Let's see what the NivoSlider plug-in did when it was installed.

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
In the source code above, we see that the Install() method is invoked at installation time as follows
1. Define the NivoSliderSettings class, which inherits ISettings to save the configuration of slides. Save the initialized configuration to the database Setting table.
2. This. AddOrUpdate PluginLocaleResource method adds local resources, which are mainly used to configure resources for multilingual support.
3.base.Install() for plug-in installation.
Uninstall() method is called to delete configuration, delete local resources and uninstall plug-ins when uninstalling plug-ins.
The above is the introduction of the method invoked when the plug-in is installed and unloaded, and the configuration of the plug-in can be carried out at the relevant time points when the plug-in is redeveloped.
3. Plug-in Configuration Routing
Different plug-ins have their own configuration items. For example, Alipay plug-ins and WeChat payment plug-ins are both payment plug-ins, but the configuration is different. Configuration routing is introduced to implement different configurations. The widget IWidgetPlugin interface GetConfiguration Route method is used to return routing information for the configuration interface. Let's look at the NivoSlider plug-in
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 }
When you click on configuration, route to the Widgets NivoSlider controller Configure() method to display the plug-in configuration page

4. Realization of Multi-store Configuration

If more than two shopping malls are configured, there will be multiple stores above. Different configurations can be made for different stores.

1 [AdminAuthorize]
2 [ChildActionOnly]
3 public ActionResult Configure()
4 {
5 //Loading the scope of available stores
6 var storeScope = this.GetActiveStoreScopeConfiguration(_storeService, _workContext);
7 var nivoSliderSettings = _settingService.LoadSetting<NivoSliderSettings>(storeScope);//Load the configuration of available stores
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 }
Configure source code
Looking at the source code, we can see that these two sentences control the multi-store configuration.
1 //Loading the scope of available stores
2 var storeScope = this.GetActiveStoreScopeConfiguration(_storeService, _workContext);
3 var nivoSliderSettings = _settingService.LoadSetting<NivoSliderSettings>(storeScope);//Load the configuration of available stores
First load the currently configured store. Get the store Scope and load the settings for the store NivoSlider Setting configuration item.
In this way, when you choose different malls, you can get the value of the allocation in the selection mall.
Let's look at the Configure.cshtml view again
@Html.Action("StoreScopeConfiguration", "Setting", new { area = "Admin" })
The routing is used to generate nop multi-store setup module
Select different malls to call Setting Controller, ChangeStoreScopeConfiguration method, which saves the user's selected mall id in the GenericaAttribute table as shown below.

The SystemCustomerAttributeNames.AdminAreaStoreScopeConfiguration variable corresponds to the Key value, and Velue is saved as the Id of the mall.
When the page chooses different malls, after the processing of the above method, call var storeScope = this.GetActiveStoreScopeConfiguration(_storeService, _workContext); the method can get the designated mall.

When specifying a mall, we will find that there is an extra radio box for each item of the configuration item. If you choose, you can set the configuration for the mall. If you do not choose, you can use the default item.
How do I generate this single option in the view? Look at the source code
@Html.OverrideStoreCheckboxFor(model => model.Picture2Id_OverrideForStore, model => model.Picture2Id, Model.ActiveStoreScopeConfiguration)
The Html extension is used to customize the mall configuration. The OverrideStoreCheckbox For extension is an extension in the Nop.Web.Framework.HtmlExtensions class.
When model.Picture2Id_OverrideForStore is True, the custom mall configuration is used, model.Picture2Id is the configuration attribute, and model.ActiveStoreScopeConfiguration is the current mall id.
It can be seen that there are more ActiveStore Scope Configuration attributes for store id than normal model, and a bool method of _OverrideForStore for each attribute is used to determine whether the store default value is overwritten.

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">
199 <div class="panel-body">
200 <div class="form-group">
201 <div class="col-md-3">
202
203 </div>
204 <div class="col-md-9">
205 <input type="submit" name="save" class="btn bg-blue" value="@T("Admin.Common.Save")" />
206 </div>
207 </div>
208 </div>
209 </div>
210 </div>
211 }
Configuration view code
The _settingService.SaveSettingOverridablePerStore method is invoked when the configuration is submitted to save configuration support for multiple stores. _

1 [HttpPost]
2 [AdminAuthorize]
3 [ChildActionOnly]
4 public ActionResult Configure(ConfigurationModel model)
5 {
6 //load settings for a chosen store scope
7 var storeScope = this.GetActiveStoreScopeConfiguration(_storeService, _workContext);
8 var nivoSliderSettings = _settingService.LoadSetting<NivoSliderSettings>(storeScope);
9
10 //get previous picture identifiers
11 var previousPictureIds = new[]
12 {
13 nivoSliderSettings.Picture1Id,
14 nivoSliderSettings.Picture2Id,
15 nivoSliderSettings.Picture3Id,
16 nivoSliderSettings.Picture4Id,
17 nivoSliderSettings.Picture5Id
18 };
19
20 nivoSliderSettings.Picture1Id = model.Picture1Id;
21 nivoSliderSettings.Text1 = model.Text1;
22 nivoSliderSettings.Link1 = model.Link1;
23 nivoSliderSettings.Picture2Id = model.Picture2Id;
24 nivoSliderSettings.Text2 = model.Text2;
25 nivoSliderSettings.Link2 = model.Link2;
26 nivoSliderSettings.Picture3Id = model.Picture3Id;
27 nivoSliderSettings.Text3 = model.Text3;
28 nivoSliderSettings.Link3 = model.Link3;
29 nivoSliderSettings.Picture4Id = model.Picture4Id;
30 nivoSliderSettings.Text4 = model.Text4;
31 nivoSliderSettings.Link4 = model.Link4;
32 nivoSliderSettings.Picture5Id = model.Picture5Id;
33 nivoSliderSettings.Text5 = model.Text5;
34 nivoSliderSettings.Link5 = model.Link5;
35
36 /* We do not clear cache after each setting update.
37 * This behavior can increase performance because cached settings will not be cleared
38 * and loaded from database after each update */
39 _settingService.SaveSettingOverridablePerStore(nivoSliderSettings, x => x.Picture1Id, model.Picture1Id_OverrideForStore, storeScope, false);
40 _settingService.SaveSettingOverridablePerStore(nivoSliderSettings, x => x.Text1, model.Text1_OverrideForStore, storeScope, false);
41 _settingService.SaveSettingOverridablePerStore(nivoSliderSettings, x => x.Link1, model.Link1_OverrideForStore, storeScope, false);
42 _settingService.SaveSettingOverridablePerStore(nivoSliderSettings, x => x.Picture2Id, model.Picture2Id_OverrideForStore, storeScope, false);
43 _settingService.SaveSettingOverridablePerStore(nivoSliderSettings, x => x.Text2, model.Text2_OverrideForStore, storeScope, false);
44 _settingService.SaveSettingOverridablePerStore(nivoSliderSettings, x => x.Link2, model.Link2_OverrideForStore, storeScope, false);
45 _settingService.SaveSettingOverridablePerStore(nivoSliderSettings, x => x.Picture3Id, model.Picture3Id_OverrideForStore, storeScope, false);
46 _settingService.SaveSettingOverridablePerStore(nivoSliderSettings, x => x.Text3, model.Text3_OverrideForStore, storeScope, false);
47 _settingService.SaveSettingOverridablePerStore(nivoSliderSettings, x => x.Link3, model.Link3_OverrideForStore, storeScope, false);
48 _settingService.SaveSettingOverridablePerStore(nivoSliderSettings, x => x.Picture4Id, model.Picture4Id_OverrideForStore, storeScope, false);
49 _settingService.SaveSettingOverridablePerStore(nivoSliderSettings, x => x.Text4, model.Text4_OverrideForStore, storeScope, false);
50 _settingService.SaveSettingOverridablePerStore(nivoSliderSettings, x => x.Link4, model.Link4_OverrideForStore, storeScope, false);
51 _settingService.SaveSettingOverridablePerStore(nivoSliderSettings, x => x.Picture5Id, model.Picture5Id_OverrideForStore, storeScope, false);
52 _settingService.SaveSettingOverridablePerStore(nivoSliderSettings, x => x.Text5, model.Text5_OverrideForStore, storeScope, false);
53 _settingService.SaveSettingOverridablePerStore(nivoSliderSettings, x => x.Link5, model.Link5_OverrideForStore, storeScope, false);
54
55 //now clear settings cache
56 _settingService.ClearCache();
57
58 //get current picture identifiers
59 var currentPictureIds = new[]
60 {
61 nivoSliderSettings.Picture1Id,
62 nivoSliderSettings.Picture2Id,
63 nivoSliderSettings.Picture3Id,
64 nivoSliderSettings.Picture4Id,
65 nivoSliderSettings.Picture5Id
66 };
67
68 //delete an old picture (if deleted or updated)
69 foreach (var pictureId in previousPictureIds.Except(currentPictureIds))
70 {
71 var previousPicture = _pictureService.GetPictureById(pictureId);
72 if (previousPicture != null)
73 _pictureService.DeletePicture(previousPicture);
74 }
75
76 SuccessNotification(_localizationService.GetResource("Admin.Plugins.Saved"));
77 return Configure();
78 }
Submit configuration code
With so much verbosity, in fact, the same is true. Insert a record of Binding Mall Id in the Setting table as follows:
Name is the corresponding configuration field, Value is the value, StoreId is the mall id.
1.IPlugin interface, Install(), Uninstall() are used for installation and uninstall, respectively.
2.IWidgetPlugin Interface, GetConfiguration Route Method for Returning Routing Information of Configuration Interface
3. View @Html.Action ("StoreScope Configuration", "Setting", "New {area = Admin"}) for multi-store configuration
4. Multi-store property settings are extended with @Html.OverrideStoreCheckbox For.
5. Multi-store settings are saved using the SaveSettingOverridable PerStore method of the ISettingService interface.
Wrong understandings and incorrect opinions in this article, please correct, leave a message and share with us for common progress.
This article is originally created and reproduced by big waves. Please indicate the source.