Exception in template (Designs\StandardWebshop\eCom/Product/Product.cshtml): System.Exception: Error Running ExecuteReader: Transaction (Process ID 179) was deadlocked on lock resources with another process and has been chosen as the deadlock victim. Rerun the transaction., Sql: "SELECT
-- Object columns
O.DefinitionKey
,O.LastModified AS OjectLastModified
,O.ObjectId
,O.XmlObjectId
,O.ShopId
,O.LanguageId
-- Value columns
,V.LastModified AS ValueLastModified
,V.XmlReferenceObjectId
,V.XmlReferenceObjectKey
,V.ValueId
,V.[Text]
,V.FieldKey
,V.SortOrder
FROM [LWI_Spec_Objects] AS O
JOIN [LWI_Spec_Values] AS V ON
V.ShopId = O.ShopId
AND V.LanguageId = O.LanguageId
AND V.XmlObjectKey = O.DefinitionKey
AND V.XmlObjectId = O.XmlObjectId
WHERE
O.DefinitionKey IN ('Product')
AND O.XmlObjectId IN ('BETOCRETE CL210WP')
AND O.ShopId IN ('SHOP1')
AND O.LanguageId IN ('LANG1')
ORDER BY O.DefinitionKey, O.LanguageId, O.ShopId, O.XmlObjectId
", Params: '' ---> System.Data.SqlClient.SqlException: Transaction (Process ID 179) was deadlocked on lock resources with another process and has been chosen as the deadlock victim. Rerun the transaction.
at System.Data.SqlClient.SqlConnection.OnError(SqlException exception, Boolean breakConnection, Action`1 wrapCloseInAction)
at System.Data.SqlClient.TdsParser.ThrowExceptionAndWarning(TdsParserStateObject stateObj, Boolean callerHasConnectionLock, Boolean asyncClose)
at System.Data.SqlClient.TdsParser.TryRun(RunBehavior runBehavior, SqlCommand cmdHandler, SqlDataReader dataStream, BulkCopySimpleResultSet bulkCopyHandler, TdsParserStateObject stateObj, Boolean& dataReady)
at System.Data.SqlClient.SqlDataReader.TryConsumeMetaData()
at System.Data.SqlClient.SqlDataReader.get_MetaData()
at System.Data.SqlClient.SqlCommand.FinishExecuteReader(SqlDataReader ds, RunBehavior runBehavior, String resetOptionsString, Boolean isInternal, Boolean forDescribeParameterEncryption, Boolean shouldCacheForAlwaysEncrypted)
at System.Data.SqlClient.SqlCommand.RunExecuteReaderTds(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, Boolean async, Int32 timeout, Task& task, Boolean asyncWrite, Boolean inRetry, SqlDataReader ds, Boolean describeParameterEncryptionRequest)
at System.Data.SqlClient.SqlCommand.RunExecuteReader(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, String method, TaskCompletionSource`1 completion, Int32 timeout, Task& task, Boolean& usedCache, Boolean asyncWrite, Boolean inRetry)
at System.Data.SqlClient.SqlCommand.RunExecuteReader(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, String method)
at System.Data.SqlClient.SqlCommand.ExecuteReader(CommandBehavior behavior, String method)
at Glimpse.Ado.AlternateType.GlimpseDbCommand.ExecuteDbDataReader(CommandBehavior behavior)
at NLWI.Platforms.Dynamicweb9.Database.ADatabaseRepository.ExecuteReader(String query, Object[] ps)
--- End of inner exception stack trace ---
at NLWI.Platforms.Dynamicweb9.Database.ADatabaseRepository.ExecuteReader(String query, Object[] ps)
at NLWI.Platforms.Dynamicweb9.Specs.Repositories.SpecificationRepository.GetSpecificationObjects(HashSet`1 keys) in D:\VSO Agents\00TFS01-norriq-ip\_work\3\s\src\NLWI.Platforms.Dynamicweb9.Specs\Repositories\SpecificationRepository.cs:line 265
at NLWI.Platforms.Dynamicweb9.Specs.Services.CachedSpecificationService.b__12_1(HashSet`1 k) in D:\VSO Agents\00TFS01-norriq-ip\_work\3\s\src\NLWI.Platforms.Dynamicweb9.Specs\Services\CachedSpecificationService.cs:line 91
at NLWI.Core.Platform.Caching.DictionaryCaching.GetOrInsert[TKey,TVal](HashSet`1 keys, Func`2 buildCacheKey, Func`2 lookupMethod, CacheOptions cacheOptions)
at NLWI.Platforms.Dynamicweb9.Specs.Services.CachedSpecificationService.GetSpecificationObjects(HashSet`1 specificationObjectIdentifiers) in D:\VSO Agents\00TFS01-norriq-ip\_work\3\s\src\NLWI.Platforms.Dynamicweb9.Specs\Services\CachedSpecificationService.cs:line 88
at NLWI.Platforms.Dynamicweb9.Specs.Services.CachedProductSpecificationService.GetProductSpecifications(Dictionary`2 autoIdMappings) in D:\VSO Agents\00TFS01-norriq-ip\_work\3\s\src\NLWI.Platforms.Dynamicweb9.Specs\Services\CachedProductSpecificationService.cs:line 64
at NLWI.Platforms.Dynamicweb9.Specs.Services.CachedProductSpecificationService.GetProductSpecifications(HashSet`1 productAutoIds) in D:\VSO Agents\00TFS01-norriq-ip\_work\3\s\src\NLWI.Platforms.Dynamicweb9.Specs\Services\CachedProductSpecificationService.cs:line 59
at NLWI.Platforms.Dynamicweb9.Specs.Services.CachedProductSpecificationService.GetProductSpecifications(Int64 productAutoId) in D:\VSO Agents\00TFS01-norriq-ip\_work\3\s\src\NLWI.Platforms.Dynamicweb9.Specs\Services\CachedProductSpecificationService.cs:line 91
at NLWI.Platforms.Dynamicweb9.Specs.ProductSpecificationExtensionMethods.GetProductSpecifications(Int32 autoId) in D:\VSO Agents\00TFS01-norriq-ip\_work\3\s\src\NLWI.Platforms.Dynamicweb9.Specs\ProductSpecificationExtensionMethods.cs:line 48
at NLWI.Platforms.Dynamicweb9.Specs.ProductSpecificationExtensionMethods.GetProductSpecifications[T](RazorTemplateBase`1 page) in D:\VSO Agents\00TFS01-norriq-ip\_work\3\s\src\NLWI.Platforms.Dynamicweb9.Specs\ProductSpecificationExtensionMethods.cs:line 24
at CompiledRazorTemplates.Dynamic.cdfdfbedcdf.Execute()
at RazorEngine.Templating.TemplateBase.RazorEngine.Templating.ITemplate.Run(ExecuteContext context)
at RazorEngine.Templating.TemplateService.Run(ITemplate template, DynamicViewBag viewBag)
at RazorEngine.Templating.TemplateService.Parse(String razorTemplate, Object model, DynamicViewBag viewBag, String cacheName)
at RazorEngine.Razor.Parse[T](String razorTemplate, T model, String cacheName)
at Dynamicweb.Rendering.Template.RenderRazorTemplate()
@using System.Web
@using NORRIQ.Universal.Extensions
@using NORRIQ.Common8.Context
@using System.Web.Mvc.Html
@using Newtonsoft.Json
@using NORRIQ.Common8.Ecom
@using NORRIQ.Common8.Factory
@using NORRIQ.FavoriteList.Models
@using NORRIQ.FavoriteList.Services
@using NORRIQ.Common8.Razor;
@using Dynamicweb.Ecommerce.Common;
@using Dynamicweb.Ecommerce.Products
@using NLWI.Platforms.Dynamicweb9.Extensions
@using NLWI.Platforms.Dynamicweb9.Specs;
@using NLWI.Platforms.Dynamicweb9.Specs.ViewModels
@using NORRIQ.Universal.SessionStorage
@using StandardWebshop.CustomCode
@using StandardWebshop.CustomCode.ContactForm
@inherits Dynamicweb.Rendering.RazorTemplateBase<Dynamicweb.Rendering.RazorTemplateModel<Dynamicweb.Rendering.Template>>
@{
// EcomMedia settings
var image = NORRIQ.EcomMedia.Frontend.GetProductMedia(this);
var docs = NORRIQ.EcomMedia.Frontend.GetProductMedia(this);
//XPI
var specs = this.GetProductSpecifications();
var SpecImages = specs.GetAllByKey("Image");
var SpecVideos = specs.GetAllByKey("YouTubeLinks");
// Product
var ProductCurrency = Context.Currency.Symbol;
var Productsheet = Translate("Productsheet", "Datablad");
//var isProductB2C = NORRIQ.Common8.Factory.ObjectFactory.GetInstance<NORRIQ.Common8.Context.AreaItemSettings>().GetCurrentAreaValue<string>("B2CShopping");
// Related products
//var Columns = "col-xs-12 col-sm-4 col-md-3";
var ListMode = ObjectFactory.GetInstance<AreaItemSettings>().GetCurrentAreaValue<string>("ShowRelateproductsAsSlider");
// List mode
var mode = ObjectFactory.GetInstance<TemporarilySettings>().GetAndUpdate("listmode") ?? "" + Pageview.Area.Item["ProductlistMode"] + "";
//Favortites
var ProductAvailableFavoriteLists = (List<NORRIQ.FavoriteList.Models.FavoriteItemList>)GetValue("NIQ:FavoriteListsAvailable");
var ProductFavoriteListsWithProduct = (List<NORRIQ.FavoriteList.Models.FavoriteItemList>)GetValue("NIQ:FavoritListsWithProduct");
var ProductIsFavorite = ProductFavoriteListsWithProduct.Any();
var ProductListId = ProductAvailableFavoriteLists.Any() ? ProductAvailableFavoriteLists.First().Id : 0;
var ProductFavoriteTitle = Translate("Add to you favoriteliste");
string productId = GetString("Ecom:Product.ID");
string variantId = GetString("Ecom:Product.VariantID");
string languageId = GetString("Ecom:Product.LanguageID");
var productKey = new ProductKey(productId, variantId ?? "", languageId);
var contractFormService = ObjectFactory.GetInstance<ProductContactFormParagraphResolver>();
string contactFormParagraphId = contractFormService.GetContactParagraphLink(productKey);
var currentProduct = Dynamicweb.Ecommerce.Services.Products.GetProductById(productId, variantId, languageId);
var group = currentProduct != null && currentProduct.Groups.FirstOrDefault() != null ? currentProduct.Groups.FirstOrDefault() : null;
var tableListView = group != null ? group.ProductGroupFieldValues.FirstOrDefault(x => x.ProductGroupField.SystemName == "TableListView") : null;
var tableListViewColumnString = tableListView != null ? tableListView.Value.ToString() : null;
var tableListColumns = tableListViewColumnString != null ? tableListViewColumnString.Split(new[] { "," }, StringSplitOptions.RemoveEmptyEntries).Select(s => s.Trim()).ToList() : null;
var tableSpecs = new List<ProductSpecification>();
if (tableListColumns != null && tableListColumns.Any())
{
foreach (string header in tableListColumns)
{
var spec = specs.GetByKey(header);
if (spec != null)
{
tableSpecs.Add(spec);
}
}
}
}
<section class="" itemscope itemtype="http://schema.org/Product">
<div class="row">
<div class="col-xs-12 col-sm-6 product-media">
@if (specs.GetAllByKey("Image").Any())
{
<text>@if (SpecImages.Any())
{
<div class="product-images" id="product-images">
@foreach (var images in SpecImages)
{
<a class="product-image mfp-image" data-image-type="image" href="/Admin/Public/GetImage.ashx?Width=1000&Height=1000&Crop=5&Compression=80&Image=/Files/Images/XPI/@(images.Value)">
<img itemprop="image" class="img-responsive" src="/Admin/Public/GetImage.ashx?Width=400&Height=400&Crop=5&Compression=80&Image=/Files/Images/XPI/@(images.Value)" alt="@images.Caption" />
</a>
}
@foreach (var video in SpecVideos)
{
<a class="product-image mfp-iframe" data-image-type="video" href="@GetYouTubeLink(video.Value)">
<img itemprop="image" width="400" class="img-responsive" src="@GetYouTubeImageUrl(video.Value)" />
</a>
}
</div>
if (SpecImages.Count() > 0 || SpecImages.Any() && SpecVideos.Any())
{
<div id="product-images-thumbs" class="product-thumbs">
@foreach (var images in SpecImages)
{
<div class="product-thumb">
<div class="product-thumb-inner" data-thumb-type="image">
<img class="img-responsive" src="/Admin/Public/GetImage.ashx?Width=110&Height=110&Crop=5&Compression=80&Image=/Files/Images/XPI/@(images.Value)" alt="@images.Caption" />
</div>
</div>
}
@foreach (var video in SpecVideos)
{
<div class="product-thumb">
<div class="product-thumb-inner" data-thumb-type="video">
<img class="img-responsive" src="@GetYouTubeImageUrl(video.Value)" alt="@video.Caption" />
</div>
</div>
}
</div>
}
}
else
{
<div class="product-images">
<div class="product-image">
<div class="product-image-inner">
<img class="img-responsive" src="/Admin/Public/GetImage.ashx?&Width=400&Height=400&Crop=5&Compression=80&Image=/Files/Images/Ecom/default.png" alt="@Translate("No image","No image")" />
</div>
</div>
</div>
}
@functions
{
string GetYouTubeLink(string url)
{
var uri = new UriBuilder(url).Uri;
var query = HttpUtility.ParseQueryString(uri.Query);
var videoId = query["v"];
return "https://www.youtube.com" + uri.AbsolutePath + "?v=" + videoId;
}
string GetYouTubeImageUrl(string url)
{
var uri = new UriBuilder(url).Uri;
//var uri = new Uri(url);
var query = HttpUtility.ParseQueryString(uri.Query);
var videoId = query["v"];
if (string.IsNullOrEmpty(videoId))
{
return "https://img.youtube.com/vi/" + uri.AbsolutePath.Replace("/", "") + "/0.jpg";
}
return "https://img.youtube.com/vi/" + videoId + "/0.jpg";
}
}
</text>
}
else
{
<text>@inherits Dynamicweb.Rendering.RazorTemplateBase<Dynamicweb.Rendering.RazorTemplateModel<Dynamicweb.Rendering.Template>>
@if (image.GetImages().Count() > 1 || image.GetImages().Any() && !String.IsNullOrEmpty(GetString("Ecom:Product:Field.YoutubeVideoID")) || !String.IsNullOrEmpty(GetString("Ecom:Product:Field.VimeoVideoID")))
{
<div class="product-images" id="product-images">
@foreach (var images in image.GetImages())
{
<a class="product-image mfp-zoom" href="/Admin/Public/GetImage.ashx?Width=1000&Height=1000&Crop=5&Compression=80&Image=@(images.Url)">
<img itemprop="image" class="img-responsive" src="/Admin/Public/GetImage.ashx?Width=400&Height=400&Crop=5&Compression=80&Image=@(images.Url)" alt="@GetString("Ecom:Product.Name")" />
</a>
}
@if (!String.IsNullOrEmpty(GetString("Ecom:Product:Field.YoutubeVideoID")))
{
var YoutubeSrc = "https://www.youtube-nocookie.com/embed/" + GetString("Ecom:Product:Field.YoutubeVideoID") + "?rel=0";
<div class="product-image">
<iframe src="@YoutubeSrc" width="640" height="360" frameborder="0" allowfullscreen></iframe>
</div>
}
@if (!String.IsNullOrEmpty(GetString("Ecom:Product:Field.VimeoVideoID")))
{
var VimeoSrc = "https://player.vimeo.com/video/" + GetString("Ecom:Product:Field.VimeoVideoID") + "?byline=0";
<div class="product-image">
<iframe src="@VimeoSrc" width="640" height="360" frameborder="0" webkitallowfullscreen mozallowfullscreen allowfullscreen></iframe>
</div>
}
</div>
<div id="product-images-thumbs" class="product-thumbs">
@foreach (var images in image.GetImages())
{
<div class="product-thumb">
<div class="product-thumb-inner" data-thumb-type="image">
<img class="img-responsive" src="/Admin/Public/GetImage.ashx?Width=110&Height=110&Crop=5&Compression=80&Image=@(images.Url)" alt="@GetString("Ecom:Product.Name")" />
</div>
</div>
}
@if (!String.IsNullOrEmpty(GetString("Ecom:Product:Field.YoutubeVideoID")))
{
<div class="product-thumb">
<div class="product-thumb-inner" data-thumb-type="video">
<span class="product-thumb-play"><i class="icon-youtube icon-5x" aria-hidden="true"></i></span>
</div>
</div>
}
@if (!String.IsNullOrEmpty(GetString("Ecom:Product:Field.VimeoVideoID")))
{
<div class="product-thumb">
<div class="product-thumb-inner" data-thumb-type="video">
<span class="product-thumb-play"><i class="icon-vimeo icon-5x" aria-hidden="true"></i></span>
</div>
</div>
}
</div>
}
else
{
<div class="product-images product-images-single">
<a class="product-image mfp-zoom" href="/Admin/Public/GetImage.ashx?Width=1000&Height=1000&Crop=5&Compression=80&Image=@(image.GetFirstImage().Url)">
<img class="img-responsive" alt="@GetString("Ecom:Product.Name")" src="/Admin/Public/GetImage.ashx?Width=400&Height=400&Crop=5&Compression=80&Image=@(image.GetFirstImage().Url)" />
</a>
</div>
}</text>
}
</div>
<div class="col-xs-12 col-sm-6 product-data ">
<h1 itemprop="name" class="title-styled">
@GetString("Ecom:Product.Name")
</h1>
@*@if (Pageview.Security.UserLoggedIn)
{
<div class="product-detail async-price" data-product-key='@(this.GetJsonPriceKey())' data-product-retail-price='@(this.GetJsonRetailPrice())'>
<div class="product-info">
<span class="product-number">
<span class="name">
@Translate("Product Number", "Product Number"):
</span>
<span class="value">
@GetString("Ecom:Product.Number")
</span>
</span>
<span class="product-stock async-price-stock">
<i class="icon-async icon-pulse"></i>
</span>
</div>
<div class="product-offer">
<div class="product-price-info">
<p class="product-price async-price-total">
<i class="icon-async icon-pulse"></i>
</p>
</div>
<p class="product-price-type">
@Translate("Unitprice without VAT", "Unitprice without VAT")
</p>
@if (GetLoop("VariantGroups").Any())
{
<text>@inherits Dynamicweb.Rendering.RazorTemplateBase<Dynamicweb.Rendering.RazorTemplateModel<Dynamicweb.Rendering.Template>>
@using StandardWebshop.CustomCode.ViewModels.Variants;
@using Newtonsoft.Json;
@{
var variants = this.GetVariantTree();
var settings = new JsonSerializerSettings
{
Converters = new List<JsonConverter> { new VariantDimensionTreeNodeJsonConverter() },
Formatting = Formatting.Indented,
ReferenceLoopHandling = ReferenceLoopHandling.Ignore
};
string variantsJson = JsonConvert.SerializeObject(variants, settings);
}
<div id="variant-container">
<div data-bind="foreach: { data: Dimensions, as: 'DimensionValues' }">
<label for="selecta">@Translate("variant_label", "Variant")</label>
<select class="form-control" data-bind="disable: !DimensionValues.length,
options: DimensionValues,
optionsText: 'OptionName',
value: $root.SelectedVariants[$index()],
optionsCaption: DimensionValues.length ? '@Translate("variant_chose_variant", "Vælg variant")' : '@Translate("variant_chose_previous_variant", "Vælg forrige variant")'" id="selecta"></select>
</div>
</div>
<!-- Build the JSON object -->
<script append="true">
var globalVariantTree = @variantsJson;
$(document).ready(function () {
var variantControl = new AppStart.VariantControl({
VariantTree: @variantsJson,
$variantContainer: $('#variant-container')
});
variantControl.Render();
var variantControl = new AppStart.VariantSelectionHandler(AppStart.VariantSelectionHandlerModes.ReloadOnVariantSelected);
})
</script></text>
}
<div class="product-buying">
<form class="form-inline" id="prodform_@GetString("Ecom:Product:Page.ID")" name="prodform_@GetString("Ecom:Product:Page.ID")" method="post" action="@GetGlobalValue("Global:Pageview.Url.Raw")">
@GetString("Ecom:Product.Form.Clean")
<label for="quantity" class="sr-only">@Translate("Qty", "Qty")</label>
<div class="input-group input-group-lg">
<input name="quantity" id="quantity" value="1" type="text" class="form-control" autocomplete="off" />
<span class="input-group-btn">
<button class="btn btn-primary" role="button" type="submit" @((GetLoop("VariantGroups").Any() && String.IsNullOrEmpty(GetString("Ecom:Product.VariantID")) ? "disabled=\"disabled\"" : ""))>
<i class="icon-minicart" aria-hidden="true"></i> <span class="product-added-text">@Translate("Add to cart", "Add to cart")</span>
</button>
</span>
</div>
</form>
@if (!GetLoop("VariantGroups").Any())
{
<div class="product-favorite">
<a href="javascript:void(0)" class="js-favorite-toggle" )"
data-favorite-list-id="@ProductListId"
data-is-favorite="@(ProductIsFavorite ? "true" : "false")"
data-product-id="@(GetString("Ecom:Product.ID"))"
data-product-language-id="@(GetString("Ecom:Product.LanguageID"))"
data-product-variant-id="@(GetString("Ecom:Product.VariantID"))">
@if (ProductIsFavorite)
{
<i class="icon-favorite-added"></i> @Translate("Remove favorite", "Remove favorite")
}
else
{
<i class="icon-favorite"></i> @Translate("Make favorite", "Make favorite")
}
</a>
</div>
}
</div>
</div>
</div>
}*@
<div><div class="product-detail">
<div class="product-info">
<span class="product-number">
<span class="name">
@Translate("Product Number", "Product Number"):
</span>
<span class="value">
@GetString("Ecom:Product.Number")
</span>
</span>
<span class="pull-rightXXX">
@*<a class="" rel="nofollow" href="@Navigation.GetUrlByNavigationTag("productsheet")?GroupID=@GetString("Ecom:Product.PrimaryOrFirstGroupID")&ProductID=@GetString("Ecom:Product.ID")&VariantID=@GetString("Ecom:Product.VariantID")&PDF=true&Filename=@GetString("Ecom:Product.Name")_@(GetString("Ecom:Product.Number")).pdf"><i class="icon-print" aria-hidden="true"></i> @Translate("Print PDF")</a>*@
</span>
@*<span class="product-stock">
<i class="icon-stock @GetString("Ecom:Product:Stock.DeliveryUnit")" aria-hidden="true"></i> <span class="stock-label-text">@GetString("Ecom:Product:Stock.Text")</span>
</span>*@
</div>
<div class="product-offer">
@*<div class="product-price-info">
<p class="product-price">
<span class="product-currency">@GetString("Ecom:Product.Currency.Code")</span> @GetString("Ecom:Product.Price.PriceWithVAT")
</p>
</div>*@
@if (GetLoop("VariantGroups").Any())
{
<text>@inherits Dynamicweb.Rendering.RazorTemplateBase<Dynamicweb.Rendering.RazorTemplateModel<Dynamicweb.Rendering.Template>>
@using StandardWebshop.CustomCode.ViewModels.Variants;
@using Newtonsoft.Json;
@{
var variants = this.GetVariantTree();
var settings = new JsonSerializerSettings
{
Converters = new List<JsonConverter> { new VariantDimensionTreeNodeJsonConverter() },
Formatting = Formatting.Indented,
ReferenceLoopHandling = ReferenceLoopHandling.Ignore
};
string variantsJson = JsonConvert.SerializeObject(variants, settings);
}
<div id="variant-container">
<div data-bind="foreach: { data: Dimensions, as: 'DimensionValues' }">
<label for="selecta">@Translate("variant_label", "Variant")</label>
<select class="form-control" data-bind="disable: !DimensionValues.length,
options: DimensionValues,
optionsText: 'OptionName',
value: $root.SelectedVariants[$index()],
optionsCaption: DimensionValues.length ? '@Translate("variant_chose_variant", "Vælg variant")' : '@Translate("variant_chose_previous_variant", "Vælg forrige variant")'" id="selecta"></select>
</div>
</div>
<!-- Build the JSON object -->
<script append="true">
var globalVariantTree = @variantsJson;
$(document).ready(function () {
var variantControl = new AppStart.VariantControl({
VariantTree: @variantsJson,
$variantContainer: $('#variant-container')
});
variantControl.Render();
var variantControl = new AppStart.VariantSelectionHandler(AppStart.VariantSelectionHandlerModes.ReloadOnVariantSelected);
})
</script></text>
}
@*<div class="product-buying">
<form class="form-inline" id="prodform_@GetString("Ecom:Product:Page.ID")" name="prodform_@GetString("Ecom:Product:Page.ID")" method="post" action="@GetGlobalValue("Global:Pageview.Url.Raw")">
@GetString("Ecom:Product.Form.Clean")
<label for="quantity" class="sr-only">@Translate("Qty")</label>
<div class="input-group input-group-lg">
<input name="quantity" id="quantity" value="1" type="text" class="form-control" autocomplete="off" />
<span class="input-group-btn">
<button class="btn btn-primary" role="button" type="submit" @((GetLoop("VariantGroups").Any() && String.IsNullOrEmpty(GetString("Ecom:Product.VariantID")) ? "disabled=\"disabled\"" : ""))>
<i class="icon-minicart" aria-hidden="true"></i> <span class="product-added-text">@Translate("Add to cart")</span>
</button>
</span>
</div>
</form>
</div>*@
</div>
</div></div>
</div>
<div class="col-xs-12 col-sm-6 product-tabs">
<ul class="nav nav-tabs product-nav-tabs" role="tablist">
@if (!String.IsNullOrWhiteSpace(GetString("Ecom:Product.LongDescription")) || specs.GetByKey("ProductDescription").Value != null)
{
<li role="presentation" class="active">
<a href="#desc" aria-controls="desc" role="tab" data-toggle="tab">
@Translate("Description", "Description")
</a>
</li>
}
@if (specs.GetByGroup("Specifikationer").Any())
{
<li role="presentation">
<a href="#specs" aria-controls="specs" role="tab" data-toggle="tab">
@Translate("Specifications")
</a>
</li>
}
@if (docs.HasItem("Documents") || specs.GetAllByKey("Datablad").Any() || specs.GetAllByKey("Sikkerhedsdatablad").Any())
{
<li role="presentation">
<a href="#docs" aria-controls="docs" role="tab" data-toggle="tab">
@Translate("Documents")
</a>
</li>
}
@if (!string.IsNullOrWhiteSpace(contactFormParagraphId))
{
<li role="presentation">
<a href="#product-contact-me" aria-controls="docs" role="tab" data-toggle="tab">
@Translate("Contact Me")
</a>
</li>
}
</ul>
<div class="tab-content product-tab-content">
@if (!String.IsNullOrWhiteSpace(GetString("Ecom:Product.LongDescription")) || specs.GetByKey("ProductDescription").Value != null)
{
<div role="tabpanel" class="tab-pane active" id="desc" itemprop="description">
@GetString("Ecom:Product.LongDescription")
@specs.GetByKey("ProductDescription").Value
</div>
}
@if (specs.GetByGroup("Specifikationer").Any())
{
<div role="tabpanel" class="tab-pane" id="specs">
<table class="table table-striped">
<tbody>
@foreach (var spec in specs.GetByGroup("Specifikationer").GroupBy(a => a.Key))
{
<tr>
<td>
@spec.First().Caption
</td>
<td>
@String.Join(", ", spec.Select(a => a.Value))
</td>
</tr>
}
</tbody>
</table>
</div>
}
@if (docs.HasItem("Documents") || specs.GetAllByKey("Datablad").Any() || specs.GetAllByKey("Sikkerhedsdatablad").Any())
{
<div role="tabpanel" class="tab-pane" id="docs">
@if (docs.HasItem("Documents"))
{
foreach (var item in docs.GetItems("Documents"))
{
<p>
<a href="@item.Url">
@item.Url.Split('/').Last()
</a> <small>(@item.FileSizeInMb)</small>
</p>
}
}
@foreach (var specFile in specs.GetAllByKey("Datablad"))
{
var name = Translate(specFile.Caption);
<p>
<a download="@name" href="/Files/Images/XPI/@(specFile.Value)" title="@name">
@specFile.GetReferenceSpecification().GetByKey("OriginalFilename").Value
</a>
</p>
}
@foreach (var specFile in specs.GetAllByKey("Sikkerhedsdatablad"))
{
var name = Translate(specFile.Caption);
<p>
<a download="@name" href="/Files/Images/XPI/@(specFile.Value)" title="@name">
@specFile.GetReferenceSpecification().GetByKey("OriginalFilename").Value
</a>
</p>
}
</div>
}
@if (!string.IsNullOrWhiteSpace(contactFormParagraphId))
{
<div role="tabpanel" class="tab-pane" id="product-contact-me" data-product-name="@GetString("Ecom:Product.Name")" data-product-number="@GetString("Ecom:Product.Number")">
<p>@Translate("ContactMeMessage", "Hvis du har spørgsmål til produktet, udfyld nedenstående formular og vi vender tilbage hurtigst muligt.")</p>
@RenderParagraphContent(int.Parse(contactFormParagraphId))
<p class="error hidden" id="error-message">@Translate("SubmitFormerror-message", "Noget gik galt, forsøg venligst igen.")</p>
</div>
}
</div>
</div>
@if (tableSpecs.Any())
{
<div class="col-xs-12 product-specs">
<h2 class="title-styled">
@Translate("Specifications")
</h2>
<table class="table table-condensed productlist-table js-product-table plpx-table">
<thead>
<tr>
@foreach (var spec in tableSpecs)
{
<th>
<strong>@spec.Caption</strong>
</th>
}
</tr>
</thead>
<tbody>
<tr>
@foreach (var spec in tableSpecs)
{
<td>
@String.Join(", ", spec.Value)
</td>
}
</tr>
</tbody>
</table>
</div>
}
<div class="col-xs-12 product-related">
@if (GetLoop("ProductRelatedGroups").Any())
{
foreach (var grp in GetLoop("ProductRelatedGroups"))
{
if (grp.GetLoop("RelatedProducts").Any())
{
var RelatedRow = "productlist-grid-flex";
if (grp.GetLoop("RelatedProducts").Count > 4)
{
RelatedRow = "slick-middle-arrow slick-flex related-product-slider";
}
<h2 class="title-styled">
@grp.GetString("Ecom:Product:RelatedGroup.Name")
</h2>
<div class="@RelatedRow" id="slide-products-@grp.GetString("Ecom:Product:RelatedGroup.GroupID")">
@foreach (var product in grp.GetLoop("RelatedProducts"))
{
if (Pageview.Security.UserLoggedIn)
{
<text>@inherits Dynamicweb.Rendering.RazorTemplateBase<Dynamicweb.Rendering.RazorTemplateModel<Dynamicweb.Rendering.Template>>
@using NLWI.Platforms.Dynamicweb9.Extensions;
@{
// Image takes from either DW or XPI
var media = NORRIQ.EcomMedia.Frontend.GetProductMedia(product);
var ProductSpecs = product.GetProductSpecifications();
var Image = ProductSpecs.GetAllByKey("Image").Any() ? "/Files/Images/XPI/" + ProductSpecs.GetByKey("Image").Value : media.GetFirstImage().Url;
// Favoritelist
var availableFavoriteLists = (List<NORRIQ.FavoriteList.Models.FavoriteItemList>)product.GetValue("NIQ:FavoriteListsAvailable");
var favoriteListsWithProduct = (List<NORRIQ.FavoriteList.Models.FavoriteItemList>)product.GetValue("NIQ:FavoritListsWithProduct");
var isFavorite = favoriteListsWithProduct.Any();
var listId = availableFavoriteLists.Any() ? availableFavoriteLists.First().Id : 0;
var favoriteLabel = isFavorite ? Translate("Remove from favorites") : Translate("Add to favorites");
}
<div class="@(String.IsNullOrEmpty(Pageview.CurrentParagraph.Item["ProductlistGrid"].ToString()) ? Pageview.Area.Item["ProductlistGrid"] : Pageview.CurrentParagraph.Item["ProductlistGrid"]) async-price js-favProduct" data-product-display="flex" data-product-key='@(product.GetJsonPriceKey())' data-product-retail-price='@(product.GetJsonRetailPrice())'>
<div class="productlist-grid-product@(product.GetInteger("Products.LoopCounter") < 7 ? " in-view" : "") hvr-glow">
<a class="productlist-grid-image" href="@product.GetString("NIQ:ProductUrl")">
<img src="/Admin/Public/GetImage.ashx?Width=200&Height=200&Crop=5&Compression=80&Image=@Image"
class="img-responsive"
alt="@product.GetString("Ecom:Product.Name")" />
</a>
<a href="@product.GetString("NIQ:ProductUrl")" class="productlist-grid-name">
<span>@product.GetString("Ecom:Product.Name")</span>
</a>
<div class="productlist-grid-info">
<span class="productlist-grid-number">
@Translate("Product Number") <span itemprop="sku">@product.GetString("Ecom:Product.Number")</span>
</span>
<span class="productlist-grid-stock async-price-stock" itemprop="availability"></span>
</div>
<div class="productlist-grid-offer">
<span class="productlist-grid-price async-price-total" itemprop="price">
<span class="icon-async icon-pulse"></span>
</span>
@if (!product.GetLoop("VariantGroups").Any())
{
<form class="form" id="prodform_@product.GetString("Ecom:Product.Number")" name="prodform_@product.GetString("Ecom:Product.Number")" method="post" action="@GetGlobalValue("Global:Pageview.Url.Raw")">
@product.GetString("Ecom:Product.Form.Clean")
<button role="button" type="submit" class="btn btn-primary">
<span class="product-added-text">@Translate("Add to cart")</span>
</button>
</form>
}
else
{
<a href="@product.GetString("NIQ:ProductUrl")" class="btn btn-info">
@Translate("Choose Variant")
</a>
}
</div>
@if (!product.GetLoop("VariantGroups").Any())
{
<div class="productlist-grid-buttons">
<a href="javascript:void(0)"
class="js-favorite-toggle productlist-grid-favorite"
title="@favoriteLabel"
data-favorite-list-id="@listId"
data-is-favorite="@(isFavorite ? "true" : "false")"
data-product-id="@(product.GetString("Ecom:Product.ID"))"
data-product-language-id="@(product.GetString("Ecom:Product.LanguageID"))"
data-product-variant-id="@(product.GetString("Ecom:Product.VariantID"))">
<i class="icon-favorite-toggle" aria-hidden="true"></i> <span class="sr-only">@favoriteLabel</span>
</a>
</div>
}
</div>
</div>
</text>
}
else
{
<text>@inherits Dynamicweb.Rendering.RazorTemplateBase<Dynamicweb.Rendering.RazorTemplateModel<Dynamicweb.Rendering.Template>>
@{
// Image takes from either DW or XPI
var media = NORRIQ.EcomMedia.Frontend.GetProductMedia(product);
var ProductSpecs = product.GetProductSpecifications();
var Image = ProductSpecs.GetAllByKey("Image").Any() ? "/Files/Images/XPI/" + ProductSpecs.GetByKey("Image").Value : media.GetFirstImage().Url;
}
<div class="@(String.IsNullOrEmpty(Pageview.CurrentParagraph.Item["ProductlistGrid"].ToString()) ? Pageview.Area.Item["ProductlistGrid"] : Pageview.CurrentParagraph.Item["ProductlistGrid"])" data-product-display="flex">
<div class="productlist-grid-product@(product.GetInteger("Products.LoopCounter") < 7 ? " in-view" : "") hvr-glow" itemscope itemtype="http://schema.org/Product">
<a class="productlist-grid-image" href="@product.GetString("NIQ:ProductUrl")" itemprop="url">
<img src="/Admin/Public/GetImage.ashx?Width=200&Height=200&Crop=5&Compression=80&Image=@Image"
class="img-responsive"
alt="@product.GetString("Ecom:Product.Name")"
itemprop="image" />
</a>
<a href="@product.GetString("NIQ:ProductUrl")" class="productlist-grid-name" itemprop="url">
<span itemprop="name">@product.GetString("Ecom:Product.Name")</span>
</a>
<span class="productlist-grid-number">
@Translate("Varenr.") <span itemprop="mpn">@product.GetString("Ecom:Product.Number")</span>
</span>
@* Include if shop has B2C shopping *@
@*<div class="productlist-grid-info">
<span class="productlist-grid-number">
@Translate("Product Number") <span itemprop="mpn">@product.GetString("Ecom:Product.Number")</span>
</span>
<span class="productlist-grid-stock">
<i class="icon-stock @product.GetString("Ecom:Product:Stock.DeliveryUnit")" aria-hidden="true"></i>
<span itemprop="availability" href="http://schema.org/InStock" class="stock-label-text">@product.GetString("Ecom:Product:Stock.Text")</span>
</span>
</div>
<div class="productlist-grid-offer" itemprop="offers" itemscope itemtype="http://schema.org/Offer">
<span class="productlist-grid-price">
<meta itemprop="priceCurrency" content="@product.GetString("Ecom:Product.Currency.Code")" />
<span itemprop="price">
@product.GetString("Ecom:Product.Price.PriceWithVAT")
</span>
</span>
@if (!product.GetLoop("VariantGroups").Any())
{
<form class="form" id="prodform_@product.GetString("Ecom:Product:Page.ID")" name="prodform_@product.GetString("Ecom:Product:Page.ID")" method="post" action="@GetGlobalValue("Global:Pageview.Url.Raw")">
@product.GetString("Ecom:Product.Form.Clean")
<button role="button" type="submit" class="btn btn-primary">
<span class="product-added-text">@Translate("Add to cart")</span>
</button>
</form>
}
else
{
<a href="@product.GetString("NIQ:ProductUrl")" class="btn btn-info">
@Translate("Choose Variant")
</a>
}
</div>*@
</div>
</div></text>
}
}
</div>
}
}
}
</div>
</div>
</section>
<script append="true">
$(document).ready(function () {
var pdp = new AppStart.Product({
$asyncTemplate: $("#async-price"),
productPrimaryImage: '#product-images',
productImgThumb: '#product-images-thumbs',
$productImages: $('.product-images'),
$asyncPrices: $('.async-price'),
$relatedProducts: $('.related-product-slider'),
qtySelector: '.qty-input',
isLoggedIn: @Pageview.Security.UserLoggedIn.ToString().ToLower()
});
pdp.init();
});
</script>
@if (Pageview.Security.UserLoggedIn)
{
<script append="true">
$(document).ready(function () {
var favorite = new AppStart.Favoritelist({
isFavoriteMode: false,
$allFavoriteIcons: $('.js-favorite-toggle'),
$productParent: $(),
defaultFavoriteName: "Favorites"
});
favorite.init();
});
</script>
<script id="async-price" type="text/x-jsrender">
<div data-target=".async-price-unit">
{{if NetUnitPrice.PriceWithoutVat != UnitPrice.PriceWithoutVat}}
{{>UnitPrice.PriceWithoutVat.formatMoney(2,',','.')}}
{{/if}}
</div>
<div data-target=".async-price-stock">
{{if Inventory > 1 }}
<i class="icon-stock icon-green" title="{{>Inventory}}"></i> <span class="stock-label-text">@Translate("In Stock")</span>
{{else Inventory == 1}}
<i class="icon-stock icon-yellow" title="{{>Inventory}}"></i> <span class="stock-label-text">@Translate("Few in stock")</span>
{{else}}
<i class="icon-stock icon-red" title="0"></i> <span class="stock-label-text">@Translate("Out of stock")</span>
{{/if}}
</div>
<div data-target=".async-price-total">
{{>NetUnitPrice.PriceWithoutVat.formatMoney(2,',','.')}}
{{if error != null }}
<i class="icon-warning" title="@Translate("There was a technical problem so your specific price could not be calculated. The price you see is retail price.")"></i>
{{/if}}
</div>
</script>
<script type="text/x-jsrender" id="autoaddfeedbackloading">
<i class="icon-async icon-pulse"></i>
</script>
<script type="text/x-jsrender" id="autoaddfeedbacksuccess">
<i class="icon-added" title="@Translate("Product added to cart")"></i>
</script>
<script type="text/x-jsrender" id="autoaddfeedbackerror">
{{if error == "badinput"}}
<i class="icon-warning" title="@Translate("Please enter a numerical value")"></i>
{{else error == "servererror"}}
<i class="icon-warning" title="@Translate("An server error occured your cart was not updated")"></i>
{{else}}
<i class="icon-warning"></i>
{{/if}}
</script>
}