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_f6a3b0867d284a5ab9cad3dba3f136a1.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>>
@using System.Linq
@using Dynamicweb
@using Dynamicweb.Security.UserManagement
@{
string contentPadding = Pageview.CurrentParagraph.Item["ContentPadding"] != null ? Pageview.CurrentParagraph.Item["ContentPadding"].ToString() : string.Empty;
contentPadding = contentPadding == "none" ? "px-0" : contentPadding;
contentPadding = contentPadding == "small" ? "p-2 p-md-3" : contentPadding;
contentPadding = contentPadding == "large" ? "p-4 p-md-5" : contentPadding;
var themeRaw = Pageview.CurrentParagraph.Item["Theme"]?.ToString();
string theme = !string.IsNullOrEmpty(themeRaw) ? " h-100 theme " + themeRaw.Replace(" ", "").Trim().ToLower() : string.Empty;
string searchTerm = string.Empty;
if (!string.IsNullOrEmpty(Dynamicweb.Context.Current.Request["userquery"]))
{
searchTerm = Dynamicweb.Context.Current.Request["userquery"];
}
string iconPath = "/Files/Templates/Designs/Swift/Assets/icons/";
var queryItems = GetLoop("QueryResultItem");
//bool nowImpersonating = !string.IsNullOrEmpty(Dynamicweb.Context.Current.Request.QueryString.Get("NowImpersonating")) ? Convert.ToBoolean(Dynamicweb.Context.Current.Request.QueryString.Get("NowImpersonating")) : false;
bool nowImpersonating = Dynamicweb.Security.UserManagement.User.GetCurrentSecondaryUser() != null;
bool isStandardSwiftTemplates = Pageview.AreaSettings.GetString("AddressFieldsBasedOn", "swift") == "swift";
UserGroupService service = new Dynamicweb.Security.UserManagement.UserGroupService();
UserGroup canImpersonateGroup = service.GetGroups().FirstOrDefault(x => x.Name == "UsersPortal_CanImpersonate");
bool canSeePage = nowImpersonating || (canImpersonateGroup != null && Pageview.User.GetGroups().Contains(canImpersonateGroup));
}
@if (canSeePage)
{
<div class="@(contentPadding)@(theme)">
<header class="">
<div class="grid grid-1 grid-sm-2 align-items-center">
@if (!string.IsNullOrEmpty(searchTerm))
{
<div class="d-flex align-items-baseline justify-content-between gap-3 mb-3">
<h1 class="h2">@Translate("You have searched for") "@searchTerm"</h1>
</div>
}
else
{
<h1 class="h2 mb-3">@Translate("Manage customer")</h1>
}
<div class="position-relative type-ahead-dropdown">
<form method="get" class="suggest-form">
<div class="d-flex align-items-center justify-content-end">
<label for="userQuery_@Pageview.CurrentParagraph.ID" class="visually-hidden">@Translate("Search for customer")</label>
<div class="d-flex align-items-center flex-fill" style="position: relative;">
<span class="position-absolute icon-2 reset-search px-3">
@ReadFile(iconPath + "search.svg")
</span>
<input id="userQuery_@Pageview.CurrentParagraph.ID"
type="search"
class="form-control form-control-sm rounded-pill type-ahead-field py-2 ps-5 pe-5"
placeholder="@Translate("Search for customer")"
aria-label="@Translate("Search for customer")"
aria-describedby="userQuery_@Pageview.CurrentParagraph.ID"
name="userquery"
value="@searchTerm"
data-original="@searchTerm">
<button type="button"
onclick="var f = document.getElementById('userQuery_@Pageview.CurrentParagraph.ID'); f.value = ''; f.focus(); f.closest('form').submit();"
class="btn position-absolute end-0 icon-2 reset-search"
aria-label="@Translate("Clear search field")"
style="opacity: 0; visibility: hidden; right: 0;">
@ReadFile(iconPath + "x.svg")
</button>
</div>
<button type="submit" class="ms-2 btn btn-secondary" aria-label="@Translate("Search")">
@Translate("Search")
</button>
</div>
</form>
</div>
</div>
</header>
@if (queryItems.Count() != 0)
{
@* Bootstrap only support horizontally scrolled tables. Thus, we need to have separate designs for large and small screens. *@
<table class="table d-none d-lg-table table-striped table-hover table-linked align-middle mb-0" border="1">
<thead>
<tr>
<th>
@Translate("Customer no")
</th>
<th>
@Translate("SignInAsCustomer:Company", "Company")
</th>
<th>
@Translate("SignInAsCustomer:Name","Customer")
</th>
<th>
@Translate("Email")
</th>
<th style="min-width: 155px;" aria-hidden="true">
<span>
</span>
</th>
</tr>
</thead>
<tbody class="border-top-0">
@foreach (var result in queryItems)
{
string UserLink = $"/Default.aspx?ID={Pageview.Page.ID}&DWExtranetSecondaryUserSelector={result.GetInteger("UserID")}&NowImpersonating=True";
bool hasAddressFormat = Dynamicweb.Ecommerce.International.Country.GetDisplayAddress(result.GetString("CountryCode")).Any();
<tr class="position-relative">
<td>
@if (!string.IsNullOrWhiteSpace(result.GetString("CustomerNumber")))
{
<a href="@UserLink" class="d-block text-decoration-none">
@result.GetString("CustomerNumber")
</a>
}
</td>
<td>
@if (!string.IsNullOrWhiteSpace(result.GetString("Company")))
{
<a href="@UserLink" class="d-block text-decoration-none">
@result.GetString("Company")
</a>
}
</td>
<td>
@if (!string.IsNullOrWhiteSpace(result.GetString("FirstName")) || !string.IsNullOrWhiteSpace(result.GetString("LastName")))
{
<a href="@UserLink" class="d-block text-decoration-none" tabindex="-1">
@result.GetString("FirstName") @result.GetString("LastName")
</a>
}
else if (!string.IsNullOrWhiteSpace(result.GetString("Name")))
{
<a href="@UserLink" class="d-block text-decoration-none" tabindex="-1">
@result.GetString("Name")
</a>
}
</td>
<td>
@if (!string.IsNullOrWhiteSpace(result.GetString("UserEmail")))
{
<a href="@UserLink" class="d-block text-decoration-none" tabindex="-1">
@result.GetString("UserEmail")
</a>
}
</td>
<td class="text-end ">
<a href="@UserLink" class="d-block text-decoration-none" tabindex="-1">
<span class="btn btn-sm btn-secondary">
@Translate("Manage customer")
</span>
</a>
</td>
</tr>
}
</tbody>
</table>
@* Bootstrap only support horizontally scrolled tables. Thus, we need to have separate designs for large and small screens. *@
<table class="table d-table d-lg-none table-borderless table-clean align-top mb-0">
@foreach (var result in queryItems)
{
string UserLink = $"/Default.aspx?ID={Pageview.Page.ID}&DWExtranetSecondaryUserSelector={result.GetInteger("UserID")}&NowImpersonating=True";
<tbody class="border-bottom">
<tr>
<th class="fs-8">
@Translate("Customer No")
</th>
<td class="text-end">
@if (!string.IsNullOrWhiteSpace(result.GetString("CustomerNumber")))
{
@result.GetString("CustomerNumber")
}
</td>
</tr>
<tr>
<th class="fs-8">
@Translate("SignInAsCustomer:Company", "Company")
</th>
<td class="text-end">
@if (!string.IsNullOrWhiteSpace(result.GetString("Company")))
{
@result.GetString("Company")
}
</td>
</tr>
<tr>
<th class="fs-8">
@Translate("SignInAsCustomer:Name","Customer")
</th>
<td class="text-end">
@if (!string.IsNullOrWhiteSpace(result.GetString("FirstName")) || !string.IsNullOrWhiteSpace(result.GetString("LastName")))
{
<span>@result.GetString("FirstName") @result.GetString("LastName")</span>
}
else if (!string.IsNullOrWhiteSpace(result.GetString("Name")))
{
@result.GetString("Name")
}
</td>
</tr>
<tr>
<th class="fs-8">
@Translate("Email")
</th>
<td class="text-end text-break">
@if (!string.IsNullOrWhiteSpace(result.GetString("UserEmail")))
{
@result.GetString("UserEmail")
}
</td>
</tr>
<tr>
<th class="fs-8">
@Translate("Address")
</th>
<td class="text-end">
@if (isStandardSwiftTemplates)
{
if (!string.IsNullOrWhiteSpace(result.GetString("Address")))
{
<text>
@result.GetString("Address"),
</text>
}
if (!string.IsNullOrEmpty(result.GetString("Address2")))
{
@result.GetString("Address2")
;
}
if (!string.IsNullOrWhiteSpace(result.GetString("Zip")))
{
@result.GetString("Zip")
}
if (!string.IsNullOrWhiteSpace(result.GetString("City")))
{
@($", {result.GetString("City")}")
}
if (!string.IsNullOrEmpty(result.GetString("State")))
{
var countryCode = !string.IsNullOrEmpty(result.GetString("CountryCode")) ? result.GetString("CountryCode") : Pageview.Area.EcomCountryCode;
string stateName = Dynamicweb.Ecommerce.Services.Countries.GetRegion(countryCode, result.GetString("State"))?.GetName(Dynamicweb.Ecommerce.Common.Context.LanguageID) ?? string.Empty;
@($", {stateName}")
}
if (!string.IsNullOrEmpty(result.GetString("CountryCode")))
{
var countryCode = !string.IsNullOrEmpty(result.GetString("CountryCode")) ? result.GetString("CountryCode") : Pageview.Area.EcomCountryCode;
string countryName = Dynamicweb.Ecommerce.Services.Countries.GetCountry(countryCode)?.GetName(Dynamicweb.Ecommerce.Common.Context.LanguageID) ?? string.Empty;
@($", {countryName.ToUpper()}")
}
}
else
{
<text>
@RenderUserItemAddressInline(result)
</text>
}
</td>
</tr>
<tr>
<td colspan="2">
<a href="@UserLink" class="d-block text-decoration-none swift_manage-customer-button">
<div class="d-grid">
<span class="btn btn-sm btn-secondary">
@Translate("Manage customer")
</span>
</div>
</a>
</td>
</tr>
</tbody>
}
</table>
var pageLoopItem = GetLoop("DwPaging.LoopPageGroup");
int pageCount = GetInteger("DwPaging.PageCount"),
currentPage = GetInteger("DwPaging.CurrentPage"),
prevPage = GetInteger("DwPaging.PreviousPageNumber"),
nextPage = GetInteger("DwPaging.NextPageNumber"),
itemsToLoad = 10,
pageSize = GetInteger("DwPaging.PageSize"),
totalItems = GetInteger("DwPaging.TotalItems"),
loadMore = pageSize + itemsToLoad,
firstPage = 1,
lastPage = pageCount;
if (GetBoolean("DwPaging.Pageable") == true)
{
string prevDisabled = currentPage == 1 ? "disabled" : "";
string nextDisabled = currentPage == pageCount ? "disabled" : "";
<div class="d-none d-lg-block">
<form id="pagination_@Pageview.CurrentParagraph.ID">
<div class="p-3 mt-3">
<ul class="pagination m-0">
<li class="page-item @(prevDisabled)">
<button type="submit" class="page-link" onclick="paginationSubmit(event, '@firstPage')">
<span class="icon-2">
@ReadFile(iconPath + "chevrons-left.svg")
</span>
</button>
</li>
<li class="page-item @(prevDisabled)">
<a class="page-link" href="@prevPage" onclick="paginationSubmit(event, '@prevPage')">
<span class="icon-2">
@ReadFile(iconPath + "chevron-left.svg")
</span>
</a>
</li>
@foreach (var pages in pageLoopItem)
{
var css = pages.GetBoolean("PageGroup.ActivePage") ? "page-item active" : "page-item";
<li class="@css">
<a href="@pages.GetString("PageGroup.PageLink")" class="page-link" onclick="paginationSubmit(event, '@pages.GetInteger("PageGroup.PageNumber")')">@pages.GetInteger("PageGroup.PageNumber")</a>
</li>
}
<li class="page-item @(nextDisabled)">
<a class="page-link" href="@nextPage" onclick="paginationSubmit(event, '@nextPage')">
<span class="icon-2">
@ReadFile(iconPath + "chevron-right.svg")
</span>
</a>
</li>
<li class="page-item @(nextDisabled)">
<button type="submit" class="page-link" onclick="paginationSubmit(event, '@lastPage')">
<span class="icon-2">
@ReadFile(iconPath + "chevrons-right.svg")
</span>
</button>
</li>
</ul>
</div>
<input type="hidden" name="pagenum" id="pageNumber_@Pageview.CurrentParagraph.ID">
</form>
<script>
paginationSubmit = function (event, pageNumber) {
event.preventDefault();
document.querySelector('#pageNumber_@Pageview.CurrentParagraph.ID').value = pageNumber;
swift.PageUpdater.Update(document.querySelector("#pagination_@Pageview.CurrentParagraph.ID"));
}
</script>
</div>
<div class="d-block d-lg-none position-sticky bottom-0">
<form id="loadMore_@Pageview.CurrentParagraph.ID">
<input type="hidden" name="pagesize" id="pageSize_@Pageview.CurrentParagraph.ID">
<div class="gap-2 grid grid-1 mx-3 pb-2 theme">
<button class="btn btn-primary w-100" type="submit" onclick="loadMore(event, '@loadMore')">
@Translate("Show more")
</button>
<div class="text-center fs-8">Showing @pageSize/@totalItems</div>
</div>
</form>
<script>
loadMore = function (event, pageSize) {
event.preventDefault();
document.querySelector('#pageSize_@Pageview.CurrentParagraph.ID').value = pageSize;
swift.PageUpdater.Update(document.querySelector("#loadMore_@Pageview.CurrentParagraph.ID"));
}
</script>
</div>
}
}
else
{
if (!string.IsNullOrEmpty(searchTerm))
{
<div class="alert alert-info text-center mt-3" role="alert">
@Translate("Your search ") <strong> "@searchTerm" </strong>@Translate("did not return any customers that match your search")
</div>
}
else
{
<div class="alert alert-info text-center mt-3" role="alert">
@Translate("You have no customer you can sign in as")
</div>
}
}
<script>
function goToPage(page) {
let url = new URL(document.location.href);
url.searchParams.set('PageNum', page);
document.location.href = url;
}
</script>
@if (nowImpersonating)
{
<div class="position-fixed bottom-0 end-0 p-3">
<div id="signInToast" class="toast align-items-center w-auto show theme light" role="alert" aria-live="assertive" aria-atomic="true">
<div class="d-flex">
<div class="toast-body p-3 fs-6">
<span>
@Translate("You are now signed in as a customer")
</span>
@if (Pageview.User != null)
{
@if (!string.IsNullOrEmpty(Pageview.User.FirstName))
{
<span class="fw-bold">@Pageview.User.FirstName @Pageview.User.LastName</span>
}
else
{
<span class="fw-bold">@Pageview.User.Name</span>
}
}
</div>
<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>
</div>
</div>
</div>
<script>
document.addEventListener("DOMContentLoaded", function (event) {
var signInToast = document.querySelector('#signInToast')
var showSignInToast = new bootstrap.Toast(signInToast)
showSignInToast.show()
});
</script>
}
</div>
}
else
{
<div><p>@Translate("No permission to see this page")</p></div>
}
@inherits Dynamicweb.Rendering.RazorTemplateBase<Dynamicweb.Rendering.RazorTemplateModel<Dynamicweb.Rendering.Template>>
@using System.Linq
@using System.Text
@using System.Text.RegularExpressions
@using Dynamicweb.Ecommerce.International
@functions {
public string RenderUserItemAddressInline(LoopItem address)
{
var result = new StringBuilder();
List<List<string>> addressFormat = Dynamicweb.Ecommerce.International.Country.GetDisplayAddress(address.GetString("CountryCode"));
string regionCode = address.GetString("State");
string regionName = GetRegionName(address.GetString("CountryCode"), regionCode);
string countryName = Dynamicweb.Ecommerce.Services.Countries.GetCountry(address.GetString("CountryCode"))?.GetName(Dynamicweb.Ecommerce.Common.Context.LanguageID) ?? string.Empty;
foreach (List<string> addressLine in addressFormat)
{
for (var i = 0; i < addressLine.Count; i++)
{
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
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
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
addressLine[i] = Regex.Replace(addressLine[i], "{company}", address.GetString("Company"), RegexOptions.IgnoreCase);
addressLine[i] = Regex.Replace(addressLine[i], "{address}", address.GetString("Address"), RegexOptions.IgnoreCase);
addressLine[i] = Regex.Replace(addressLine[i], "{address1}", address.GetString("Address"), RegexOptions.IgnoreCase);
addressLine[i] = Regex.Replace(addressLine[i], "{address2}", address.GetString("Address2"), RegexOptions.IgnoreCase);
addressLine[i] = Regex.Replace(addressLine[i], "{zip}", address.GetString("Zip"), RegexOptions.IgnoreCase);
addressLine[i] = Regex.Replace(addressLine[i], "{city}", address.GetString("City"), RegexOptions.IgnoreCase);
addressLine[i] = Regex.Replace(addressLine[i], "{regionCode}", regionCode, RegexOptions.IgnoreCase);
addressLine[i] = Regex.Replace(addressLine[i], "{region}", regionName, RegexOptions.IgnoreCase);
addressLine[i] = Regex.Replace(addressLine[i], "{countryCode}", address.GetString("CountryCode"), RegexOptions.IgnoreCase);
addressLine[i] = Regex.Replace(addressLine[i], "{country}", countryName, RegexOptions.IgnoreCase);
// Remove any bad placeholders the user may have submitted
addressLine[i] = Regex.Replace(addressLine[i], "{phone}", string.Empty, RegexOptions.IgnoreCase);
addressLine[i] = Regex.Replace(addressLine[i], "{email}", string.Empty, RegexOptions.IgnoreCase);
}
var completeLine = string.Join(string.Empty, addressLine.ToArray());
if (!string.IsNullOrWhiteSpace(completeLine))
{
result.Append($"<span>{completeLine}</span>");
}
}
return result.ToString();
}
public string GetRegionName(string countryCode, string regionValue)
{
CountryCollection allCountryRegions = Dynamicweb.Ecommerce.Services.Countries.GetRegions(countryCode);
Country matchedRegion = allCountryRegions.FirstOrDefault(r => r.RegionCode == regionValue || r.GetName(Dynamicweb.Ecommerce.Common.Context.LanguageID) == regionValue);
if (matchedRegion == null) return regionValue;
return matchedRegion.GetName(Dynamicweb.Ecommerce.Common.Context.LanguageID);
}
}