Error executing template "Designs/Swift/Paragraph/CPQ_Inputs.cshtml"
System.IO.IOException: The process cannot access the file 'C:\DynamicWeb\Solutions\DW-CPQ\wwwroot\Files\System\Log\Custom\DWCPQ - modelForm\2026-02-26.log' because it is being used by another process.
at Microsoft.Win32.SafeHandles.SafeFileHandle.CreateFile(String fullPath, FileMode mode, FileAccess access, FileShare share, FileOptions options)
at Microsoft.Win32.SafeHandles.SafeFileHandle.Open(String fullPath, FileMode mode, FileAccess access, FileShare share, FileOptions options, Int64 preallocationSize, Nullable`1 unixCreateMode)
at System.IO.Strategies.OSFileStreamStrategy..ctor(String path, FileMode mode, FileAccess access, FileShare share, FileOptions options, Int64 preallocationSize, Nullable`1 unixCreateMode)
at System.IO.StreamWriter.ValidateArgsAndOpenPath(String path, Boolean append, Encoding encoding, Int32 bufferSize)
at System.IO.StreamWriter..ctor(String path, Boolean append, Encoding encoding)
at DW_CPQ_API.Helpers.LogHelper.WriteLine(String text, Boolean append)
at DW_CPQ_API.Helpers.LogHelper.WriteFormattedLog(LogLevel level, String text)
at DW_CPQ_API.Helpers.LogHelper.Info(String text)
at DW_CPQ_API.ModelController.LoadFormInput()
at DW_CPQ_API.ModelController.LoadFormApplyRules()
at DW_CPQ_API.ModelController.GetModelData()
at DW_CPQ_API.ModelController..ctor(String modelVersionId, Nullable`1 pageId, NameValueCollection requestVars)
at DW_CPQ_API.ModelController..ctor(Int32 pageId, NameValueCollection requestVars)
at CompiledRazorTemplates.Dynamic.RazorEngine_68b4cb2fa2344a30bfd1759cdf70dba8.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.ViewModelTemplate<Dynamicweb.Frontend.ParagraphViewModel>
2 @using Dynamicweb.Ecommerce.ProductCatalog
3 @using System
4 @using DW_CPQ_API
5 @using System.Text.Json
6 @using System.Linq
7
8 @{
9
10 var modelController = Dynamicweb.Context.Current.Items["ModelController"] as ModelController;
11
12 if(modelController == null)
13 {
14 modelController = new ModelController(Model.PageID, Dynamicweb.Context.Current.Request.Params);
15 Dynamicweb.Context.Current.Items["ModelController"] = modelController;
16 }
17
18 //when debugmode is "true" set input name in div element as its title attribute for easy identification
19 string debugmode ="";
20 if( Dynamicweb.Context.Current.Request.QueryString.Get("debugmode") != null)
21 {
22 debugmode= Dynamicweb.Context.Current.Request.QueryString.Get("debugmode")!;
23 }
24 var cpq_model = modelController.DocumentResult;
25
26 string sectionTitle = Model.Item?.GetString("CPQ_SectionTitle") ?? "";
27 string inputGroupName = Model.Item?.GetString("CPQ_InputGroupName") ?? "";
28
29 var cpqPage = Dynamicweb.Content.Services.Pages.GetPage(Model.PageID);
30 string cpqTheme = (cpqPage.Item["CPQ_Theme"] ?? "cpq-bold").ToString();
31
32 int inputColumns = Convert.ToInt32(Model.Item?.GetValue("CPQ_InputColumns") ?? 1);
33
34 string versionId=modelController.ModelVersionId;
35
36 string hideSection = "";
37 int inputCount = cpq_model.Inputs.Count(x =>
38 (string.IsNullOrEmpty(inputGroupName) || x.GroupName == inputGroupName) &&
39 (x.Visible == null || x.Visible == true));
40
41 var inputGrp = cpq_model.Groups.FirstOrDefault(x => x.Name == inputGroupName);
42 if( inputGrp != null )
43 {
44 if(inputGrp.Visible == false || inputCount == 0)
45 {
46 hideSection = "style=\"display:none;\"";
47 }
48 else
49 {
50 sectionTitle = inputGrp.Label;
51 }
52 }else {
53 if( inputCount == 0 )
54 {
55 hideSection = "style=\"display:none;\"";
56 }
57 }
58
59 }
60
61 <div class="input-section-@inputGroupName" @hideSection>
62 @if( !string.IsNullOrEmpty(sectionTitle) )//&&
63 {
64 <div class="input-section-title">@sectionTitle</div>
65 }
66 <div name="result"></div>
67 <form>
68
69 <div class="container inputs-container input-columns-@inputColumns">
70
71 @foreach(var inputItem in cpq_model.Inputs.Where(x => x.GroupName == inputGroupName))
72 {
73
74 var hidden = "";
75 if( inputItem.Visible != null && inputItem.Visible == false ) hidden = "display:none;";
76
77 var strRequired = "";
78 if( inputItem.Required != null && inputItem.Required == true ) strRequired = "add-label-required";
79
80 bool isRequired = inputItem.Required == true;
81 // bool isInvalid = isRequired && string.IsNullOrEmpty(inputItem.Value);
82 //string validationClass = isInvalid ? "is-invalid" : "";
83 bool isReadOnly = Convert.ToBoolean(inputItem.Settings.FirstOrDefault(x => x.Name == "readonly")?.Value.ToString() ?? false);
84
85 string inputOptionColumns = inputItem.Settings.FirstOrDefault(x => x.Name == "option-columns")?.Value.ToString() ?? "3";
86 string imageClass = inputItem.Settings.FirstOrDefault(x => x.Name == "option-image-class")?.Value.ToString() ?? "";
87
88 bool hideOptionLabel = inputItem.Settings.FirstOrDefault(x => x.Name == "hide-label")?.Value.ToString().ToLower() == "true";
89 bool noLabel = inputItem.Settings.FirstOrDefault(x => x.Name == "no-label")?.Value.ToString().ToLower() == "true";
90
91 <div class="input-@(inputItem.Type)-container input-container @(inputItem.Type=="radiobox"||inputItem.Type=="checkboxLarge"?"input-grid":"")" id="visible_@inputItem.Name" style="@hidden" title="@(debugmode=="true"?inputItem.Name:"")">
92
93 @{
94 if( noLabel )
95 {
96 <div id="label_@inputItem.Name" style="display:none;"></div>
97 }
98 else
99 {
100 <div class="input-label @strRequired" id="label_@inputItem.Name">@inputItem.Label</div>
101 }
102 }
103
104 <div class="input-control input-control-col-@inputOptionColumns" @(noLabel?"style=\"width:100%\"":"")>
105
106 @if( inputItem.Type == "toggle" )
107 {
108 string isChecked = "";
109 // if( inputItem.Value != null && (inputItem.Value.ToLower()=="true" || inputItem.Value.ToLower()=="on"|| inputItem.Value.ToLower()=="yes") )
110 if( inputItem.Value != null && inputItem.Value is bool && (bool)inputItem.Value)
111 {
112 isChecked = "checked";
113 }
114 <label class="toggle-switch" >
115 <input type="checkbox" name="@inputItem.Name" id="@inputItem.Name" @isChecked onclick="updateModelForm({inputname:this.name,inputvalue:this.checked});" data-required="@(inputItem.Required.GetValueOrDefault().ToString().ToLower())">
116 <span class="toggle-slider"></span>
117 </label>
118 }
119 @if( inputItem.Type == "radio" ) // Radio Button
120 {
121 bool optionInline = Convert.ToBoolean(inputItem.Settings.FirstOrDefault(x => x.Name == "option-inline")?.Value.ToString() ?? inputItem.Options.Count <= 2);
122 string inlineClass = "";
123 if( optionInline ) inlineClass = "form-check-inline";
124 foreach( var option in inputItem.Options )
125 {
126 string optionDisabled = "";
127 if( option.Disabled ) optionDisabled = "disabled";
128 var optionId = $"{inputItem.Name}_{option.Value.Replace(" ", "")}";
129 <div class="form-check @inlineClass @(string.IsNullOrWhiteSpace(inputItem.StylingText) ? "" : inputItem.StylingText)" id="@($"optionVisible_{inputItem.Name}_{option.Value.Replace(" ", "")}")">
130 <input class="form-check-input" type="radio" id="@optionId" name="@inputItem.Name" value="@option.Value" onclick="updateModelForm({inputname:this.name,inputvalue:this.value});" checked="@option.Selected" @optionDisabled data-required="@(inputItem.Required.GetValueOrDefault().ToString().ToLower())" />
131 <label class="form-check-label" onclick="this.parentElement.querySelector('#@optionId').click();">@option.Label</label>
132 @if( !string.IsNullOrEmpty(option.Image) )
133 {
134 <img src="@option.Image" class="@imageClass" onclick="this.parentElement.querySelector('#@optionId').click();" />
135 }
136 </div>
137 }
138 }
139 @if( inputItem.Type == "radiobox" )
140 {
141 foreach (var option in inputItem.Options)
142 {
143 string optionDisabled = "";
144 if( option.Disabled ) optionDisabled = "option-disabled";
145 var optionId = $"{inputItem.Name}_{option.Value.Replace(" ", "")}";
146 var selectedText = option.Selected ? "selected" : "";
147 <div class="@selectedText @optionDisabled @(string.IsNullOrWhiteSpace(inputItem.StylingText) ? "" : inputItem.StylingText)" id="@($"optionVisible_{inputItem.Name}_{option.Value.Replace(" ", "")}")"
148 onclick="this.querySelector('#@optionId').click();">
149 <input type="radio" name="@inputItem.Name" id="@optionId" value="@option.Value" style="display:none;" checked="@option.Selected"
150 data-required="@(inputItem.Required.GetValueOrDefault().ToString().ToLower())" onclick="updateModelForm({inputname:this.name, inputvalue:this.value});"/>
151 @if( !string.IsNullOrEmpty(option.Image) )
152 {
153 <img src="@option.Image" class="@imageClass" />
154 }
155 @if(!hideOptionLabel)
156 {
157 <label onclick="this.parentElement.querySelector('#@optionId').click();">@option.Label</label>
158 }
159 </div>
160 }
161 }
162 @if( inputItem.Type == "checkbox" )
163 {
164 foreach( var option in inputItem.Options )
165 {
166 string optionDisabled = "";
167 if( option.Disabled ) optionDisabled = "option-disabled";
168 var optionId = $"{inputItem.Name}_{option.Value.Replace(" ", "")}";
169 <div class="@optionDisabled @(string.IsNullOrWhiteSpace(inputItem.StylingText) ? "" : inputItem.StylingText)" id="@($"optionVisible_{inputItem.Name}_{option.Value.Replace(" ", "")}")"
170 onclick="this.querySelector('#@optionId').click();">
171 @if( !string.IsNullOrEmpty(option.Image) )
172 {
173 <img src="@option.Image" class="@imageClass" />
174 }
175 <label class="highlight">
176 <input type="checkbox" name="@inputItem.Name" id="@optionId" value="@option.Value" onclick="updateModelForm({inputname:this.name, inputvalue:this.value});" checked="@option.Selected" data-required="@(inputItem.Required.GetValueOrDefault().ToString().ToLower())" />
177 <span>@option.Label</span>
178 </label>
179
180 </div>
181 }
182 }
183 @if( inputItem.Type == "checkboxLarge" )
184 {
185 foreach (var option in inputItem.Options)
186 {
187 string optionDisabled = "";
188 if( option.Disabled ) optionDisabled = "option-disabled";
189 var optionId = $"{inputItem.Name}_{option.Value.Replace(" ", "")}";
190 <div class="@optionDisabled @(string.IsNullOrWhiteSpace(inputItem.StylingText) ? "" : inputItem.StylingText)" id="@($"optionVisible_{inputItem.Name}_{option.Value.Replace(" ", "")}")"
191 onclick="this.querySelector('#@optionId').click();">
192 <input type="checkbox" name="@inputItem.Name" id="@optionId" value="@option.Value" class="hidden-checkbox" onclick="updateModelForm({inputname:this.name, inputvalue:this.value});"
193 checked="@option.Selected" @optionDisabled data-required="@(inputItem.Required.GetValueOrDefault().ToString().ToLower())" />
194 <img src="@option.Image" class="@imageClass" />
195 <span class="checkbox-indicator @(option.Selected ? "checked" : "")">
196 <span class="checkmark @(option.Selected ? "visible" : "")">✔</span>
197 </span>
198 <label onclick="this.parentElement.querySelector('#@optionId').click();">
199 <span>@option.Label</span>
200 </label>
201 </div>
202 }
203 }
204
205 @if (inputItem.Type == "select")
206 {
207 var optionsJson = System.Text.Json.JsonSerializer.Serialize(inputItem.Options.Select(o => new { o.Value, o.Label, o.Disabled, o.Visible }), DW_CPQ_API.Helpers.JsonHelper.JsonOptions );
208
209 <div class="mb-3 position-relative @(string.IsNullOrWhiteSpace(inputItem.StylingText) ? "" : inputItem.StylingText)">
210 <input type="text"
211 id="staticselect_@inputItem.Name"
212 data-field="@inputItem.Name"
213 class="form-control static-autocomplete @(inputItem.Required == true && string.IsNullOrEmpty(inputItem.Value as string) ? "is-invalid" : "")"
214 placeholder="Type to search..."
215 autocomplete="off"
216 data-options='@optionsJson'
217 value="@inputItem.ValueText"
218 data-required="@(inputItem.Required.GetValueOrDefault().ToString().ToLower())" />
219
220 <select id="@inputItem.Name"
221 data-field="@inputItem.Name"
222 name="@inputItem.Name"
223 style="display:none"
224
225 data-required="@(inputItem.Required.GetValueOrDefault().ToString().ToLower())">
226
227 @foreach (var opt in inputItem.Options)
228 {
229 <option value="@opt.Value" selected="@(opt.Value == inputItem.Value)" disabled="@(opt.Disabled)">
230 @opt.Label
231 </option>
232 }
233 </select>
234
235 <div class="invalid-feedback"> Please select a valid option. </div>
236 </div>
237 }
238
239 @if (inputItem.Type == "text")
240 {
241 <input class="form-control @(string.IsNullOrWhiteSpace(inputItem.StylingText) ? "" : inputItem.StylingText)"
242 value="@inputItem.Value"
243 name="@inputItem.Name"
244 type="text"
245 id="@inputItem.Name"
246 data-field="@inputItem.Name"
247 placeholder="@inputItem.Placeholder"
248 @(isReadOnly ? "readonly=\"readonly\"" : "")
249 data-required="@(inputItem.Required.GetValueOrDefault().ToString().ToLower())" />
250 }
251
252 @if( inputItem.Type == "number" )
253 {
254 decimal minValue = Convert.ToDecimal(inputItem.Settings.FirstOrDefault(x => x.Name == "min")?.Value.ToString() ?? 0);
255 decimal maxValue = Convert.ToDecimal(inputItem.Settings.FirstOrDefault(x => x.Name == "max")?.Value.ToString() ?? 0);
256 decimal stepValue = Convert.ToDecimal(inputItem.Settings.FirstOrDefault(x => x.Name == "step")?.Value.ToString() ?? 0);
257
258 string minmaxString = "";
259 if( minValue != maxValue )
260 {
261 minmaxString = $"min=\"{minValue}\" max=\"{maxValue}\"";
262 }
263
264 string stepString = "";
265 if( stepValue > 0 )
266 {
267 stepString = $"step=\"{stepValue}\"";
268 }
269
270 <!-- need readonly option -->
271 @* <input class="form-control"
272 value="@inputItem.Value"
273 name="@inputItem.Name"
274 type="number"
275 id="@inputItem.Name"
276 placeholder="@inputItem.Placeholder"
277 @(isReadOnly ? "readonly=\"readonly\"" : "")
278 @minmaxString @stepString onblur="checkLimits(this)"
279 /> *@
280
281 <input
282 class="form-control @(string.IsNullOrWhiteSpace(inputItem.StylingText) ? "" : inputItem.StylingText)"
283 type="number"
284 id="@inputItem.Name"
285 data-field="@inputItem.Name"
286 name="@inputItem.Name"
287 value="@inputItem.Value"
288 placeholder="@inputItem.Placeholder"
289 readonly="@isReadOnly"
290 disabled="@isReadOnly"
291 @minmaxString @stepString onblur="updateModelForm({inputname:this.name,inputvalue:this.value});"
292 data-required="@(inputItem.Required.GetValueOrDefault().ToString().ToLower())"
293 />
294 <div class="invalid-feedback">
295 Value out of range
296 </div>
297 }
298
299 @if (inputItem.Type == "lookup")
300 {
301 var jsonString = "{}";
302 if(inputItem.Parameters != null && inputItem.Parameters.Count > 0)
303 {
304 jsonString = JsonSerializer.Serialize(inputItem.Parameters);
305 }
306
307 <div class="mb-3 @(string.IsNullOrWhiteSpace(inputItem.StylingText) ? "" : inputItem.StylingText)">
308 <div class="position-relative">
309 <input type="text"
310 id="lookup_@inputItem.Name"
311 name="lookup_@inputItem.Name"
312 class="form-control lookup-input cpqlookup"
313 value="@inputItem.ValueText"
314 placeholder="Type to search..."
315 data-params='@jsonString'
316 data-lookupName="@inputItem.Name"
317 data-versionId="@versionId"
318 autocomplete="off"
319 data-required="@(inputItem.Required.GetValueOrDefault().ToString().ToLower())" />
320 </div>
321
322 <input type="hidden"
323 value="@inputItem.Value"
324 name="@inputItem.Name"
325 id="@inputItem.Name" />
326
327 <div id="lookupresult_@inputItem.Name" class="lookup-results"></div>
328
329 <div class="invalid-feedback">
330 This field is required.
331 </div>
332 </div>
333 }
334
335 @if (inputItem.Type == "longtext")
336 {
337 <div id="visible_@inputItem.Name" class="mb-3 @(string.IsNullOrWhiteSpace(inputItem.StylingText) ? "" : inputItem.StylingText)">
338 <textarea
339 class="form-control @(string.IsNullOrWhiteSpace(inputItem.StylingText) ? "" : inputItem.StylingText)"
340 id="@inputItem.Name"
341 data-field="@inputItem.Name"
342 name="@inputItem.Name"
343 placeholder="@inputItem.Placeholder"
344 rows="2"
345 @(isReadOnly ? "readonly=\"readonly\"" : "")
346 data-required="@(inputItem.Required.GetValueOrDefault().ToString().ToLower())">@inputItem.Value</textarea>
347 </div>
348 }
349
350 @if (inputItem.Type == "richtext")
351 {
352 <div id="visible_@inputItem.Name" class="mb-3 @(string.IsNullOrWhiteSpace(inputItem.StylingText) ? "" : inputItem.StylingText)">
353 <textarea
354 class="form-control rich-editor"
355 id="@inputItem.Name"
356 data-field="@inputItem.Name"
357 name="@inputItem.Name"
358 placeholder="@inputItem.Placeholder"
359 rows="1"
360 @(isReadOnly ? "readonly=\"readonly\"" : "")
361 data-required="@(inputItem.Required.GetValueOrDefault().ToString().ToLower())">@inputItem.Value</textarea>
362 </div>
363 }
364
365 @if (inputItem.Type == "button")
366 {
367 <div id="visible_@inputItem.Name" class="mb-3 @(string.IsNullOrWhiteSpace(inputItem.StylingText) ? "" : inputItem.StylingText)">
368 <button
369 type="button"
370 class="btn @(string.IsNullOrWhiteSpace(inputItem.StylingText) ? "" : inputItem.StylingText)"
371 id="@inputItem.Name"
372 name="@inputItem.Name"
373 @(isReadOnly ? "disabled" : "")
374 data-required="@(inputItem.Required.GetValueOrDefault().ToString().ToLower())">
375 @inputItem.Value
376 </button>
377 </div>
378 }
379
380 @if (inputItem.Type == "date")
381 {
382 <div class="mb-3 @(string.IsNullOrWhiteSpace(inputItem.StylingText) ? "" : inputItem.StylingText)">
383 <input type="text"
384 class="form-control datepicker @(inputItem.Required == true && string.IsNullOrEmpty(inputItem.Value as string) ? "is-invalid" : "")"
385 name="@inputItem.Name"
386 id="@inputItem.Name"
387 value="@inputItem.Value"
388 placeholder="Select date"
389 @(inputItem.Required == true ? "required" : "")
390 data-required="@(inputItem.Required.GetValueOrDefault().ToString().ToLower())" />
391 </div>
392 }
393
394 @if (inputItem.Type == "popup")
395 {
396 <input class="form-control popup-message-field @(string.IsNullOrWhiteSpace(inputItem.StylingText) ? "" : inputItem.StylingText)"
397 value="@inputItem.Value"
398 name="@inputItem.Name"
399 type="text"
400 id="@inputItem.Name"
401 placeholder="@inputItem.Placeholder"
402 @(isReadOnly ? "readonly=\"readonly\"" : "")
403 data-required="@(inputItem.Required.GetValueOrDefault().ToString().ToLower())" />
404 }
405
406 @if( inputItem.Type == "buttonGroup" )
407 {
408 @foreach (var option in inputItem.Options)
409 {
410 string optionDisabled = option.Disabled ? "option-disabled" : "";
411 string selectedText = option.Selected ? "selected" : "";
412 var optionId = $"{inputItem.Name}_{option.Value.Replace(" ", "")}";
413 var url = option.Value.StartsWith("http") ? option.Value : "https://" + option.Value;
414
415 <a href="@url"
416 target="_blank"
417 class="option-link @selectedText @optionDisabled @(string.IsNullOrWhiteSpace(inputItem.StylingText) ? "" : inputItem.StylingText)"
418 id="@($"optionVisible_{inputItem.Name}_{option.Value.Replace(" ", "")}")"
419 onclick="selectOption(this,true);">
420
421 @if( !string.IsNullOrEmpty(option.Image) )
422 {
423 <img src="@option.Image" class="@imageClass" />
424 }
425 @if(!hideOptionLabel)
426 {
427 <label for="@optionId" class="option-label">@option.Label</label>
428 }
429 </a>
430 }
431 }
432
433 </div>
434 </div>
435 }
436 </div>
437 </form>
438 </div>
439