<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom"><title type="text">Blog posts by Daved Artemik</title><link href="http://world.optimizely.com" /><updated>2023-01-04T14:00:00.0000000Z</updated><id>https://world.optimizely.com/blogs/daved-artemik/</id> <generator uri="http://world.optimizely.com" version="2.0">Optimizely World</generator> <entry><title>Be Careful When Versioning Your Projects</title><link href="https://beendaved.blogspot.com/2023/01/be-careful-when-versioning-your-projects.html" /><id>&lt;p&gt;Our build and release pipeline in DevOps auto-versions our builds when we publish a release to the Opti DXP. A pipeline step generates a version and assigns it to a variable, and that variable is used for the build when creating the package to push to the DXP instance. However, as mentioned in &lt;a href=&quot;https://beendaved.blogspot.com/2022/12/updating-project-versions-in-azure_01169308755.html&quot; target=&quot;_blank&quot;&gt;another post&lt;/a&gt;, this process was causing some odd behavior during development.&lt;/p&gt;&lt;a href=&quot;https://beendaved.blogspot.com/2023/01/be-careful-when-versioning-your-projects.html#more&quot;&gt;&lt;/a&gt;</id><updated>2023-01-04T14:00:00.0000000Z</updated><summary type="html">Blog post</summary></entry> <entry><title>Updating Project Versions in Azure DevOps</title><link href="https://beendaved.blogspot.com/2022/12/updating-project-versions-in-azure_01169308755.html" /><id>&lt;p&gt;We have a couple projects in DevOps that specify an incrementing  build version as part of the release pipeline. The approach we have is  working well and is deploying our projects with the proper version to  our hosted environments. This approach, however, was causing some issues  for local development and we needed a way to keep our local versions in  sync with the releases. After looking into the behaviour I discovered  we weren&amp;#39;t the only ones. A quick search revealed many discussions  trying to deal with this situation, and after some trial and error I was  able to come up with a solution.&lt;/p&gt;&lt;a href=&quot;https://beendaved.blogspot.com/2022/12/updating-project-versions-in-azure_01169308755.html#more&quot;&gt;&lt;/a&gt;</id><updated>2022-12-28T14:00:00.0000000Z</updated><summary type="html">Blog post</summary></entry> <entry><title>Updating Project Versions in Azure DevOps</title><link href="https://beendaved.blogspot.com/2022/12/updating-project-versions-in-azure.html" /><id>&lt;p&gt;We have a couple projects in DevOps that specify an incrementing build version as part of the release pipeline. The approach we have is working well and is deploying our projects with the proper version to our hosted environments. This approach, however, was causing some issues for local development and we needed a way to keep our local versions in sync with the releases. After looking into the behaviour I discovered we weren&#39;t the only ones. A quick search revealed many discussions trying to deal with this situation, and after some trial and error I was able to come up with a solution.&lt;/p&gt;&lt;h4 style=&quot;text-align: left;&quot;&gt;DevOps and PowerShell provide enough flexibility&lt;/h4&gt;&lt;p&gt;The existing version update happens via a PowerShell script that runs as part of the release pipeline. First, a variable is set to the build version to be used. Then, the build command is called with that variable to specify the version. Because that process was working and in place prior to my involvement on the pipeline I didn&#39;t want to change it. Instead, I added a new pipeline step after the existing versioning step, and called a new custom PowerShell script.&amp;nbsp;&lt;/p&gt;&lt;p&gt;[pre class=&quot;brush:yml;&quot; title=&quot;Sample Pipeline YML&quot;]&lt;br /&gt;trigger:&lt;br /&gt;- develop&lt;br /&gt;&lt;br /&gt;pool:&lt;br /&gt;&amp;nbsp; vmImage: &#39;windows-latest&#39;&lt;br /&gt;&lt;br /&gt;variables:&lt;br /&gt;&amp;nbsp; # My project variables here&lt;br /&gt;&amp;nbsp; &lt;br /&gt;steps:&lt;br /&gt;&amp;nbsp; # This is important to allow scripts access to auth token&lt;br /&gt;- checkout: self&lt;br /&gt;&amp;nbsp; persistCredentials: true&lt;br /&gt;&lt;br /&gt;&amp;nbsp; # Set Build Number to variable&lt;br /&gt;- task: PowerShell@2&lt;br /&gt;&amp;nbsp; displayName: &#39;Set the Build Number&#39;&lt;br /&gt;&amp;nbsp; inputs:&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; targetType: inline&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; script: &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Write-Host &quot;Setting Build Number&quot;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Write-Host &quot;###vso[task.setvariable variable=buildNumber]$(VersionNumber).$(VersionRevision).$(($(Get-Date).ToUniversalTime()-[datetime]&quot;01/01/2022 00:00&quot;).Days.ToString()).$([System.Math]::Floor($(Get-Date).TimeOfDay.TotalMinutes).ToString())&quot;&lt;br /&gt;&lt;br /&gt;&amp;nbsp; # Extra step for debugging version&lt;br /&gt;- task: PowerShell@2&lt;br /&gt;&amp;nbsp; displayName: &#39;Confirm Build Number&#39;&lt;br /&gt;&amp;nbsp; inputs:&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; targetType: inline&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; script: Write-Host &quot;Build Number $(buildNumber)&quot;&lt;br /&gt;&lt;br /&gt;&amp;nbsp; # Update version in code in repo&lt;br /&gt;- task: PowerShell@2&lt;br /&gt;&amp;nbsp; displayName: &#39;Update Project Version&#39;&lt;br /&gt;&amp;nbsp; inputs:&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; targetType: filePath&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; filePath: &#39;dev\_SolutionItems\Powershell Scripts\UpdateProjectVersions.ps1&#39;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; arguments: &#39;$(Build.SourceBranch) $(Build.SourcesDirectory) $(buildNumber)&#39;&lt;br /&gt;&lt;br /&gt;&amp;nbsp; # Extra steps for various build and configuration tasks go here&lt;br /&gt;&lt;br /&gt;&amp;nbsp; # Build command specifying version previously set&lt;br /&gt;- task: DotNetCoreCLI@2&lt;br /&gt;&amp;nbsp; displayName: &#39;Build Code&#39;&lt;br /&gt;&amp;nbsp; inputs:&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; command: build&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; projects: &#39;$(projects)&#39;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; arguments: &#39;--configuration $(buildConfiguration) --framework $(coreFramework) -p:Version=$(buildNumber)&#39;&lt;br /&gt;&lt;br /&gt;&amp;nbsp; # Code to publish and deploy package&lt;br /&gt;[/pre]&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;Pay attention to the first two lines under steps declaring a checkout step with the &quot;&lt;b&gt;persistCredentials&lt;/b&gt;&quot; option set to &quot;&lt;b&gt;true&lt;/b&gt;&quot;. This ensures that scripts executing can access the system token. This is needed for proper permissions for the GIT operations in the PowerShell script. &lt;br /&gt;&lt;/p&gt;&lt;h4 style=&quot;text-align: left;&quot;&gt;The custom PowerShell script updates the version information in the code base.&amp;nbsp;&lt;/h4&gt;&lt;p&gt;The important thing about updating the version in the codebase is it needs to make that update to the code in the repository. The script below is the solution to perform that task. It takes in 3 required parameters to specify the solution root directory, the version number to use, and the calling branch from our GIT repo. It then performs the following tasks:&lt;/p&gt;&lt;ol style=&quot;text-align: left;&quot;&gt;&lt;li&gt;Create a temporary GIT branch on the pipeline agent&lt;/li&gt;&lt;li&gt;Identify and loop through all CSProj files in the solution directories&lt;/li&gt;&lt;li&gt;Set version information on all identified CSProj files (.NET Core+)&lt;/li&gt;&lt;li&gt;Add the updates to the GIT repo for the temp branch&lt;/li&gt;&lt;li&gt;Set the Username and Email for the commit details to reflect the Azure Agent&lt;/li&gt;&lt;li&gt;Commit changes to the temp branch&lt;/li&gt;&lt;li&gt;Merge and push the changes into the source branch&lt;br /&gt;&lt;/li&gt;&lt;/ol&gt;&lt;p&gt;[pre class=&quot;brush:pshell&quot; title=&quot;Update Version PowerShell&quot;]&lt;br /&gt;param&lt;br /&gt;&amp;nbsp; (&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;[Parameter(Position=0, Mandatory)]&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;[ValidateNotNullOrEmpty()]&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;[string]$sourceBranch,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; [Parameter(Position=1, Mandatory)]&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; [ValidateNotNullOrEmpty()]&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; [string]$rootDir,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; [Parameter(Position=2, Mandatory)]&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; [ValidateNotNullOrEmpty()]&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; [string]$version&lt;br /&gt;&amp;nbsp; )&lt;br /&gt;&amp;nbsp; if([string]::IsNullOrWhiteSpace($sourceBranch)){&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; throw &quot;Source branch must be specified.&quot;&lt;br /&gt;&amp;nbsp; }&lt;br /&gt;&amp;nbsp; if([string]::IsNullOrWhiteSpace($rootDir)){&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; throw &quot;Please specify the root path containing the CSProj files to update.&quot;&lt;br /&gt;&amp;nbsp; }&lt;br /&gt;&amp;nbsp; if([string]::IsNullOrWhiteSpace($version)){&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; throw &quot;Please specify the version number to be used.&quot;&lt;br /&gt;&amp;nbsp; }&lt;br /&gt;&lt;br /&gt;$sourceBranch = $sourceBranch.Replace(&quot;refs/heads/&quot;,&quot;&quot;)&lt;br /&gt;$tempBranch = &quot;temp/UpdateVersion_$($version)&quot;&lt;br /&gt;# create a new branch for hosting update&lt;br /&gt;git branch $tempBranch --quiet&lt;br /&gt;# switch to new branch for performing updates&lt;br /&gt;git checkout $tempBranch --quiet&lt;br /&gt;&lt;br /&gt;# function to update or add and update XML nodes in project group&lt;br /&gt;Function SetNodeValue($xmlRootNode, [string]$nodeName, [string]$nodeValue) {&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;$propGroup = $xmlRootNode.Node.SelectSingleNode(&quot;PropertyGroup&quot;)&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;$node = $propGroup.SelectSingleNode(&quot;./$($nodeName)&quot;)&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;if ($node -eq $null) {&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Write-Host &quot;Adding node for $($nodeName)&quot;&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; $node = $propGroup.OwnerDocument.CreateElement($nodeName)&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; $nodeAdded = $propGroup.AppendChild($node)&amp;nbsp;&amp;nbsp;&amp;nbsp; # do this to avoid console output&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;}&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;else {&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Write-Host &quot;Existing node found for $($nodeName)&quot;&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;}&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;$node.InnerText = $nodeValue&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;Write-Host &quot;Set value $($nodeValue) for node $($nodeName)&quot;&lt;br /&gt;}&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br /&gt;# loop all CSProj files so they are all on same version&lt;br /&gt;Get-ChildItem -Path $rootDir -Filter &quot;*.csproj&quot; -Recurse -File |&lt;br /&gt;&amp;nbsp; ForEach-Object {&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; Write-Host &quot;Found project file $($_.FullName)&quot;&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; $projPath = $_.FullName&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; $projXml = Select-Xml $projPath -XPath &quot;//Project&quot;&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; &lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; SetNodeValue $projXml &quot;AssemblyVersion&quot; $version&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; SetNodeValue $projXml &quot;FileVersion&quot; $version&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; SetNodeValue $projXml &quot;Version&quot; $version&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; &lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; $doc = $projXml.Node.OwnerDocument&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp; &lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; $doc.PreserveWhitespace = $true&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; $doc.save($projPath)&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; &lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;# add the updated CSProj to GIT&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;git add $projPath&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp; &lt;br /&gt;&amp;nbsp; }&lt;br /&gt;&lt;br /&gt;# update email and username to identify repo updates by automated pipe - not a real address&lt;br /&gt;git config user.email &quot;azure.agent@mydomain.com&quot;&lt;br /&gt;git config user.name &quot;Azure Agent&quot; --replace-all&lt;br /&gt;# commit changes with a comment identifying pipeline mod&lt;br /&gt;git commit -m &quot;[auto] Update Version: Set project versions to $($version)&quot;&lt;br /&gt;# switch back to the original branch that triggered this&lt;br /&gt;git checkout $sourceBranch --quiet&lt;br /&gt;# pull latest from git&lt;br /&gt;git pull --quiet&lt;br /&gt;# merge the proj updates back into source branch, with comment to indicate operation&lt;br /&gt;git merge $tempBranch -m &quot;[auto] Update Version: Complete version to $($version) for source $($sourceBranch)&quot; --quiet&lt;br /&gt;# push changes back into source branch&lt;br /&gt;git push -u origin --quiet&lt;br /&gt;[/pre]&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;h4 style=&quot;text-align: left;&quot;&gt;This process updates the version information in our repo&lt;/h4&gt;&lt;p&gt;With this script in place, each time a merge happens to our pipeline branch, the develop branch in this case, the version will be updated in each project file for our solution. After this, any pull of that branch will include the latest version number in it. This does mean that any local branches in progress when this happens need to pull down and merge the latest version before committing to include the latest changes without conflict. But that is a small price to pay for the automation this provides. &lt;br /&gt;&lt;/p&gt;</id><updated>2022-12-21T14:00:00.0000000Z</updated><summary type="html">Blog post</summary></entry> <entry><title>Optimizely CMS 12 Installation Breaking Changes for Visual Studio 2019</title><link href="https://beendaved.blogspot.com/2022/05/optimizely-cms-12-installation-breaking.html" /><id>&lt;p&gt;Last October I wrote an article to act as an addendum to the Optimizely Documentation for starting a new CMS site using CMS 12 and .NET 5. Since then there have been some updates to the documentation and the packages involved. Today I got bit by one of them because I am using Visual Studio 2019, and if you are too this might save you some trouble.&lt;/p&gt;&lt;a href=&quot;https://beendaved.blogspot.com/2022/05/optimizely-cms-12-installation-breaking.html#more&quot;&gt;&lt;/a&gt;</id><updated>2022-05-13T11:00:00.0000000Z</updated><summary type="html">Blog post</summary></entry> <entry><title>Validation Summary for Optimizely Forms in Non JS Mode</title><link href="https://beendaved.blogspot.com/2021/11/validation-summary-for-optimizely-forms_01757455308.html" /><id>&lt;p&gt;I recently wrote an article on how to &lt;a href=&quot;https://beendaved.blogspot.com/2021/11/validation-summary-for-optimizely-forms.html&quot;&gt;create a Validation Summary for Optimizely Forms&lt;/a&gt;. The approach described in that article uses Form Client Events and Javascript to add a validation summary to the top of the form. That method is dependent on Javascript, and Forms must operate in JS mode for it to work. This article provides a different solution for use with Optimizely Forms with &lt;b&gt;workInJonJSMode&lt;/b&gt; enabled.&lt;br /&gt;&lt;/p&gt;&lt;h4 style=&quot;text-align: left;&quot;&gt;A custom Form Container Block is req&lt;span&gt;uired for this method&lt;/span&gt;&lt;br /&gt;&lt;/h4&gt;&lt;p&gt;Create a custom Form Container Block using one of the following guides: &lt;/p&gt;&lt;ol style=&quot;text-align: left;&quot;&gt;&lt;li&gt;&lt;a href=&quot;https://world.optimizely.com/documentation/developer-guides/forms/creating-a-custom-form-block/&quot; target=&quot;_blank&quot;&gt;Optimizely documented way&lt;/a&gt; &lt;br /&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;https://beendaved.blogspot.com/2021/11/custom-optimizely-form-containers.html&quot; target=&quot;_blank&quot;&gt;Custom Optimizely Form Containers - Put the View Where You Want &lt;br /&gt;&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;https://beendaved.blogspot.com/2021/11/optimizely-form-container-block-with.html&quot; target=&quot;_blank&quot;&gt;Optimizely Form Container Block with Razor View&lt;/a&gt; &lt;br /&gt;&lt;/li&gt;&lt;/ol&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&amp;nbsp;&lt;/div&gt;&lt;h4 style=&quot;text-align: left;&quot;&gt;If your Form Container Block file is ASCX&lt;/h4&gt;&lt;p&gt;Locate the div with class &lt;b&gt;Form__Status__Message&lt;/b&gt; and add the validation summary block below.&amp;nbsp;&lt;/p&gt;&lt;p&gt;[pre class=&quot;brush:xhtml;class-name:collapse-box&quot;]&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;%-- area for showing Form&#39;s status or validation --%&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;div class=&quot;Form__Status&quot;&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;div class=&quot;Form__Status__Message &amp;lt;%: statusDisplay %&amp;gt;&quot; data-f-form-statusmessage&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;%= message %&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;/div&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;% // add this section below Form__Status__Message&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (_formConfig.WorkInNonJSMode &amp;amp;&amp;amp; ViewBag.ValidationFail)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; %&amp;gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;div class=&quot;Form__Validation__Summary&quot;&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;%&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; foreach (var element in Model.Form.Steps.ElementAt((int)ViewBag.CurrentStepIndex)?.Elements.Select(e =&amp;gt; e.SourceContent as EPiServer.Forms.Implementation.Elements.BaseClasses.ValidatableElementBlockBase).Where(e =&amp;gt; e != null))&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; var validationMessage = element.GetErrorMessage();&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (!string.IsNullOrEmpty(validationMessage)) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; %&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;div class=&quot;validation-summary-error&quot;&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;label for=&quot;&amp;lt;%= element.FormElement.Guid %&amp;gt;&quot;&amp;gt;&amp;lt;%= element.Label %&amp;gt;:&amp;lt;/label&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;%= Html.ValidationMessageFor(element) %&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;/div&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;%&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; %&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;/div&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;% } %&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;/div&amp;gt;&lt;br /&gt;[/pre]&lt;/p&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&amp;nbsp;&lt;/div&gt;&lt;h4 style=&quot;text-align: left;&quot;&gt;If your Form Container Block file is CSHTML&lt;/h4&gt;&lt;p&gt;Locate the div with class &lt;b&gt;Form__Status__Message&lt;/b&gt; and add the validation summary block below.&amp;nbsp;&lt;/p&gt;&lt;p&gt;[pre class=&quot;brush:razor;class-name:collapse-box&quot;]&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; @* area for showing Form&#39;s status or validation *@&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;div class=&quot;Form__Status&quot;&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;div class=&quot;Form__Status__Message @statusDisplay&quot; data-f-form-statusmessage&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; @Html.Raw(message)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;/div&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; @*add this section below Form__Status__Message*@&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; @if (_formConfig.WorkInNonJSMode &amp;amp;&amp;amp; ViewBag.ValidationFail)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;div class=&quot;Form__Validation__Summary&quot;&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; @foreach (var element in Model.Form.Steps.ElementAt((int)ViewBag.CurrentStepIndex)?.Elements.Select(e =&amp;gt; e.SourceContent as EPiServer.Forms.Implementation.Elements.BaseClasses.ValidatableElementBlockBase).Where(e =&amp;gt; e != null))&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; var validationMessage = element.GetErrorMessage();&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (!string.IsNullOrWhiteSpace(validationMessage))&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;div class=&quot;validation-summary-error&quot;&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;label for=&quot;@element.FormElement.Guid&quot;&amp;gt;@element.Label:&amp;lt;/label&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; @Html.ValidationMessageFor(element)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;/div&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;/div&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;/div&amp;gt;&lt;br /&gt;[/pre]&lt;/p&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&amp;nbsp;&lt;/div&gt;&lt;h4 style=&quot;text-align: left;&quot;&gt;Finally, verify non-JS mode is enabled in Forms.config&lt;/h4&gt;&lt;p&gt;If you&#39;re here you probably already have this set. However, in case you don&#39;t, the Forms.config file is located in &lt;b&gt;/modules/_protected/EPiServer.Forms&lt;/b&gt;. Change the value for &quot;&lt;b&gt;workInNonJSMode&lt;/b&gt;&quot; to &lt;b&gt;true&lt;/b&gt;. With this setting enabled, submitting the form will submit server-side before returning the view.&amp;nbsp;&lt;/p&gt;&lt;p&gt;The code blocks above only work when &lt;b&gt;workInNonJSMode &lt;/b&gt;is enabled. If validation fails, validatable elements in the current step are iterated and the validation helper is called for each. If a form element fails validation a message is returned, and it&#39;s added to the summary.&amp;nbsp;&lt;/p&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://1.bp.blogspot.com/-lVtTdPcf-eE/YYtLfRgb0JI/AAAAAAAAoBE/ZvmZO0wmNnctrQ88Vk6s54qAWUVBlEcvgCLcBGAsYHQ/s633/Form%2BSubmission%2BWorking%2BNonJS.gif&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; data-original-height=&quot;633&quot; data-original-width=&quot;469&quot; height=&quot;400&quot; src=&quot;https://1.bp.blogspot.com/-lVtTdPcf-eE/YYtLfRgb0JI/AAAAAAAAoBE/ZvmZO0wmNnctrQ88Vk6s54qAWUVBlEcvgCLcBGAsYHQ/w296-h400/Form%2BSubmission%2BWorking%2BNonJS.gif&quot; width=&quot;296&quot; /&gt;&lt;/a&gt;&lt;/div&gt;&lt;h4 style=&quot;text-align: left;&quot;&gt;You can support JS and Non-JS Forms by combining methods&lt;br /&gt;&lt;/h4&gt;&lt;p&gt;You can take the script from my &lt;a href=&quot;https://beendaved.blogspot.com/2021/11/validation-summary-for-optimizely-forms.html&quot;&gt;Validation Summary for Optimizely Forms article&lt;/a&gt; and add it to the bottom of your Form Container Block file. It will only execute if Forms jQuery is included, so it plays nicely with this code.&lt;br /&gt;&lt;/p&gt;</id><updated>2021-11-22T14:00:00.0000000Z</updated><summary type="html">Blog post</summary></entry> <entry><title>Optimizely Form Container Block with Razor View</title><link href="https://beendaved.blogspot.com/2021/11/optimizely-form-container-block-with.html" /><id>&lt;p&gt;Optimizely Forms display using a traditional Webform User Control (ASCX) out of the box. With all the work I have been doing with forms lately I wanted to see if I could change this behaviour to use a Razor View instead. Now that I have it working, I wanted to share it.&lt;/p&gt;&lt;a href=&quot;https://beendaved.blogspot.com/2021/11/optimizely-form-container-block-with.html#more&quot;&gt;&lt;/a&gt;</id><updated>2021-11-16T14:00:00.0000000Z</updated><summary type="html">Blog post</summary></entry> <entry><title>Custom Optimizely Form Containers - A Slightly Different Approach </title><link href="https://beendaved.blogspot.com/2021/11/custom-optimizely-form-containers.html" /><id>&lt;p&gt;Most instructions for creating a custom form block in Optimizely follow &lt;a href=&quot;https://world.optimizely.com/documentation/developer-guides/forms/creating-a-custom-form-block/&quot; target=&quot;_blank&quot;&gt;the same approach&lt;/a&gt;. My problem with the typical approach is that it requires a folder structure that doesn&amp;#39;t match my solution. I use a slightly different method to allow me to move my Form Container Block rendering to my choice of folders.&lt;/p&gt;&lt;a href=&quot;https://beendaved.blogspot.com/2021/11/custom-optimizely-form-containers.html#more&quot;&gt;&lt;/a&gt;</id><updated>2021-11-09T14:00:00.0000000Z</updated><summary type="html">Blog post</summary></entry> <entry><title>Validation Summary for Optimizely Forms</title><link href="https://beendaved.blogspot.com/2021/11/validation-summary-for-optimizely-forms.html" /><id>&lt;p&gt;I have seen requests for a method to implement a Validation Summary for Optimizely Forms, and I dealt with one myself. If you&amp;#39;re not familiar with the idea, a Validation Summary includes all the validation messages for form fields in a summary section for easy review. This is typically found at the top of the form after you try to submit. There is no option for this functionality out of the box with Optimizely so I put it together.&lt;br /&gt;&lt;/p&gt;&lt;a href=&quot;https://beendaved.blogspot.com/2021/11/validation-summary-for-optimizely-forms.html#more&quot;&gt;&lt;/a&gt;</id><updated>2021-11-04T13:00:00.0000000Z</updated><summary type="html">Blog post</summary></entry> <entry><title>Starting a New Project with Optimizely CMS 12 and .NET Core</title><link href="https://beendaved.blogspot.com/2021/10/starting-new-project-with-optimizely.html" /><id>&lt;p&gt;Optimizely recently released CMS 12 based on ASP.NET Core (now .NET 5). With it comes a slew of new changes, including how to set up a new project. To help developers get started with Optimizely CMS on the new framework, Optimizely released a guide to creating a starter project. After working through it myself and talking with a few developers, I decided to write a more detailed guide with a few additional notes to better help you get going.&lt;/p&gt;&lt;a href=&quot;https://beendaved.blogspot.com/2021/10/starting-new-project-with-optimizely.html#more&quot;&gt;&lt;/a&gt;</id><updated>2021-10-28T13:00:00.0000000Z</updated><summary type="html">Blog post</summary></entry> <entry><title>The Problem with Nested Blocks and AdditionalViewData</title><link href="https://beendaved.blogspot.com/2021/10/the-problem-with-nested-blocks-and.html" /><id>&lt;p&gt;It&amp;#39;s not uncommon to nest blocks in Optimizely to create more controlled and complex layouts on pages. It&amp;#39;s also sometimes necessary to provide additional data to the blocks you render. When using the PropertyFor helper this is done by specifying an additionalViewData object. However ViewData persists to nested views and this can mess up your layout. This is how to identify when this happens, and how to work around it.&lt;/p&gt;&lt;a href=&quot;https://beendaved.blogspot.com/2021/10/the-problem-with-nested-blocks-and.html#more&quot;&gt;&lt;/a&gt;</id><updated>2021-10-25T13:00:00.0000000Z</updated><summary type="html">Blog post</summary></entry> <entry><title>Moving the DisplayTemplates Folder</title><link href="https://beendaved.blogspot.com/2021/10/moving-displaytemplates-folder.html" /><id>&lt;p&gt;Optimizely uses DisplayTemplates to provide a way to render different partials for data types. DisplayTemplates are native to ASP.Net MVC, though, and Optimizely builds upon them, for instance, by specifying a Tag. An example of this is the rendering of ContentReference properties in my articles &lt;a href=&quot;https://beendaved.blogspot.com/2021/09/rendering-contentreference-properties.html&quot; target=&quot;_blank&quot;&gt;here&lt;/a&gt; and &lt;a href=&quot;https://beendaved.blogspot.com/2021/09/rendering-contentreference-with-shared.html&quot; target=&quot;_blank&quot;&gt;here&lt;/a&gt;.  The MVC engine defaults the location for them to &amp;quot;Views/Shared/DisplayTemplates&amp;quot;. Sometimes, though, it&amp;#39;s convenient to reference different locations, and this is how you can do that.&#160;&lt;/p&gt;&lt;a href=&quot;https://beendaved.blogspot.com/2021/10/moving-displaytemplates-folder.html#more&quot;&gt;&lt;/a&gt;</id><updated>2021-10-21T13:00:00.0000000Z</updated><summary type="html">Blog post</summary></entry> <entry><title>Rendering ContentReference With Shared Views Using a TemplateTag</title><link href="https://beendaved.blogspot.com/2021/10/rendering-contentreference-with-shared.html" /><id>&lt;p&gt;ContentReference properties provide a way to select a single item in Optimizely CMS when you don&amp;#39;t need the featureset a ContentArea provides. However, rendering an item with a ContentReference is a bit different. I explored this a bit in my article &lt;a href=&quot;Rendering ContentReference Properties&quot;&gt;Rendering ContentReference Properties&lt;/a&gt;. This post expands on this with a single DisplayTemplate that works for most content types. It builds on a similar technique using a ContentReferencePartial, and adds additional functionality using a TemplateTag. &lt;/p&gt;&lt;a href=&quot;https://beendaved.blogspot.com/2021/10/rendering-contentreference-with-shared.html#more&quot;&gt;&lt;/a&gt;</id><updated>2021-10-18T13:00:00.0000000Z</updated><summary type="html">Blog post</summary></entry> <entry><title>Rendering ContentReference Properties</title><link href="https://beendaved.blogspot.com/2021/10/rendering-contentreference-properties.html" /><id>&lt;p&gt;A ContentReference property allows you to select a single ContentData object for reference. By default, when you render these property types with the PropertyFor helper, it renders as a link for a page, or displays the name of a block. This is because the value stored is a ContentReference object, not the ContentData of the item referenced. This is one approach to render that content with a partial view.&lt;br /&gt;&lt;/p&gt;&lt;a href=&quot;https://beendaved.blogspot.com/2021/10/rendering-contentreference-properties.html#more&quot;&gt;&lt;/a&gt;</id><updated>2021-10-14T13:00:00.0000000Z</updated><summary type="html">Blog post</summary></entry> <entry><title>How to Exclude or Modify Episerver Forms Samples Javascript and CSS</title><link href="https://beendaved.blogspot.com/2021/10/how-to-exclude-or-modify-episerver.html" /><id>&lt;p&gt;Optimizely Forms contains jQuery and CSS packages that are included for the Form rendering out-of-box. This isn&amp;#39;t always desired because it can affect page performance, other styling, or it could have other side effects depending on your setup. Optimizely provides for the disabling of these files through the Forms.config file in the Forms module folder, which allows you to independently control the insertion of jQuery and CSS. However, this method is easy to break with an update. It also isn&amp;#39;t very flexible since it&amp;#39;s an all-or-nothing approach. &lt;br /&gt;&lt;br /&gt;&lt;/p&gt;&lt;a href=&quot;https://beendaved.blogspot.com/2021/10/how-to-exclude-or-modify-episerver.html#more&quot;&gt;&lt;/a&gt;</id><updated>2021-10-11T13:00:00.0000000Z</updated><summary type="html">Blog post</summary></entry> <entry><title>Creating Gated Content with Optimizely Forms</title><link href="https://beendaved.blogspot.com/2021/10/creating-gated-content-with-optimizely.html" /><id>&lt;p&gt;I recently worked on an Optimizely project where the customer wanted to serve gated content to visitors. If you&amp;#39;re not familiar with gated content, it&amp;#39;s where content is only available to a user that fills out a form - the form being the &amp;quot;gate&amp;quot;. Gated content can be a powerful marketing tool to help capture valuable information for lead generation, or for tracking visitor statistics.&#160;&lt;/p&gt;&lt;p&gt;In our case, the customer wanted to provide whitepaper downloads to visitors that provided a defined set of information. Our goal was to create this interaction using Optimizely Forms.&lt;br /&gt;&lt;/p&gt;&lt;a href=&quot;https://beendaved.blogspot.com/2021/10/creating-gated-content-with-optimizely.html#more&quot;&gt;&lt;/a&gt;</id><updated>2021-10-07T13:00:00.0000000Z</updated><summary type="html">Blog post</summary></entry> <entry><title>Hide Optimizely Form Info when Redirecting</title><link href="https://beendaved.blogspot.com/2021/10/hide-optimizely-form-info-when.html" /><id>&lt;p&gt;With Optimizely Forms you have the option to redirect to a page after a complete submission. By default, Optimizely appends some form information to the URL it redirects to. This allows you to process the form submission data in any way you need to on the page it directs to, or perform an action based on what form was submitted. However, if you don&amp;#39;t want that information in the URL you can change the behaviour.&lt;/p&gt;&lt;a href=&quot;https://beendaved.blogspot.com/2021/10/hide-optimizely-form-info-when.html#more&quot;&gt;&lt;/a&gt;</id><updated>2021-10-04T13:00:00.0000000Z</updated><summary type="html">Blog post</summary></entry> <entry><title>Hide FormContainerBlock in Optimizely</title><link href="https://beendaved.blogspot.com/2021/09/hide-formcontainerblock-in-optimizely.html" /><id>&lt;p&gt;It&amp;#39;s easy to customize a FormContainerBlock by creating a new one inheriting from the out-of-box FormContainerBlock model. When doing this you gain the option of using the OOB container, or your new custom one. However, I have encountered numerous times when the OOB form container was no longer necessary for the project. Furthermore, attempting to use the OOB FormContainerBlock in certain areas created issues I had to account for. In several instances for me, the easiest approach was to hide the Optimizely FormContainerBlock from editors, and this is how I did it. &lt;/p&gt;&lt;a href=&quot;https://beendaved.blogspot.com/2021/09/hide-formcontainerblock-in-optimizely.html#more&quot;&gt;&lt;/a&gt;</id><updated>2021-09-30T13:00:00.0000000Z</updated><summary type="html">Blog post</summary></entry> <entry><title>Form Events Interface Pattern</title><link href="https://beendaved.blogspot.com/2021/09/form-events-interface-pattern.html" /><id>&lt;p&gt;Much like standard content items in Optimizely CMS, Forms trigger events that can be subscribed to for further customization. You typically subscribe to these events by employing an Initialization Module and attaching an event handler to process the logic you need for each event. This works well for the out-of-the-box Forms, but I have done enough customization of forms that I started employing an Interface pattern to clean it up. I use this same pattern for content events, so I thought I would share my forms approach.&#160;&lt;/p&gt;&lt;a href=&quot;https://beendaved.blogspot.com/2021/09/form-events-interface-pattern.html#more&quot;&gt;&lt;/a&gt;</id><updated>2021-09-23T13:00:00.0000000Z</updated><summary type="html">Blog post</summary></entry> <entry><title>Stop Creating New Windows &amp; Tabs When Debugging</title><link href="https://beendaved.blogspot.com/2021/09/stop-creating-new-windows-tabs-when.html" /><id>&lt;p&gt;Most of my web applications, including Optimizely/Episerver, run through IIS on my local machine. I like to publish out sites so I have a more accurate idea of what is published when we deploy client sites out to their DXP instance. Sometimes, though, I run my Opti/Epi application right out of IIS Express using Visual Studio debugging because it can be convenient for small debugging tasks, or when troubleshooting initialization modules.&#160;&lt;/p&gt;&lt;p&gt;When you run a web application via debugging in Visual Studio, the default behaviour is for VS to launch the application in a new tab in your default browser. It will also close that browser tab or window when you stop debugging which can be annoying when you want to keep the same content or page up in between tests or code changes. This is how you can disable that.&lt;/p&gt;&lt;a href=&quot;https://beendaved.blogspot.com/2021/09/stop-creating-new-windows-tabs-when.html#more&quot;&gt;&lt;/a&gt;</id><updated>2021-09-20T21:00:00.0000000Z</updated><summary type="html">Blog post</summary></entry> <entry><title>Previewable TextArea Properties</title><link href="https://beendaved.blogspot.com/2021/04/previewable-textarea-properties.html" /><id> &lt;p&gt;        Inline editing is an awesome feature in Episerver because it creates a great editor experience. Because         the inline editing happens in the context of the page, it delivers a close WYSIWYG (What You See Is What         You Get) authoring view. As you edit property values the page updates to show you what the new updated         values.     &lt;/p&gt;    &lt;p&gt;        Unfortunately, this isn&amp;#39;t always the desired effect. Sometimes, you want a more customized rendering of         the in-page view for a property, though. When the page is constantly updating as you edit or type, this         can be a bit cumbersome. FullFreshPropertiesMetaData can help to a degree, but it&amp;#39;s not always the answer.         Sometimes, I like to just use an edit popup.&#160;     &lt;/p&gt;    &lt;a href=&quot;https://beendaved.blogspot.com/2021/04/previewable-textarea-properties.html#more&quot;&gt;&lt;/a&gt;</id><updated>2021-04-12T22:29:00.0000000Z</updated><summary type="html">Blog post</summary></entry></feed>