Error executing template "Designs/Swift/Paragraph/Custom__KeystoneSingleFilePublisher.cshtml"
System.NullReferenceException: Object reference not set to an instance of an object.
   at CompiledRazorTemplates.Dynamic.RazorEngine_0b4dc5a6c4954fb08a2db01140ebb9da.Execute() in E:\Domains\Sites\portal.keystonerv.com\Files\Templates\Designs\Swift\Paragraph\Custom__KeystoneSingleFilePublisher.cshtml:line 56
   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 Dynamicweb.Rendering.ViewModelTemplate<Dynamicweb.Frontend.ParagraphViewModel> 2 @using System.IO 3 @using System.Text 4 @functions 5 { 6 static readonly string[] SupportedImageFormats = new string[] {".jpg", ".jpeg", ".webp", ".png", ".gif", ".bmp", ".tiff", ".pdf"}; 7 static readonly string[] SupportedDocumentFormats = new string[] {".docx", ".xlsx", ".ppt", ".pptx", ".txt", ".msg", ".zip"}; 8 static readonly string[] SupportedVideoFormats = new string[] {".mp4", ".avi", ".mov", ".webm", ".ogg"}; 9 static readonly string[] SupportedPlayedVideoFormats = new string[] {".mp4", ".webm", ".ogg"}; 10 11 private static bool IsValidDirectory(string path) 12 { 13 if (string.IsNullOrEmpty(path)) return false; 14 15 var fullPath = Dynamicweb.Context.Current.Server.MapPath(path); 16 17 return !string.IsNullOrEmpty(fullPath) && Directory.Exists(fullPath); 18 } 19 20 private static bool IsFileSupported(string fileExtension) 21 { 22 return IsImage(fileExtension) || IsVideo(fileExtension) || IsDocument(fileExtension); 23 } 24 25 private static bool IsImage(string fileExtension) 26 { 27 return SupportedImageFormats.Contains(fileExtension); 28 } 29 30 private static bool IsVideo(string fileExtension) 31 { 32 return SupportedVideoFormats.Contains(fileExtension); 33 } 34 35 private static bool IsVideoPlayable(string fileExtension) 36 { 37 return SupportedPlayedVideoFormats.Contains(fileExtension); 38 } 39 40 private static string GetVideoType(string fileExtension) 41 { 42 return IsVideoPlayable(fileExtension) ? $"video/{SupportedPlayedVideoFormats.FirstOrDefault(s => s == fileExtension)?.Replace(".",string.Empty)}" : string.Empty; 43 } 44 45 private static bool IsDocument(string fileName) 46 { 47 return SupportedDocumentFormats.Any(s => fileName.EndsWith(s, StringComparison.OrdinalIgnoreCase)); 48 } 49 } 50 51 @{ 52 var queryStringParameter = Model.Item.GetString("QuerystringParameter"); 53 var requestFile = Dynamicweb.Context.Current.Request.QueryString.Get(queryStringParameter); 54 var folder = Model.Item.GetString("Folder"); 55 56 var isValidFilePath = !requestFile.Contains("../"); 57 var combinedPath = string.Empty; 58 var fullPath = string.Empty; 59 60 if (isValidFilePath) 61 { 62 combinedPath = requestFile.StartsWith("/") ? $"{folder}{requestFile}" : Path.Combine(folder, requestFile); 63 fullPath = Dynamicweb.Context.Current.Server.MapPath(combinedPath); 64 } 65 66 var file = !string.IsNullOrEmpty(fullPath) && File.Exists(fullPath) ? new FileInfo(fullPath) : null; 67 var isFileSupported = file != null ? IsDocument(file.Extension) || IsImage(file.Extension) : false; 68 } 69 70 @if (isFileSupported) 71 { 72 var title = Model.Item.GetString("Title"); 73 var hideTitle = Model.Item.GetBoolean("HideTitle"); 74 75 var contentPadding = Model.Item.GetRawValueString("contentPadding", ""); 76 contentPadding = contentPadding == "none" ? "p-3 px-xl-3 py-xl-4" : contentPadding; 77 contentPadding = contentPadding == "small" ? "p-3 p-xl-4" : contentPadding; 78 contentPadding = contentPadding == "large" ? "p-4 p-xl-5" : contentPadding; 79 80 var theme = !string.IsNullOrWhiteSpace(Model.Item.GetRawValueString("Theme")) ? " theme " + Model.Item.GetRawValueString("Theme").Replace(" ", "").Trim().ToLower() : ""; 81 82 var layout = Model.Item.GetString("Layout"); 83 var showDownloadButton = Model.Item.GetBoolean("ShowDownloadButton"); 84 var fileLength = file.Length > 0 ? $"{(file.Length / 1024):N0} KB" : $"{file.Length}"; 85 86 var downloadButtonText = Model.Item.GetString("DownloadButtonText"); 87 var downloadButtonIcon = Model.Item.GetRawValueString("DownloadButtonIcon"); 88 var downloadButtonType = Model.Item.GetString("DownloadButtonType", "primary"); 89 var downloadLink = $"/Admin/Public/download.aspx?ForceDownload=true&File={combinedPath}"; 90 91 <div class="@(contentPadding) @(theme) item_@Model.Item.SystemName.ToLower()"> 92 93 @if (!string.IsNullOrEmpty(title) && !hideTitle) 94 { 95 <h2 class="h5 mb-4">@title</h2> 96 } 97 98 @if (layout == "thumbnail") 99 { 100 var alignment = Model.Item.GetString("Alignment", "center"); 101 var columnSize = Model.Item.GetInt32("ColumnSize"); 102 103 <div class="row justify-content-@(alignment)"> 104 <div class="col-@(columnSize)"> 105 <a class="text-decoration-none" href="@combinedPath"> 106 107 <div class="d-flex justify-content-center align-items-center position-relative w-100 p-2 mb-3" style="background-color: hsl(0, 0%, 93%);"> 108 109 @if (IsImage(file.Extension)) 110 { 111 var imageWidth = Model.Item.GetInt32("ImageWidth"); 112 var imageRatio = Model.Item.GetString("ImageAspectRatio", "100%"); 113 var imgPath = $"/Admin/Public/GetImage.ashx?image={combinedPath}&width={imageWidth}&format=webp"; 114 115 <div class="ratio" style="--bs-aspect-ratio: @imageRatio;"> 116 <img class="mw-100 mh-100 align-self-center" alt="@file.Name" src="@imgPath" loading="lazy"> 117 </div> 118 } 119 else if (IsDocument(file.Extension)) 120 { 121 var iconPath = "/Files/Templates/Designs/Swift/Assets/icons/file.svg"; 122 123 <span class="icon-6"> 124 @ReadFile(iconPath) 125 </span> 126 } 127 128 </div> 129 130 </a> 131 132 <div class="row d-flex justify-content-between"> 133 134 <div class="flex-fill"> 135 <h3 class="h6" style="word-break: break-all">@file.Name</h3> 136 </div> 137 138 <div class="fs-6 opacity-50"> 139 @fileLength 140 </div> 141 142 </div> 143 144 @if (showDownloadButton && (!string.IsNullOrEmpty(downloadButtonText) || !string.IsNullOrEmpty(downloadButtonIcon))) 145 { 146 <div class="row mt-2"> 147 <a class="btn btn-@downloadButtonType d-flex justify-content-center gap-1" href="@downloadLink"> 148 149 @if (!string.IsNullOrEmpty(downloadButtonIcon)) 150 { 151 <span class="icon-2"> 152 @ReadFile(downloadButtonIcon) 153 </span> 154 } 155 156 @if (!string.IsNullOrEmpty(downloadButtonText)) 157 { 158 <span>@downloadButtonText</span> 159 } 160 161 </a> 162 </div> 163 } 164 </div> 165 </div> 166 } 167 else if (layout == "text") 168 { 169 <div class="d-flex justify-content-start align-items-center gap-4"> 170 <a class="text-decoration-none" href="@combinedPath"> 171 <span class="">@file.Name</span> 172 <span class="fs-6 opacity-50 ms-2">@fileLength</span> 173 </a> 174 175 @if (showDownloadButton && (!string.IsNullOrEmpty(downloadButtonText) || !string.IsNullOrEmpty(downloadButtonIcon))) 176 { 177 <a class="btn btn-sm btn-@downloadButtonType d-flex justify-content-center gap-1" href="@downloadLink"> 178 179 @if (!string.IsNullOrEmpty(downloadButtonIcon)) 180 { 181 <span class="icon-2"> 182 @ReadFile(downloadButtonIcon) 183 </span> 184 } 185 186 @if (!string.IsNullOrEmpty(downloadButtonText)) 187 { 188 <span>@downloadButtonText</span> 189 } 190 191 </a> 192 } 193 </div> 194 } 195 </div> 196 } 197 else if(Pageview.IsVisualEditorMode) 198 { 199 <div class="alert alert-info" role="alert"> 200 <span>@Translate("Keystone single file publisher: Edit this column to configure")</span> 201 </div> 202 }