Error executing template "Designs/Swift/eCom/CustomerExperienceCenter/Favorites/FavoriteLists.cshtml"
System.NullReferenceException: Object reference not set to an instance of an object.
at CompiledRazorTemplates.Dynamic.RazorEngine_5ba7c945399b4afead2ef0e005eb9f76.Execute() in D:\dynamicweb.net\Solutions\Dynamicweb\dynamicwebdemo.dwsales.dynamicweb-cms.com\files\Templates\Designs\Swift\eCom\CustomerExperienceCenter\Favorites\FavoriteLists.cshtml:line 216
at RazorEngine.Templating.TemplateBase.RazorEngine.Templating.ITemplate.Run(ExecuteContext context, TextWriter reader)
at RazorEngine.Templating.RazorEngineService.RunCompile(ITemplateKey key, TextWriter writer, Type modelType, Object model, DynamicViewBag viewBag)
at RazorEngine.Templating.RazorEngineServiceExtensions.<>c__DisplayClass16_0.<RunCompile>b__0(TextWriter writer)
at RazorEngine.Templating.RazorEngineServiceExtensions.WithWriter(Action`1 withWriter)
at Dynamicweb.Rendering.RazorTemplateRenderingProvider.Render(Template template)
at Dynamicweb.Rendering.TemplateRenderingService.Render(Template template)
at Dynamicweb.Rendering.Template.RenderRazorTemplate()
1 @inherits ViewModelTemplate<FavoriteListListViewModel>
2 @using Dynamicweb.Rendering
3 @using Dynamicweb.Ecommerce.Frontend
4
5 @{
6 var themeRaw = Pageview.CurrentParagraph.Item["Theme"]?.ToString();
7 string theme = !string.IsNullOrEmpty(themeRaw) ? " h-100 theme " + themeRaw.Replace(" ", "").Trim().ToLower() : "";
8 }
9
10 @if (theme != "") {
11 <div class="@(theme)">
12 @RenderContent()
13 </div>
14 } else {
15 @RenderContent()
16 }
17
18 @helper RenderContent() {
19 string listPageLink = Pageview.CurrentParagraph.Item["ProductListPage"] != null ? Pageview.CurrentParagraph.Item["ProductListPage"].ToString() : "";
20 string currentPageUrl = "/Default.aspx?ID=" + Pageview.Page.ID;
21 int listsCount = Model.TotalFavoriteListsCount;
22 int pageSize = Model.PageSize;
23
24 <header class="d-flex flex-wrap align-items-center gap-3 p-3 border-bottom">
25 <h1 class="h6 m-0 flex-fill">@Translate("Favorite lists")</h1>
26 @if (Model.FavoriteLists != null)
27 {
28 if(Model.FavoriteLists.Count > 0) {
29 <button type="button" class="btn btn-link p-0 border-0" data-bs-toggle="modal" data-bs-target="#createFavoriteListModal">+ @Translate("Add new favorite list")</button>
30 }
31 }
32 </header>
33
34 if (Model.FavoriteLists == null || Model.FavoriteLists.Count < 1)
35 {
36 <div class="grid">
37 <div class="g-col-12 g-start-lg-3 g-col-lg-8 d-flex flex-column gap-3 text-center py-3">
38 <h2 class="h5 m-0">@Translate("It looks like you do not have any favorites yet")</h2>
39 <p class="m-0">@Translate("Save and arrange the best things here until you are ready for them")</p>
40
41 <div class="d-flex flex-column flex-sm-row gap-3 justify-content-center">
42 @if (!string.IsNullOrEmpty(listPageLink)) {
43 <a href="@listPageLink" class="btn btn-secondary">@Translate("Go exploring")</a>
44 }
45 <button type="button" class="btn btn-primary" data-bs-toggle="modal" data-bs-target="#createFavoriteListModal">@Translate("Create favorite list")</button>
46 </div>
47 </div>
48 </div>
49 }
50 else
51 {
52 string productCountLabel = Model.FavoriteLists.Count > 1 ? Translate("products") : Translate("product");
53
54 foreach (var theList in Model.FavoriteLists)
55 {
56 string favoriteListLink = currentPageUrl + "&FavoriteListId=" + theList.Id;
57 string listName = !string.IsNullOrEmpty(theList.Name) ? theList.Name : Translate("Favorites");
58
59 <article class="d-flex flex-column gap-3 p-3 border-bottom">
60
61 <header class="d-flex flex-row align-items-baseline lh-1">
62 <h3 class="flex-fill h6 m-0">
63 <a href="@favoriteListLink" class="text-decoration-none opacity-75">@listName</a>
64 </h3>
65 <span class="small text-end">@theList.ProductList.Products.Count @productCountLabel <span class="d-none d-sm-inline">@Translate("in this list")</span></span>
66 </header>
67
68 <div class="d-md-none grid grid-2">
69 @if(theList.ProductList.Products.Count > 0)
70 {
71 foreach (var item in theList.ProductList.Products.Take(2))
72 {
73 string productImage = "/Admin/Public/GetImage.ashx?Image=" + item.DefaultImage.Value + "&Format=webp&Width=350&Height=350";
74
75 <div class="ratio ratio-1x1">
76 <a href="@favoriteListLink" class="d-flex justify-content-center align-items-center">
77 <img
78 src="@productImage"
79 width="350"
80 loading="lazy"
81 decoding="async"
82 class="mw-100 mh-100"
83 alt="@item.Name" />
84 </a>
85 </div>
86 }
87 }
88 else
89 {
90 <div class="g-col-12 py-5 text-center border">
91 <a href="@listPageLink">@Translate("This list is empty. Click here to be inspired")</a>
92 </div>
93 }
94 </div>
95
96 <div class="d-none d-md-grid d-print-grid grid grid-2 grid-md-5">
97 @if(theList.ProductList.Products.Count > 0)
98 {
99 foreach (var item in theList.ProductList.Products.Take(5))
100 {
101 string productImage = "/Admin/Public/GetImage.ashx?Image=" + @item.DefaultImage.Value + "&Format=webp&Width=350&Height=350";
102
103 <div class="ratio ratio-1x1">
104 <a href="@favoriteListLink" class="d-flex justify-content-center align-items-center">
105 <img
106 src="@productImage"
107 width="350"
108 loading="lazy"
109 decoding="async"
110 class="mw-100 mh-100"
111 alt="@item.Name" />
112 </a>
113 </div>
114 }
115 }
116 else
117 {
118 <div class="g-col-12 py-6 text-center border">
119 <a href="@listPageLink">@Translate("This list is empty. Click here to be inspired")</a>
120 </div>
121 }
122 </div>
123
124 <footer class="d-flex flex-row gap-3 align-items-center justify-content-end">
125 <button
126 type="button"
127 class="btn btn-link p-0 renameFavoriteListModal"
128 data-bs-toggle="modal"
129 data-bs-target="#renameFavoriteListModal"
130 data-list-id="@theList.Id"
131 data-list-name="@listName">@Translate("Rename")
132 </button>
133 <button
134 type="button"
135 class="btn btn-link p-0 deleteFavoriteNameButton"
136 data-bs-toggle="modal"
137 data-bs-target="#deleteFavoriteListModal"
138 data-list-id="@theList.Id"
139 data-list-name="@listName">@Translate("Delete")</button>
140 </footer>
141 </article>
142 }
143 }
144
145 if (listsCount > pageSize)
146 {
147 <div class="p-3">
148 @RenderPagination(currentPageUrl, Model.PageCount, Model.CurrentPage, Model.PageSize)
149 </div>
150 }
151 }
152
153 <div class="modal fade" tabindex="-1" id="createFavoriteListModal">
154 <div class="modal-dialog modal-dialog-centered">
155 <div class="modal-content">
156 <div class="modal-header">
157 <h5 class="modal-title">@Translate("Create favorite list")</h5>
158 <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
159 </div>
160 <div class="modal-body d-flex flex-column gap-3">
161 <div>
162 <label for="createFavoriteListInputName" class="form-label">@Translate("Name the favorite list")</label>
163 <input type="text" class="form-control" id="createFavoriteListInputName" placeholder="@Translate("Name")">
164 </div>
165 <div class="alert alert-danger m-0 d-none" role="alert" id="createFavoriteListError">@Translate("A Favorite List must have a name")</div>
166 </div>
167 <div class="modal-footer">
168 <button type="button" class="btn btn-secondary" data-bs-dismiss="modal">@Translate("Cancel")</button>
169 <button type="button" class="btn btn-primary" id="createFavoriteListButton">@Translate("Create list")</button>
170 </div>
171 </div>
172 </div>
173 </div>
174
175 <div class="modal fade" tabindex="-1" id="renameFavoriteListModal">
176 <div class="modal-dialog modal-dialog-centered">
177 <div class="modal-content">
178 <div class="modal-header">
179 <h5 class="modal-title">@Translate("Rename favorite list")</h5>
180 <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
181 </div>
182 <div class="modal-body">
183 <div>
184 <label for="renameFavoriteListInputName" class="form-label">@Translate("Rename favorite list"):</label>
185 <input type="text" class="form-control" id="renameFavoriteListInputName" placeholder="@Translate("Name")">
186 </div>
187 </div>
188 <div class="modal-footer">
189 <button type="button" class="btn btn-secondary" data-bs-dismiss="modal">@Translate("Cancel")</button>
190 <button type="button" class="btn btn-primary" id="renameFavoriteListButton">@Translate("Update list")</button>
191 </div>
192 </div>
193 </div>
194 </div>
195
196 <div class="modal fade" tabindex="-1" id="deleteFavoriteListModal">
197 <div class="modal-dialog modal-dialog-centered">
198 <div class="modal-content">
199 <div class="modal-header">
200 <h5 class="modal-title">@Translate("Delete favorite list")</h5>
201 <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
202 </div>
203 <div class="modal-body">
204 <p>@Translate("You are about to delete"): <strong id="deleteFavoriteName"></strong>.</p>
205 <p>@Translate("Are you sure you want to delete it?")</p>
206 </div>
207 <div class="modal-footer">
208 <button type="button" class="btn btn-secondary" data-bs-dismiss="modal">@Translate("Cancel")</button>
209 <button type="button" class="btn btn-primary" id="deleteFavoriteListButton">@Translate("Delete list")</button>
210 </div>
211 </div>
212 </div>
213 </div>
214
215 <script>
216 let userId = @Pageview.User.ID;
217 let renameFavoriteListModal = document.querySelector("#renameFavoriteListModal")
218 let deleteFavoriteListModal = document.querySelector("#deleteFavoriteListModal")
219
220 renameFavoriteListModal.addEventListener('show.bs.modal', function (event) {
221 let button = event.relatedTarget
222 let renameFavoriteListId = button.getAttribute('data-list-id');
223 let renameFromName = button.getAttribute('data-list-name')
224 let renameFavoriteListInputName = document.getElementById('renameFavoriteListInputName');
225
226 renameFavoriteListInputName.value = renameFromName;
227
228 document.querySelector("#renameFavoriteListButton").addEventListener("click", function () {
229 let favoriteListId = renameFavoriteListId;
230
231 // Rename Favorite List
232 document.location.href = "/?favoritecmd=renamefavoritelist&userId=" + userId + "&favoriteListId=" + favoriteListId + "&name=" + renameFavoriteListInputName.value;
233 });
234 })
235
236 deleteFavoriteListModal.addEventListener('show.bs.modal', function (event) {
237 let button = event.relatedTarget;
238 let deleteFavoriteListId = button.getAttribute('data-list-id');
239 let deleteFavoriteListName = button.getAttribute('data-list-name');
240 let deleteFavoriteName = document.querySelector("#deleteFavoriteName");
241
242 // Update label to confirm before deletion
243 deleteFavoriteName.innerHTML = deleteFavoriteListName;
244
245 // Delete Favorite List
246 document.querySelector("#deleteFavoriteListButton").addEventListener("click", function () {
247 let favoriteListId = deleteFavoriteListId;
248 DeleteFavoriteList(userId, favoriteListId);
249 });
250 })
251
252 async function DeleteFavoriteList(userId, favoriteListId) {
253 var url = "/?favoritecmd=removefavoritelist&userId=" + userId + "&favoriteListId=" + favoriteListId;
254
255 let response = await fetch(url);
256 if (response.ok) {
257 document.location.href = "/Default.aspx?ID=@(Pageview.Page.ID)";
258 }
259 }
260
261 // Create new Favorite List
262 document.querySelector("#createFavoriteListButton").addEventListener("click", function () {
263 let createFavoriteListName = document.querySelector("#createFavoriteListInputName").value;
264
265 if (createFavoriteListName != "") {
266 document.location.href = "/?favoritecmd=createfavoritelist&userId=" + userId + "&name=" + createFavoriteListName;
267 }
268 else if (document.querySelector("#createFavoriteListError"))
269 {
270 document.querySelector("#createFavoriteListError").classList.remove("d-none");
271 }
272 });
273 </script>
274
275
276 @helper RenderPagination(string currentPageLink, int pageCount, int currentPage, int pageSize)
277 {
278 <ul class="pagination m-0">
279 @{string pageHrefTemplate = string.Format("<a class=\"page-link\" href=\"{0}&PageNum={{0}}&PageSize={{1}}\">{{0}}</a>", currentPageLink);}
280 @for (int i = 1; i <= pageCount; i++)
281 {
282 var css = i == currentPage
283 ? "page-item active"
284 : "page-item";
285 <li class="@css">
286 @string.Format(pageHrefTemplate, i, pageSize)
287 </li>
288 }
289 </ul>
290 }
291