Error executing template "Designs/Swift/QueryPublisher/Essve_SecondaryUsers.cshtml"
System.NullReferenceException: Object reference not set to an instance of an object.
at CompiledRazorTemplates.Dynamic.RazorEngine_0c659c002ac44bb787da4761f7ea558c.ExecuteAsync()
at RazorEngine.Templating.TemplateBase.Run(ExecuteContext context, TextWriter reader)
at RazorEngine.Templating.RazorEngineCore.RunTemplate(ICompiledTemplate template, TextWriter writer, Object model, DynamicViewBag viewBag)
at RazorEngine.Templating.RazorEngineService.Run(ITemplateKey key, TextWriter writer, Type modelType, Object model, DynamicViewBag viewBag)
at RazorEngine.Templating.DynamicWrapperService.Run(ITemplateKey key, TextWriter writer, Type modelType, Object model, DynamicViewBag viewBag)
at RazorEngine.Templating.RazorEngineServiceExtensions.Run(IRazorEngineService service, String name, TextWriter writer, Type modelType, Object model, DynamicViewBag viewBag)
at RazorEngine.Templating.RazorEngineServiceExtensions.<>c__DisplayClass23_0.<Run>b__0(TextWriter writer)
at RazorEngine.Templating.RazorEngineServiceExtensions.WithWriter(Action`1 withWriter)
at RazorEngine.Templating.RazorEngineServiceExtensions.Run(IRazorEngineService service, String name, Type modelType, Object model, DynamicViewBag viewBag)
at Dynamicweb.Rendering.RazorTemplateRenderingProvider.Render(Template template)
at Dynamicweb.Rendering.TemplateRenderingService.Render(Template template)
at Dynamicweb.Rendering.Template.RenderRazorTemplate()
1 @inherits Dynamicweb.Rendering.RazorTemplateBase<Dynamicweb.Rendering.RazorTemplateModel<Dynamicweb.Rendering.Template>>
2 @using System.Linq
3 @using Dynamicweb
4 @using Dynamicweb.Security.UserManagement
5
6 @{
7 string contentPadding = Pageview.CurrentParagraph.Item["ContentPadding"] != null ? Pageview.CurrentParagraph.Item["ContentPadding"].ToString() : string.Empty;
8 contentPadding = contentPadding == "none" ? "px-0" : contentPadding;
9 contentPadding = contentPadding == "small" ? "p-2 p-md-3" : contentPadding;
10 contentPadding = contentPadding == "large" ? "p-4 p-md-5" : contentPadding;
11 var themeRaw = Pageview.CurrentParagraph.Item["Theme"]?.ToString();
12 string theme = !string.IsNullOrEmpty(themeRaw) ? " h-100 theme " + themeRaw.Replace(" ", "").Trim().ToLower() : string.Empty;
13 string searchTerm = string.Empty;
14 if (!string.IsNullOrEmpty(Dynamicweb.Context.Current.Request["userquery"]))
15 {
16 searchTerm = Dynamicweb.Context.Current.Request["userquery"];
17
18 }
19 string iconPath = "/Files/Templates/Designs/Swift/Assets/icons/";
20
21 var queryItems = GetLoop("QueryResultItem");
22
23 //bool nowImpersonating = !string.IsNullOrEmpty(Dynamicweb.Context.Current.Request.QueryString.Get("NowImpersonating")) ? Convert.ToBoolean(Dynamicweb.Context.Current.Request.QueryString.Get("NowImpersonating")) : false;
24 bool nowImpersonating = Dynamicweb.Security.UserManagement.User.GetCurrentSecondaryUser() != null;
25 bool isStandardSwiftTemplates = Pageview.AreaSettings.GetString("AddressFieldsBasedOn", "swift") == "swift";
26 UserGroupService service = new Dynamicweb.Security.UserManagement.UserGroupService();
27 UserGroup canImpersonateGroup = service.GetGroups().FirstOrDefault(x => x.Name == "UsersPortal_CanImpersonate");
28 bool canSeePage = nowImpersonating || (canImpersonateGroup != null && Pageview.User.GetGroups().Contains(canImpersonateGroup));
29 }
30
31 @if (canSeePage)
32 {
33 <div class="@(contentPadding)@(theme)">
34 <header class="">
35 <div class="grid grid-1 grid-sm-2 align-items-center">
36 @if (!string.IsNullOrEmpty(searchTerm))
37 {
38 <div class="d-flex align-items-baseline justify-content-between gap-3 mb-3">
39 <h1 class="h2">@Translate("You have searched for") "@searchTerm"</h1>
40 </div>
41 }
42 else
43 {
44 <h1 class="h2 mb-3">@Translate("Manage customer")</h1>
45 }
46 <div class="position-relative type-ahead-dropdown">
47 <form method="get" class="suggest-form">
48 <div class="d-flex align-items-center justify-content-end">
49 <label for="userQuery_@Pageview.CurrentParagraph.ID" class="visually-hidden">@Translate("Search for customer")</label>
50
51 <div class="d-flex align-items-center flex-fill" style="position: relative;">
52 <span class="position-absolute icon-2 reset-search px-3">
53 @ReadFile(iconPath + "search.svg")
54 </span>
55 <input id="userQuery_@Pageview.CurrentParagraph.ID"
56 type="search"
57 class="form-control form-control-sm rounded-pill type-ahead-field py-2 ps-5 pe-5"
58 placeholder="@Translate("Search for customer")"
59 aria-label="@Translate("Search for customer")"
60 aria-describedby="userQuery_@Pageview.CurrentParagraph.ID"
61 name="userquery"
62 value="@searchTerm"
63 data-original="@searchTerm">
64
65 <button type="button"
66 onclick="var f = document.getElementById('userQuery_@Pageview.CurrentParagraph.ID'); f.value = ''; f.focus(); f.closest('form').submit();"
67 class="btn position-absolute end-0 icon-2 reset-search"
68 aria-label="@Translate("Clear search field")"
69 style="opacity: 0; visibility: hidden; right: 0;">
70 @ReadFile(iconPath + "x.svg")
71 </button>
72 </div>
73
74 <button type="submit" class="ms-2 btn btn-secondary" aria-label="@Translate("Search")">
75 @Translate("Search")
76 </button>
77 </div>
78 </form>
79 </div>
80 </div>
81 </header>
82
83
84 @if (queryItems.Count() != 0)
85 {
86
87 @* Bootstrap only support horizontally scrolled tables. Thus, we need to have separate designs for large and small screens. *@
88
89 <table class="table d-none d-lg-table table-striped table-hover table-linked align-middle mb-0" border="1">
90 <thead>
91 <tr>
92 <th>
93 @Translate("Customer no")
94 </th>
95 <th>
96 @Translate("SignInAsCustomer:Company", "Company")
97 </th>
98 <th>
99 @Translate("SignInAsCustomer:Name","Customer")
100 </th>
101 <th>
102 @Translate("Email")
103 </th>
104 <th style="min-width: 155px;" aria-hidden="true">
105 <span>
106
107 </span>
108 </th>
109 </tr>
110 </thead>
111 <tbody class="border-top-0">
112 @foreach (var result in queryItems)
113 {
114 string UserLink = $"/Default.aspx?ID={Pageview.Page.ID}&DWExtranetSecondaryUserSelector={result.GetInteger("UserID")}&NowImpersonating=True";
115 bool hasAddressFormat = Dynamicweb.Ecommerce.International.Country.GetDisplayAddress(result.GetString("CountryCode")).Any();
116
117 <tr class="position-relative">
118 <td>
119 @if (!string.IsNullOrWhiteSpace(result.GetString("CustomerNumber")))
120 {
121 <a href="@UserLink" class="d-block text-decoration-none">
122 @result.GetString("CustomerNumber")
123 </a>
124 }
125 </td>
126 <td>
127 @if (!string.IsNullOrWhiteSpace(result.GetString("Company")))
128 {
129 <a href="@UserLink" class="d-block text-decoration-none">
130 @result.GetString("Company")
131 </a>
132 }
133 </td>
134 <td>
135 @if (!string.IsNullOrWhiteSpace(result.GetString("FirstName")) || !string.IsNullOrWhiteSpace(result.GetString("LastName")))
136 {
137 <a href="@UserLink" class="d-block text-decoration-none" tabindex="-1">
138 @result.GetString("FirstName") @result.GetString("LastName")
139 </a>
140 }
141 else if (!string.IsNullOrWhiteSpace(result.GetString("Name")))
142 {
143 <a href="@UserLink" class="d-block text-decoration-none" tabindex="-1">
144 @result.GetString("Name")
145 </a>
146 }
147 </td>
148 <td>
149 @if (!string.IsNullOrWhiteSpace(result.GetString("UserEmail")))
150 {
151 <a href="@UserLink" class="d-block text-decoration-none" tabindex="-1">
152 @result.GetString("UserEmail")
153 </a>
154 }
155 </td>
156 <td class="text-end ">
157 <a href="@UserLink" class="d-block text-decoration-none" tabindex="-1">
158 <span class="btn btn-sm btn-secondary">
159 @Translate("Manage customer")
160 </span>
161 </a>
162 </td>
163 </tr>
164 }
165 </tbody>
166 </table>
167
168 @* Bootstrap only support horizontally scrolled tables. Thus, we need to have separate designs for large and small screens. *@
169
170 <table class="table d-table d-lg-none table-borderless table-clean align-top mb-0">
171 @foreach (var result in queryItems)
172 {
173 string UserLink = $"/Default.aspx?ID={Pageview.Page.ID}&DWExtranetSecondaryUserSelector={result.GetInteger("UserID")}&NowImpersonating=True";
174
175 <tbody class="border-bottom">
176 <tr>
177 <th class="fs-8">
178 @Translate("Customer No")
179 </th>
180 <td class="text-end">
181 @if (!string.IsNullOrWhiteSpace(result.GetString("CustomerNumber")))
182 {
183 @result.GetString("CustomerNumber")
184 }
185 </td>
186 </tr>
187 <tr>
188 <th class="fs-8">
189 @Translate("Customer")
190 </th>
191 <td class="text-end">
192 @if (!string.IsNullOrWhiteSpace(result.GetString("Name")))
193 {
194 @result.GetString("Name")
195 }
196 </td>
197 </tr>
198 <tr>
199 <th class="fs-8">
200 @Translate("Email")
201 </th>
202 <td class="text-end text-break">
203 @if (!string.IsNullOrWhiteSpace(result.GetString("UserEmail")))
204 {
205 @result.GetString("UserEmail")
206 }
207 </td>
208 </tr>
209 <tr>
210 <th class="fs-8">
211 @Translate("Address")
212 </th>
213 <td class="text-end">
214 @if (isStandardSwiftTemplates)
215 {
216 if (!string.IsNullOrWhiteSpace(result.GetString("Address")))
217 {
218 <text>
219 @result.GetString("Address"),
220 </text>
221 }
222 if (!string.IsNullOrEmpty(result.GetString("Address2")))
223 {
224 @result.GetString("Address2")
225 ;
226 }
227 if (!string.IsNullOrWhiteSpace(result.GetString("Zip")))
228 {
229 @result.GetString("Zip")
230 }
231 if (!string.IsNullOrWhiteSpace(result.GetString("City")))
232 {
233 @($", {result.GetString("City")}")
234 }
235 if (!string.IsNullOrEmpty(result.GetString("State")))
236 {
237 var countryCode = !string.IsNullOrEmpty(result.GetString("CountryCode")) ? result.GetString("CountryCode") : Pageview.Area.EcomCountryCode;
238 string stateName = Dynamicweb.Ecommerce.Services.Countries.GetRegion(countryCode, result.GetString("State"))?.GetName(Dynamicweb.Ecommerce.Common.Context.LanguageID) ?? string.Empty;
239
240 @($", {stateName}")
241 }
242 if (!string.IsNullOrEmpty(result.GetString("CountryCode")))
243 {
244 var countryCode = !string.IsNullOrEmpty(result.GetString("CountryCode")) ? result.GetString("CountryCode") : Pageview.Area.EcomCountryCode;
245 string countryName = Dynamicweb.Ecommerce.Services.Countries.GetCountry(countryCode)?.GetName(Dynamicweb.Ecommerce.Common.Context.LanguageID) ?? string.Empty;
246
247 @($", {countryName.ToUpper()}")
248 }
249 }
250 else
251 {
252 <text>
253 @RenderUserItemAddressInline(result)
254 </text>
255 }
256 </td>
257 </tr>
258 <tr>
259 <td colspan="2">
260 <a href="@UserLink" class="d-block text-decoration-none swift_manage-customer-button">
261 <div class="d-grid">
262 <span class="btn btn-sm btn-secondary">
263 @Translate("Manage customer")
264 </span>
265 </div>
266 </a>
267 </td>
268 </tr>
269 </tbody>
270 }
271 </table>
272 var pageLoopItem = GetLoop("DwPaging.LoopPageGroup");
273 int pageCount = GetInteger("DwPaging.PageCount"),
274 currentPage = GetInteger("DwPaging.CurrentPage"),
275 prevPage = GetInteger("DwPaging.PreviousPageNumber"),
276 nextPage = GetInteger("DwPaging.NextPageNumber"),
277 itemsToLoad = 10,
278 pageSize = GetInteger("DwPaging.PageSize"),
279 totalItems = GetInteger("DwPaging.TotalItems"),
280 loadMore = pageSize + itemsToLoad,
281 firstPage = 1,
282 lastPage = pageCount;
283
284 if (GetBoolean("DwPaging.Pageable") == true)
285 {
286 string prevDisabled = currentPage == 1 ? "disabled" : "";
287 string nextDisabled = currentPage == pageCount ? "disabled" : "";
288 <div class="d-none d-lg-block">
289 <form id="pagination_@Pageview.CurrentParagraph.ID">
290 <div class="p-3 mt-3">
291 <ul class="pagination m-0">
292 <li class="page-item @(prevDisabled)">
293 <button type="submit" class="page-link" onclick="paginationSubmit(event, '@firstPage')">
294 <span class="icon-2">
295 @ReadFile(iconPath + "chevrons-left.svg")
296 </span>
297 </button>
298 </li>
299 <li class="page-item @(prevDisabled)">
300 <a class="page-link" href="@prevPage" onclick="paginationSubmit(event, '@prevPage')">
301 <span class="icon-2">
302 @ReadFile(iconPath + "chevron-left.svg")
303 </span>
304 </a>
305 </li>
306 @foreach (var pages in pageLoopItem)
307 {
308 var css = pages.GetBoolean("PageGroup.ActivePage") ? "page-item active" : "page-item";
309
310 <li class="@css">
311 <a href="@pages.GetString("PageGroup.PageLink")" class="page-link" onclick="paginationSubmit(event, '@pages.GetInteger("PageGroup.PageNumber")')">@pages.GetInteger("PageGroup.PageNumber")</a>
312 </li>
313 }
314 <li class="page-item @(nextDisabled)">
315 <a class="page-link" href="@nextPage" onclick="paginationSubmit(event, '@nextPage')">
316 <span class="icon-2">
317 @ReadFile(iconPath + "chevron-right.svg")
318 </span>
319 </a>
320 </li>
321 <li class="page-item @(nextDisabled)">
322 <button type="submit" class="page-link" onclick="paginationSubmit(event, '@lastPage')">
323 <span class="icon-2">
324 @ReadFile(iconPath + "chevrons-right.svg")
325 </span>
326 </button>
327 </li>
328 </ul>
329 </div>
330 <input type="hidden" name="pagenum" id="pageNumber_@Pageview.CurrentParagraph.ID">
331 </form>
332 <script>
333 paginationSubmit = function (event, pageNumber) {
334 event.preventDefault();
335 document.querySelector('#pageNumber_@Pageview.CurrentParagraph.ID').value = pageNumber;
336 swift.PageUpdater.Update(document.querySelector("#pagination_@Pageview.CurrentParagraph.ID"));
337 }
338 </script>
339 </div>
340 <div class="d-block d-lg-none position-sticky bottom-0">
341 <form id="loadMore_@Pageview.CurrentParagraph.ID">
342 <input type="hidden" name="pagesize" id="pageSize_@Pageview.CurrentParagraph.ID">
343 <div class="gap-2 grid grid-1 mx-3 pb-2 theme">
344 <button class="btn btn-primary w-100" type="submit" onclick="loadMore(event, '@loadMore')">
345 @Translate("Show more")
346 </button>
347 <div class="text-center fs-8">Showing @pageSize/@totalItems</div>
348 </div>
349 </form>
350 <script>
351 loadMore = function (event, pageSize) {
352 event.preventDefault();
353 document.querySelector('#pageSize_@Pageview.CurrentParagraph.ID').value = pageSize;
354 swift.PageUpdater.Update(document.querySelector("#loadMore_@Pageview.CurrentParagraph.ID"));
355 }
356 </script>
357 </div>
358 }
359 }
360 else
361 {
362 if (!string.IsNullOrEmpty(searchTerm))
363 {
364 <div class="alert alert-info text-center mt-3" role="alert">
365 @Translate("Your search ") <strong> "@searchTerm" </strong>@Translate("did not return any customers that match your search")
366 </div>
367 }
368 else
369 {
370 <div class="alert alert-info text-center mt-3" role="alert">
371 @Translate("You have no customer you can sign in as")
372 </div>
373 }
374 }
375
376 <script>
377 function goToPage(page) {
378 let url = new URL(document.location.href);
379 url.searchParams.set('PageNum', page);
380 document.location.href = url;
381 }
382 </script>
383
384 @if (nowImpersonating)
385 {
386 <div class="position-fixed bottom-0 end-0 p-3">
387 <div id="signInToast" class="toast align-items-center w-auto show theme light" role="alert" aria-live="assertive" aria-atomic="true">
388 <div class="d-flex">
389 <div class="toast-body p-3 fs-6">
390 <span>
391 @Translate("You are now signed in as a customer")
392 </span>
393 @if (Pageview.User != null)
394 {
395 @if (!string.IsNullOrEmpty(Pageview.User.FirstName))
396 {
397 <span class="fw-bold">@Pageview.User.FirstName @Pageview.User.LastName</span>
398 }
399 else
400 {
401 <span class="fw-bold">@Pageview.User.Name</span>
402 }
403 }
404 </div>
405 <button type="button" class="btn h-100 icon-3 m-auto" data-bs-dismiss="toast" aria-label="@Translate("Close toast")">@ReadFile(iconPath + "x.svg")</button>
406 </div>
407 </div>
408 </div>
409
410 <script>
411 document.addEventListener("DOMContentLoaded", function (event) {
412 var signInToast = document.querySelector('#signInToast')
413 var showSignInToast = new bootstrap.Toast(signInToast)
414 showSignInToast.show()
415 });
416 </script>
417 }
418
419 </div>
420 }
421 else
422 {
423 <div><p>@Translate("No permission to see this page")</p></div>
424 }
425
426 @inherits Dynamicweb.Rendering.RazorTemplateBase<Dynamicweb.Rendering.RazorTemplateModel<Dynamicweb.Rendering.Template>>
427 @using System.Linq
428 @using System.Text
429 @using System.Text.RegularExpressions
430 @using Dynamicweb.Ecommerce.International
431
432 @functions {
433 public string RenderUserItemAddressInline(LoopItem address)
434 {
435 var result = new StringBuilder();
436
437 List<List<string>> addressFormat = Dynamicweb.Ecommerce.International.Country.GetDisplayAddress(address.GetString("CountryCode"));
438 string regionCode = address.GetString("State");
439 string regionName = GetRegionName(address.GetString("CountryCode"), regionCode);
440 string countryName = Dynamicweb.Ecommerce.Services.Countries.GetCountry(address.GetString("CountryCode"))?.GetName(Dynamicweb.Ecommerce.Common.Context.LanguageID) ?? string.Empty;
441
442 foreach (List<string> addressLine in addressFormat)
443 {
444 for (var i = 0; i < addressLine.Count; i++)
445 {
446 addressLine[i] = Regex.Replace(addressLine[i], "{name}", string.Empty, RegexOptions.IgnoreCase); // his needs tobe empty because there is no 'Name' property on the user Address object, but the format from the UI will/could have it
447 addressLine[i] = Regex.Replace(addressLine[i], "{firstName}", string.Empty, RegexOptions.IgnoreCase); // This needs tobe empty because there is no 'First Name' property on the user Address object, but the format from the UI will/could have it
448 addressLine[i] = Regex.Replace(addressLine[i], "{lastName}", string.Empty, RegexOptions.IgnoreCase); // This needs tobe empty because there is no 'Last Name' property on the user Address object, but the format from the UI will/could have it
449 addressLine[i] = Regex.Replace(addressLine[i], "{company}", address.GetString("Company"), RegexOptions.IgnoreCase);
450 addressLine[i] = Regex.Replace(addressLine[i], "{address}", address.GetString("Address"), RegexOptions.IgnoreCase);
451 addressLine[i] = Regex.Replace(addressLine[i], "{address1}", address.GetString("Address"), RegexOptions.IgnoreCase);
452 addressLine[i] = Regex.Replace(addressLine[i], "{address2}", address.GetString("Address2"), RegexOptions.IgnoreCase);
453 addressLine[i] = Regex.Replace(addressLine[i], "{zip}", address.GetString("Zip"), RegexOptions.IgnoreCase);
454 addressLine[i] = Regex.Replace(addressLine[i], "{city}", address.GetString("City"), RegexOptions.IgnoreCase);
455 addressLine[i] = Regex.Replace(addressLine[i], "{regionCode}", regionCode, RegexOptions.IgnoreCase);
456 addressLine[i] = Regex.Replace(addressLine[i], "{region}", regionName, RegexOptions.IgnoreCase);
457 addressLine[i] = Regex.Replace(addressLine[i], "{countryCode}", address.GetString("CountryCode"), RegexOptions.IgnoreCase);
458 addressLine[i] = Regex.Replace(addressLine[i], "{country}", countryName, RegexOptions.IgnoreCase);
459
460 // Remove any bad placeholders the user may have submitted
461 addressLine[i] = Regex.Replace(addressLine[i], "{phone}", string.Empty, RegexOptions.IgnoreCase);
462 addressLine[i] = Regex.Replace(addressLine[i], "{email}", string.Empty, RegexOptions.IgnoreCase);
463 }
464
465 var completeLine = string.Join(string.Empty, addressLine.ToArray());
466 if (!string.IsNullOrWhiteSpace(completeLine))
467 {
468 result.Append($"<span>{completeLine}</span>");
469 }
470 }
471
472 return result.ToString();
473 }
474
475 public string GetRegionName(string countryCode, string regionValue)
476 {
477 CountryCollection allCountryRegions = Dynamicweb.Ecommerce.Services.Countries.GetRegions(countryCode);
478 Country matchedRegion = allCountryRegions.FirstOrDefault(r => r.RegionCode == regionValue || r.GetName(Dynamicweb.Ecommerce.Common.Context.LanguageID) == regionValue);
479
480 if (matchedRegion == null) return regionValue;
481
482 return matchedRegion.GetName(Dynamicweb.Ecommerce.Common.Context.LanguageID);
483 }
484 }
485
486