tag:blogger.com,1999:blog-45073720880712004082024-03-16T08:08:22.356+01:00SitecoreCoffeeRadoslaw Kozlowski about SitecoreRadoslaw Kozlowskihttp://www.blogger.com/profile/06810133427607221124noreply@blogger.comBlogger34125tag:blogger.com,1999:blog-4507372088071200408.post-10287713649210038042021-01-22T15:37:00.000+01:002021-01-22T15:37:22.190+01:00Fortis - Unable to find template error<p>I was upgrading my client's Sitecore instance lately and at some point I've spotted this issue with Fortis:<br /></p>
<pre>Fortis | Unable to find template for MyProject.Model.IMyTemplate</pre>
<p>After doing some digging in the internet I couldn't find out what was causing it. I decided to compare all config files and I've spotted that my Web.config on new environment is missing these bits:</p>
<p>Declaration of Fortis section in <span style="font-family: courier;"><configSections></span></p>
<pre><configSections>
...
<section name="fortis" type="System.Configuration.NameValueSectionHandler" />
...
</configSections></pre>
<p>...and the actual section my Model project assembly reference:</p>
<pre><fortis>
<add key="assembly" value="MyProject.Model, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" />
</fortis></pre>
<p><br /></p><p>With these added it all worked. I hope this will help somebody!<br /></p>Radoslaw Kozlowskihttp://www.blogger.com/profile/06810133427607221124noreply@blogger.com0tag:blogger.com,1999:blog-4507372088071200408.post-63805329037254045942020-11-30T16:33:00.004+01:002020-11-30T16:49:16.591+01:00HelixCheck - update v 1.0.1<p>I've just released a quick update to my GitHub Action - HelixCheck.</p><p>New release includes additional input parameter named <code>excluded-projects</code> which can be used to exclude projects that we don't want to be analysed. Example setup:</p>
<pre>name: Helix Check
on:
push:
branches: [ develop, master ]
pull_request:
branches: [ develop, master ]
jobs:
check_job:
name: Helix check
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v2
- name: Helix Check
uses: ethisysltd/helix-check@v1.0.1
id: check
with:
solution-file: 'Helixbase.sln'
project-name: 'Helixbase'
website-folder: 'website'
excluded-projects: 'Helixbase.Foundation.NotFollowingHelix,Helixbase.Feature.RatherNotFollowingHelix'
- name: Get the check result
run: echo "Check result - ${{ steps.check.outputs.result }}"
- name: Get the output time
run: echo "The time was - ${{ steps.check.outputs.time }}"</pre>
<p>Value of that parameter should be a string with comma-delimited names of projects. I couldn't use YAML's multiline collections syntax here because of GitHub Actions limitations.<br /></p><p>Ideally this parameter shouldn't be used, as Helix project setup should be clean, but I've got some requests to add this. And, as usual, in real world solutions there can be legacy projects which might be a work in progress of refactoring, so there it goes!</p><p>If used, there will be additional warning added to the output, which won't affect the result outcome but will add more visibility of the setup gotchas:</p><div class="separator" style="clear: both; text-align: center;"><a href="https://1.bp.blogspot.com/-UOlpRRTFKvI/X8UPFehFIOI/AAAAAAAACLQ/BJgxFd529cMErjBP2B61j8a8qRcSuNHuQCLcBGAsYHQ/s666/warn.PNG" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="36" data-original-width="666" src="https://1.bp.blogspot.com/-UOlpRRTFKvI/X8UPFehFIOI/AAAAAAAACLQ/BJgxFd529cMErjBP2B61j8a8qRcSuNHuQCLcBGAsYHQ/s16000/warn.PNG" /></a></div><p></p><p>This action can be found in GitHub marketplace here: <a href="https://github.com/marketplace/actions/helix-check">https://github.com/marketplace/actions/helix-check</a></p><p>Code repo is available here: <a href="https://github.com/ethisysltd/helix-check">https://github.com/ethisysltd/helix-check</a><br /></p><p><br /></p>Radoslaw Kozlowskihttp://www.blogger.com/profile/06810133427607221124noreply@blogger.com0tag:blogger.com,1999:blog-4507372088071200408.post-63775780076790355442020-07-23T14:16:00.006+02:002020-11-30T16:34:23.247+01:00HelixCheck - GitHub action<div>
Recently I've prepared a GitHub action that checks solution structure to see
if it is Helix compliant and follow guidelines of folders structure. <br />
</div>
<div><br /></div>
<div>
It is available on GitHub marketplace and ready to be used with Sitecore
projects following Helix principles -
<a href="https://github.com/marketplace/actions/helix-check">https://github.com/marketplace/actions/helix-check</a>.
</div>
<div><br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://github.com/marketplace/actions/helix-check" style="margin-left: 1em; margin-right: 1em;" target="_blank"><img border="0" data-original-height="500" data-original-width="500" height="320" src="https://1.bp.blogspot.com/-3QMWodreBiU/Xxmb_1iWJYI/AAAAAAAACFs/weE-DRHHQKQ50Kn5O4CLRWNqWWNW4H-7wCLcBGAsYHQ/s320/OriginalSmall.png" /></a>
</div>
<div><br /></div>
<div>
If you're not familiar with GitHub actions you can read more about it here
<a href="https://github.com/features/actions">https://github.com/features/actions</a>
or in technical documentation -
<a href="https://docs.github.com/en/actions">https://docs.github.com/en/actions</a>.
</div>
<div><br /></div>
<div><h4 style="text-align: left;">General rules</h4></div>
<div></div>
<div>
Action tries to reflect Helix rules from documentation -
<a href="https://helix.sitecore.net/">https://helix.sitecore.net/</a><br />
</div>
<div><br /></div>
<div>Projects references:</div>
<div>
<ul style="text-align: left;">
<li>Feature layer projects can only reference Foundation</li>
<li>Foundation layer projects can only reference other Foundations</li>
<li>
Project layer projects can reference Feature and Foundation but not other
Projects<br />
</li>
</ul>
</div>
<div>Folders structure and naming convention:</div>
<div>
<ul style="text-align: left;">
<li>There are layer folders specified in the solution</li>
<ul>
<li>Feature</li>
<li>Foundation</li>
<li>Project</li>
</ul>
<li>Projects are placed in correct folders, for example:</li>
<ul>
<li>
src\Feature\ORM\website\Helixbase.Foundation.ORM.csproj - incorrect
</li>
<li>
src\Foundation\ORM\website\Helixbase.Foundation.ORM.csproj - correct
</li>
</ul>
</ul>
<div><br /></div>
<ul style="text-align: left;">
<ul></ul>
</ul>
</div>
<div><h4 style="text-align: left;">Configuration</h4></div>
<div>Example workflow:<br /></div>
<div><br /></div>
<pre>name: Helix Check
on:
push:
branches: [ develop, master ]
pull_request:
branches: [ develop, master ]
jobs:
check_job:
name: Helix check
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v2
- name: Helix Check
uses: ethisysltd/helix-check@v1.0
id: check
with:
solution-file: 'Helixbase.sln'
project-name: 'Helixbase'
website-folder: 'website'
- name: Get the check result
run: echo "Check result - ${{ steps.check.outputs.result }}"
- name: Get the output time
run: echo "The time was - ${{ steps.check.outputs.time }}"</pre>
<div><br /></div>
<div></div>
<div>
It should be placed inside folder
<span style="font-family: "courier";">.github\workflows\</span> and named
something like <span style="font-family: "courier";">helix-check.yml</span>
</div>
<div><span style="font-family: "courier";"></span><br /></div>
<div>Action is configured by these inputs:<br /></div>
<div>
<br />
<table class="table">
<thead>
<tr>
<th>Input</th>
<th>Description</th>
<th>Usage</th>
</tr>
</thead>
<tbody>
<tr>
<td><code>solution-file</code></td>
<td>Path to the solution that will be analyzed.</td>
<td>Required</td>
</tr>
<tr>
<td><code>project-name</code></td>
<td>The name of your project.</td>
<td>Required</td>
</tr>
<tr>
<td><code>website-folder</code></td>
<td>
The name of the folder that always contain website project file.<br />
Default "website", earlier "code" was used.
</td>
<td>Optional</td>
</tr>
</tbody>
</table>
</div>
<div><br /></div>
<div>
While using the action makes sure you've checked the readme.md inside repo, as
it will always be most up to date -
<a href="https://github.com/ethisysltd/helix-check">https://github.com/ethisysltd/helix-check</a>.<br />
</div>
<div><br /></div>
<div>
In the action repository I've put example Helix solutions for tests -
<a href="https://github.com/muso31/Helixbase" target="_blank">Helixbase by Neil Shack</a>. <br />
</div>
<div>If there are no issues found, simple log message is shown. <br /></div>
<div><br /></div>
<div>
<pre>Solution file: example-solution/valid/Helixbase.sln
Project name: Helixbase
Solution file exists.
<br />Solution is Helix compliant.</pre>
</div>
<div><br /></div>
<div><br /></div>
<div>
I've managed to add a copy of that one and mess it up really badly so you can
see result of analysis:
</div>
<div><br /></div>
<pre>Solution file: example-solution/invalid/Helixbase-Invalid.sln
Project name: Helixbase
Solution file exists.
##[warning]Issues with project Helixbase.Foundation.ORM
Folder incorrect: src\Feature\ORM\code\Helixbase.Foundation.ORM.csproj
##[warning]Issues with project Helixbase.Feature.Hero
Folder incorrect: src\Foundation\Hero\code\Helixbase.Feature.Hero.csproj
##[warning]Issues with project Helixbase.Project.Helixbase
Incorrect references:
- Helixbase.Project.Common
##[warning]Issues with project Helixbase.Feature.VersionTrim
Incorrect references:
- Helixbase.Project.Common
- Helixbase.Feature.ShowTitles
##[warning]Issues with project Helixbase.Foundation.Core
Incorrect references:
- Helixbase.Feature.Redirects
- Helixbase.Project.Common<br /><br />##[error]Solution is not Helix compliant.</pre>
<div><br /></div>
<div>
Action is released to the Marketplace under
<a href="https://github.com/marketplace/actions/helix-check">https://github.com/marketplace/actions/helix-check</a>. I will be adding additional checks soon, feel free to give me a shout if
you find any issues or bugs.<br />
</div>
<div></div>
<div><br /></div>
<div>Cheers!<br /></div>
<div><br /></div>
Radoslaw Kozlowskihttp://www.blogger.com/profile/06810133427607221124noreply@blogger.com0tag:blogger.com,1999:blog-4507372088071200408.post-41591562847998409872019-11-25T18:31:00.000+01:002020-01-02T18:33:26.341+01:00Azure Search - Improving speed while getting facets onlyIf you want to get only facets from your search query - for some purposes as preparing filters list - remember to set limit to 0.<br />
<br />
For example like this:<br />
<br />
<span style="font-family: "Courier New", Courier, monospace;">var facetResults = searchQuery.Take(0).GetFacets();</span><br />
<br />
<span style="font-family: "Courier New", Courier, monospace;">.Take(0)</span> translates to <span style="font-family: "Courier New", Courier, monospace;">$top=0</span> in Azure Search query. That will return something like this:<br />
<br />
<pre>
{
"@odata.context": "https://{YOUR-SEARCH-SERVICE}.search.windows.net/indexes('my-index-web-index-99')/$metadata#docs(*)",
"@odata.count": 857,
"@search.facets": {
"contenttype_facet_1": [
{
"count": 146,
"value": "Content Type 1"
},
{
"count": 134,
"value": "Content Type 2"
},
{
"count": 118,
"value": "Content Type 3"
},
],
"topic_facet_1": [
{
"count": 176,
"value": "Topic 1"
},
{
"count": 70,
"value": "Topic 2"
},
{
"count": 62,
"value": "Topic 3"
},
{
"count": 52,
"value": "Topic 4"
}
],
"subtopic_facet_1": [
{
"count": 49,
"value": "Subtopic 1"
},
{
"count": 32,
"value": "Subtopic 2"
}
]
},
"value": []
}
</pre>
<br />
So only essential statistics data without actual results<br />
<br />Radoslaw Kozlowskihttp://www.blogger.com/profile/06810133427607221124noreply@blogger.com0tag:blogger.com,1999:blog-4507372088071200408.post-38520078158641338972019-11-01T13:06:00.000+01:002019-12-18T13:10:54.042+01:00RenderField processor for tooltip linksA couple of days ago I've got a requirement from my client about inline tooltips functionality. Those tooltips needed to have formatted text so RTE field should be used.<br />
<br />
<br />
I started with creating repository folder for those tooltips<br />
<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://1.bp.blogspot.com/-CDoLd7aZM8U/XfoTszhKHbI/AAAAAAAAB9I/jdQN18CMe4EkF6PaCcssFU3HyRLkU3WJQCLcBGAsYHQ/s1600/1.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="71" data-original-width="181" src="https://1.bp.blogspot.com/-CDoLd7aZM8U/XfoTszhKHbI/AAAAAAAAB9I/jdQN18CMe4EkF6PaCcssFU3HyRLkU3WJQCLcBGAsYHQ/s1600/1.PNG" /></a></div>
<br />
<br />
Template for tooltip item was really simple, just one RTE field<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://1.bp.blogspot.com/--0twAlut77E/XfoUBKO0l8I/AAAAAAAAB9Q/FYM4zhu4qiY0y2ewxUP2mvhaCYhGduduwCLcBGAsYHQ/s1600/2.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="357" data-original-width="492" src="https://1.bp.blogspot.com/--0twAlut77E/XfoUBKO0l8I/AAAAAAAAB9Q/FYM4zhu4qiY0y2ewxUP2mvhaCYhGduduwCLcBGAsYHQ/s1600/2.PNG" /></a></div>
<br />
<br />
To have a link which will open a tooltip I had to write a pipeline processor which<br />
<ul>
<li>Will read RTE field content</li>
<li>Find internal links</li>
<li>Check if they point to tooltip item</li>
<ul>
<li>If yes then process link</li>
</ul>
</ul>
<br />
<br />
<script src="https://gist.github.com/ReoKzK/c72869a109678f36455daa3b3ab13341.js"></script>
<br />
This pipeline processor must be run after field value is read, so after<br />
<span style="font-family: "Courier New", Courier, monospace;">Sitecore.Pipelines.RenderField.GetFieldValue, Sitecore.Kernel</span><br />
<br />
<script src="https://gist.github.com/ReoKzK/f1ef0a24e6b2e55902c1da9feaf2263a.js"></script>
Radoslaw Kozlowskihttp://www.blogger.com/profile/06810133427607221124noreply@blogger.com0tag:blogger.com,1999:blog-4507372088071200408.post-19393748512914329372019-10-20T20:00:00.000+02:002019-11-27T20:07:16.311+01:00Helix Publishing Pipeline - file locks issue on deployOn my last project when I was implementing Helix Publishing Pipeline I found really bizarre issue. Almost every time I was deploying code by publishing it from Visual Studio, some dlls were locked by w3wp process.<br />
<br />
No surprise IIS uses those assemblies but I didn't have such locking problem earlier.<br />
<br />
I was digging for hours in the Internet and I found out that IIS uses assembly shadowing. So basically it doesn't use directly dlls from webroot bin, but from its the temp folder.<br />
<br />
It can be disabled by this setting<br />
<br />
<blockquote class="tr_bq">
<hostingEnvironment shadowCopyBinAssemblies="false" /></blockquote>
<br />
When I set this for test, file locks were all over the place.<br />
<br />
Earlier I used Process Explorer and I saw that w3wp locks not only shadowed dlls but as well those from webroot bin, so something was not right there!<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://1.bp.blogspot.com/-nnCdBPtmqx8/Xd7JHcfJrqI/AAAAAAAAB7k/LVMsMK7-EfU2c4fSbROMXqO6q2ly9FINQCLcBGAsYHQ/s1600/image%2B%25286%2529%2B%25286%2529.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="468" data-original-width="1600" height="186" src="https://1.bp.blogspot.com/-nnCdBPtmqx8/Xd7JHcfJrqI/AAAAAAAAB7k/LVMsMK7-EfU2c4fSbROMXqO6q2ly9FINQCLcBGAsYHQ/s640/image%2B%25286%2529%2B%25286%2529.png" width="640" /></a></div>
<br />
<br />
More digging eventually gave me information that our issue was self-inflicted: <a href="https://stackoverflow.com/a/28019475">https://stackoverflow.com/a/28019475</a><br />
<br />
In GlassMapperScCustom assemblies were loaded by invoking method <br />
<blockquote class="tr_bq">
Assembly.LoadFile(assemblyPath) </blockquote>
<br />
which loads exact assemblies and it doesn't take into account shadows.<br />
<br />
Instead of that we should always use<br />
<br />
<blockquote class="tr_bq">
Assembly.LoadFrom(assemblyPath) </blockquote>
<br />
which loads shadows as it should be.<br />
<br />
That fixed issue with file locks for good! Radoslaw Kozlowskihttp://www.blogger.com/profile/06810133427607221124noreply@blogger.com1Wrocław, Poland51.1078852 17.03853760000004150.948439199999996 16.715814100000042 51.2673312 17.361261100000039tag:blogger.com,1999:blog-4507372088071200408.post-51900079180481167092019-02-19T17:06:00.000+01:002019-02-19T17:14:00.763+01:00Azure Search provider - Results ordering issueI was implementing Azure Search lately into my last project and I found some <span style="font-family: inherit;">strange </span>issue in the provider (we're using Sitecore 9.0.2 rev. 180604). When I wanted to order my search results using Linq like this:<br />
<br />
<pre>searchQuery.OrderBy(x => x.JobRole).ThenBy(x => x.LastName)</pre>
<br />
it was translated to:<br />
<br />
<pre>$orderby=last_name_s,job_role_i</pre>
<br />
So it looks like it's taking argument of <span style="font-family: "courier new" , "courier" , monospace;">ThenBy</span> as first and <span style="font-family: "courier new" , "courier" , monospace;">OrderBy</span> as the second. Inverting parameters:<br />
<br />
<pre>searchQuery.OrderBy(x => x.LastName).ThenBy(x => x.JobRole)</pre>
<br />
gave me desired query:<br />
<br />
<pre>$orderby=job_role_i,last_name_s</pre>
<br />
<span style="font-family: inherit;">And search result as well were sorted like I wanted.</span><br />
<span style="font-family: inherit;"><br /></span>
<span style="font-family: inherit;">Azure Search documentation states nothing unusual, but I had to confirm this:</span><br />
<span style="font-family: inherit;"><br /></span>
<br />
<blockquote>
$orderby=[string] (optional)<br />
<br />
A list of comma-separated expressions to sort the results by. When calling via POST, this parameter is named orderby instead of $orderby. Each expression can be either a field name or a call to the geo.distance() function. Each expression can be followed by asc to indicate ascending, and desc to indicate descending. The default is ascending order. Ties will be broken by the match scores of documents. If no $orderby is specified, the default sort order is descending by document match score. There is a limit of 32 clauses for $orderby.</blockquote>
<span style="font-family: inherit;"><a href="https://docs.microsoft.com/en-us/rest/api/searchservice/search-documents#orderbystring-optional">https://docs.microsoft.com/en-us/rest/api/searchservice/search-documents#orderbystring-optional</a> </span><br />
<br />
<span style="font-family: inherit;">I have raised an issue on Sitecore Helpdesk and guys from support checked and reported the issue. It has a reference number 309333. Current resolution is to invert parameters like I did.</span><br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://2.bp.blogspot.com/-tFmY9ExgPO4/XGwpvjNpVkI/AAAAAAAABvs/SKEqwSTEVeM6jRNN0p-MTUQavz4WP_EtwCLcBGAs/s1600/Azure-Search-369x369.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="369" data-original-width="369" height="320" src="https://2.bp.blogspot.com/-tFmY9ExgPO4/XGwpvjNpVkI/AAAAAAAABvs/SKEqwSTEVeM6jRNN0p-MTUQavz4WP_EtwCLcBGAs/s320/Azure-Search-369x369.png" style="background: white; border-radius: 5px; padding: 10px;" width="320" /></a></div>
<br />
<div class="separator" style="clear: both; text-align: center;">
</div>
Radoslaw Kozlowskihttp://www.blogger.com/profile/06810133427607221124noreply@blogger.com0Newcastle upon Tyne, UK54.978252 -1.617780000000038954.8325385 -1.9405035000000388 55.1239655 -1.2950565000000389tag:blogger.com,1999:blog-4507372088071200408.post-28960985628892080002018-12-02T11:20:00.000+01:002018-12-14T19:15:42.655+01:00Unicorn - disabling automatic items serializationI've come across a problem with Unicorn last time. We deployed to QA environment and a couple days later testers started to see issues like this:<br />
<br />
<pre>Unicorn: You cannot have a sparse serialized tree</pre>
<br />
It was appearing when they were saving edited content. I've decided that we don't really need automatic items serialization on QA and other environments, so it will be best to just switch it off. I took a look into <span style="font-family: "courier new" , "courier" , monospace;">Unicorn.DataProvider.config</span> and the comment there states:<br />
<br />
<pre>This file configures the Unicorn data provider. The data provider writes updated serialized items to disk when they are changed.
This file should be removed in ANY deployed instance (CE or CD) that does not act as a source for serialized item updates.
Generally speaking that's anywhere other than a developer workstation, so your CI process (you have one, right?) should remove this file during the build.
IMPORTANT EXCEPTION: If you are using Transparent Sync as a deployment mechanism, this file must remain on your CE environment.</pre>
<br />
That's exactly why it should be turned off on any non-development environments.<br />
<br />
As we are using Sitecore 9, we have set <span style="font-family: "courier new" , "courier" , monospace;">localenv</span> variable to <span style="font-family: "courier new" , "courier" , monospace;">Local</span> on our dev instances Web.config<br />
<br />
<pre><add key="localenv:define" value="Local" /></pre>
<br />
Instead of removing <span style="font-family: "courier new" , "courier" , monospace;">Unicorn.DataProvider.config</span> config file after deployment, I have added <span style="font-family: "courier new" , "courier" , monospace;">localenv:require="Local"</span> to root element there:<br />
<br />
<pre style="background: #1e1e1e; color: gainsboro; font-family: Consolas; font-size: 12px;"><span style="color: grey;"><</span><span style="color: #569cd6;">sitecore</span><span style="color: grey;"> </span><u><b><span style="color: #92caf4;">localenv:require</span><span style="color: grey;">=</span><span style="color: grey;">"</span><span style="color: #c8c8c8;">Local</span><span style="color: grey;">"</span></b></u><span style="color: grey;">></span>
<span style="color: grey;"> <</span><span style="color: #569cd6;">dataProviders</span><span style="color: grey;">></span>
<span style="color: grey;"> <!--</span>
<span style="color: #57a64a;"> Register the Unicorn data provider for use. If a database hooks to the Unicorn data provider it will</span>
<span style="color: #57a64a;"> automatically write changes to the database that match any configured predicate into the serialization provider.</span>
<span style="color: #57a64a;"> Changes that only affect Revision, Modified, or any fields ignored by FieldPredicates will be ignored.</span>
<span style="color: #57a64a;"> </span><span style="color: grey;">--></span>
<span style="color: grey;"> <</span><span style="color: #569cd6;">unicorn</span><span style="color: grey;"> </span><span style="color: #92caf4;">type</span><span style="color: grey;">=</span><span style="color: grey;">"</span><span style="color: #c8c8c8;">Unicorn.Data.DataProvider.Unicorn$(database)DataProvider, Unicorn</span><span style="color: grey;">"</span><span style="color: grey;">></span>
<span style="color: grey;"> <</span><span style="color: #569cd6;">param</span><span style="color: grey;"> </span><span style="color: #92caf4;">connectionStringName</span><span style="color: grey;">=</span><span style="color: grey;">"</span><span style="color: #c8c8c8;">$(1)</span><span style="color: grey;">"</span><span style="color: grey;">/></span>
<span style="color: grey;"> <</span><span style="color: #569cd6;">Name</span><span style="color: grey;">></span><span style="color: #c8c8c8;">$(1)</span><span style="color: grey;"></</span><span style="color: #569cd6;">Name</span><span style="color: grey;">></span>
<span style="color: grey;"> </</span><span style="color: #569cd6;">unicorn</span><span style="color: grey;">></span>
<span style="color: grey;"> </</span><span style="color: #569cd6;">dataProviders</span><span style="color: grey;">></span>
<span style="color: grey;"> <!--</span>
<span style="color: #57a64a;"> Hook the Unicorn Data Provider into the master and core databases. If you're not</span>
<span style="color: #57a64a;"> syncing anything in core you can safely unregister it from here. If you want to</span>
<span style="color: #57a64a;"> sync something to another database register it here.</span>
<span style="color: #57a64a;"> It's safe to remove this config section on any environment where you are not</span>
<span style="color: #57a64a;"> collecting item changes, which may mean anywhere other than local development</span>
<span style="color: #57a64a;"> sites. This will avoid any performance hit from writing unused serialized files.</span>
<span style="color: #57a64a;"> </span><span style="color: grey;">--></span>
<span style="color: grey;"> <</span><span style="color: #569cd6;">databases</span><span style="color: grey;">></span>
<span style="color: grey;"> <</span><span style="color: #569cd6;">database</span><span style="color: grey;"> </span><span style="color: #92caf4;">id</span><span style="color: grey;">=</span><span style="color: grey;">"</span><span style="color: #c8c8c8;">master</span><span style="color: grey;">"</span><span style="color: grey;">></span>
<span style="color: grey;"> <</span><span style="color: #569cd6;">dataProviders</span><span style="color: grey;">></span>
<span style="color: grey;"> <</span><span style="color: #569cd6;">dataProvider</span><span style="color: grey;"> </span><span style="color: #92caf4;">ref</span><span style="color: grey;">=</span><span style="color: grey;">"</span><span style="color: #c8c8c8;">dataProviders/main</span><span style="color: grey;">"</span><span style="color: grey;">></span>
<span style="color: grey;"> <</span><span style="color: #569cd6;">patch:attribute</span><span style="color: grey;"> </span><span style="color: #92caf4;">name</span><span style="color: grey;">=</span><span style="color: grey;">"</span><span style="color: #c8c8c8;">ref</span><span style="color: grey;">"</span><span style="color: grey;">></span><span style="color: #c8c8c8;">dataProviders/unicorn</span><span style="color: grey;"></</span><span style="color: #569cd6;">patch:attribute</span><span style="color: grey;">></span>
<span style="color: grey;"> </</span><span style="color: #569cd6;">dataProvider</span><span style="color: grey;">></span>
<span style="color: grey;"> </</span><span style="color: #569cd6;">dataProviders</span><span style="color: grey;">></span>
<span style="color: grey;"> </</span><span style="color: #569cd6;">database</span><span style="color: grey;">></span>
<span style="color: grey;"> <</span><span style="color: #569cd6;">database</span><span style="color: grey;"> </span><span style="color: #92caf4;">id</span><span style="color: grey;">=</span><span style="color: grey;">"</span><span style="color: #c8c8c8;">core</span><span style="color: grey;">"</span><span style="color: grey;">></span>
<span style="color: grey;"> <</span><span style="color: #569cd6;">dataProviders</span><span style="color: grey;">></span>
<span style="color: grey;"> <</span><span style="color: #569cd6;">dataProvider</span><span style="color: grey;"> </span><span style="color: #92caf4;">ref</span><span style="color: grey;">=</span><span style="color: grey;">"</span><span style="color: #c8c8c8;">dataProviders/main</span><span style="color: grey;">"</span><span style="color: grey;">></span>
<span style="color: grey;"> <</span><span style="color: #569cd6;">patch:attribute</span><span style="color: grey;"> </span><span style="color: #92caf4;">name</span><span style="color: grey;">=</span><span style="color: grey;">"</span><span style="color: #c8c8c8;">ref</span><span style="color: grey;">"</span><span style="color: grey;">></span><span style="color: #c8c8c8;">dataProviders/unicorn</span><span style="color: grey;"></</span><span style="color: #569cd6;">patch:attribute</span><span style="color: grey;">></span>
<span style="color: grey;"> </</span><span style="color: #569cd6;">dataProvider</span><span style="color: grey;">></span>
<span style="color: grey;"> </</span><span style="color: #569cd6;">dataProviders</span><span style="color: grey;">></span>
<span style="color: grey;"> </</span><span style="color: #569cd6;">database</span><span style="color: grey;">></span>
<span style="color: grey;"> </</span><span style="color: #569cd6;">databases</span><span style="color: grey;">></span>
<span style="color: grey;"></</span><span style="color: #569cd6;">sitecore</span><span style="color: grey;">></span></pre>
<br />
That makes sure the changes made by editors won't be serialized.Radoslaw Kozlowskihttp://www.blogger.com/profile/06810133427607221124noreply@blogger.com0Newcastle upon Tyne, UK54.978252 -1.617780000000038954.8325385 -1.9405035000000388 55.1239655 -1.2950565000000389tag:blogger.com,1999:blog-4507372088071200408.post-75808791797806970862018-11-17T20:46:00.000+01:002018-11-30T13:27:31.452+01:00Renderings static bindingLast time I had to prepare a component which behaves like a carousel of specific type of renderings. Instead of copy-pasting the Razor markup or using basic Razor partials I decided to use static binding of renderings - method I've never used before. It appeared to be extremely handy.<br />
<br />
Basically you can specify a rendering like this:<br />
<br />
<pre>@Html.Sitecore().Rendering("{ rendering ID }", new { Cacheable = true, Cache_VaryByData = true, DataSource = "{ DataSource ID}" })</pre>
<br />
First parameter is rendering ID, second is anonymous object where we can specify additional properties, like caching or even datasource that will be used there.<br />
<br />
You can even add your custom properties and read them inside rendering, just like this:<br />
<br />
<pre>@Html.Sitecore().Rendering(
Constants.MyRendering.RenderingId.ToString("B"),
new
{
Cacheable = true,
Cache_VaryByData = true,
DataSource = myDatasource.Id.ToString("B"),
MyProperty = "My custom value"
})</pre>
<br />
To be more familiar with possible properties of that anonymous object I have decompiled GetRendering method from SitecoreHelper class:<br />
<br />
<script src="https://gist.github.com/ReoKzK/a3474401bbed5c7c7d1e25a108639e58.js"></script>
<br/>
I have created and extension method to easily retrieve rendering properties:<br />
<br />
<script src="https://gist.github.com/ReoKzK/966e4b92c26044d9e88d00bfe355aa16.js"></script>
And you can use it in view like this:<br />
<br />
<pre>var property = Html.Sitecore().GetRenderingProperty("MyProperty");</pre>
<br />
<br />Radoslaw Kozlowskihttp://www.blogger.com/profile/06810133427607221124noreply@blogger.com0Newcastle upon Tyne, UK54.978252 -1.617780000000038954.8325385 -1.9405035000000388 55.1239655 -1.2950565000000389tag:blogger.com,1999:blog-4507372088071200408.post-67740416425509677472018-10-04T13:16:00.002+02:002018-10-07T21:03:25.402+02:00Sitecore PowerShell Extensions - Custom functionLast time I had to prepare a resolution for making changes
on the existing content after the deployment. We were adding new components to
Standard Values of the page and they had to be configured properly on the
content item by setting data source. Change like this couldn’t be synchronised
by Unicorn as the page content item was one-time deployment only item (NewItemOnlyEvaluator)
and setting data source straight on Standard Value is a really bad idea!<o:p></o:p><br />
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
We had three options there:</div>
<div class="MsoNormal">
</div>
<ol>
<li>Set data source manually after synch</li>
<li>Create a Sitecore content package with prepared
changes</li>
<li>Prepare Sitecore PowerShell script that will automate
the changes we need</li>
</ol>
<div class="MsoListParagraphCxSpLast" style="mso-list: l0 level1 lfo1; text-indent: -18.0pt;">
<o:p></o:p></div>
<div class="MsoNormal">
As doing things manually is always error-prone and package
could overwrite some content changes, we decided to go for third option –
PowerShell scripting!<o:p></o:p></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
First of all, I needed a way for setting data source on rendering
that already exists on a page content item. I found there is
not such specific function in SPE core so I wrote a custom one.</div>
<br />
<br />
<script src="https://gist.github.com/ReoKzK/a8b7f907ec46956f83021c2b30e79bc6.js"></script> <br />
<br />
<br />
To create a custom SPE function we need to have new module created. The easiest it will be by using wizard:<br />
<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://4.bp.blogspot.com/-uk40Tt6Yxns/W7XqfffJwAI/AAAAAAAABoI/rMx0mhuiWDoT3942iYhw8h4XqT2M8ZKYACLcBGAs/s1600/New%2Bmodule%2B%2528wizard%2529.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="756" data-original-width="1353" height="178" src="https://4.bp.blogspot.com/-uk40Tt6Yxns/W7XqfffJwAI/AAAAAAAABoI/rMx0mhuiWDoT3942iYhw8h4XqT2M8ZKYACLcBGAs/s320/New%2Bmodule%2B%2528wizard%2529.PNG" width="320" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<br />
<br />
We will need Shared Functions integration, so we can select it just while creating the module.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://2.bp.blogspot.com/-vKLEKSSg7WI/W7XqlssEhcI/AAAAAAAABoM/MF7Bq-r2hq8_p29xlnEZTryu5IrQ3nadQCLcBGAs/s1600/New%2Bmodule%2B%2528wizard%2529%2B2.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1600" data-original-width="1205" height="320" src="https://2.bp.blogspot.com/-vKLEKSSg7WI/W7XqlssEhcI/AAAAAAAABoM/MF7Bq-r2hq8_p29xlnEZTryu5IrQ3nadQCLcBGAs/s320/New%2Bmodule%2B%2528wizard%2529%2B2.PNG" width="240" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<br />
It can be done after as well just by creating scripts library called
Functions. Here's link to documentation:
<a href="https://doc.sitecorepowershell.com/modules/integration-points/functions">https://doc.sitecorepowershell.com/modules/integration-points/functions</a><br />
<br />
After this we will have our module folder with Functions folder inside. There we will create our custom shared function.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://3.bp.blogspot.com/-QsXoa_nAii8/W7XrWnmHq1I/AAAAAAAABoY/6DX0-GVijmouBVgtAR-GNpazAPBXft8aACLcBGAs/s1600/New%2BPowershell%2Bfuntion.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="438" data-original-width="1132" height="123" src="https://3.bp.blogspot.com/-QsXoa_nAii8/W7XrWnmHq1I/AAAAAAAABoY/6DX0-GVijmouBVgtAR-GNpazAPBXft8aACLcBGAs/s320/New%2BPowershell%2Bfuntion.PNG" width="320" /></a></div>
<br />
I have named it <span style="font-family: "courier new" , "courier" , monospace;">Set-RenderingDatasource</span>. Body of the function should be placed inside field described as <i>Script body - Source code written in PowerShell</i><span class="scEditorFieldLabelAdministrator">. That's the function I've shown earlier. </span><br />
<span class="scEditorFieldLabelAdministrator"><br /></span>
<span class="scEditorFieldLabelAdministrator">Next thing will be create new PowerShell Script Library item, just on the same level as Functions item. I named it as After Deploy Scripts and created one new script inside - </span><span class="scEditorFieldLabelAdministrator"><span style="font-family: "courier new" , "courier" , monospace;">Apply-Datasources</span>:</span><br />
<br />
<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://2.bp.blogspot.com/-0v5rHJCeNHY/W7Xs5rGj1nI/AAAAAAAABok/rkyt7IBlxqg6P_L_g3-YBJ2IPd_H5TmFQCLcBGAs/s1600/Scripts.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="397" data-original-width="656" height="120" src="https://2.bp.blogspot.com/-0v5rHJCeNHY/W7Xs5rGj1nI/AAAAAAAABok/rkyt7IBlxqg6P_L_g3-YBJ2IPd_H5TmFQCLcBGAs/s200/Scripts.PNG" width="200" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<span class="scEditorFieldLabelAdministrator">This script will use our custom shared function to apply datasources to items. Here is the code:</span><br />
<br />
<script src="https://gist.github.com/ReoKzK/d7d26f87d106b92296e364f1887ea141.js"></script>
<span class="scEditorFieldLabelAdministrator"><br /></span><br />
First crucial thing is to import our shared function<br />
<br />
<pre>Import-Function -Name Set-RenderingDatasource</pre>
<br />
Then I have added a flag for rolling back changes if needed. That's a subject of decision how we should do the rollback. For this example rollback will be simply setting empty datasources to that items - as they are empty at beginning.<br />
<br />
Under I've added variables that will contain ID of the page where we want make our updates, references to rendering items we want to set datasource and ids of datasources. All those things should be known, as we are assuming they will be deployed by, e.g. unicorn (new renderings and datasources - one time deployment) or they are in the content already for some time - the page we want to update.<br />
<br />
Then, based on the rollback flag, I'm using our imported function to set up datasources<br />
<br />
<pre>Set-RenderingDatasource -Page $updatedPage -Rendering $modalRendering -DatasourceId $modalDatasourceId -Device Default -Publish</pre>
<br />
Let's roll now! Let's edit our script in ISE!<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://3.bp.blogspot.com/-jas72ny-Sqw/W7Xv1G8g0fI/AAAAAAAABow/ovVxjFWwDhA8FEg7vQdWtRbB-JepM4AEwCLcBGAs/s1600/Edit.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="236" data-original-width="801" height="94" src="https://3.bp.blogspot.com/-jas72ny-Sqw/W7Xv1G8g0fI/AAAAAAAABow/ovVxjFWwDhA8FEg7vQdWtRbB-JepM4AEwCLcBGAs/s320/Edit.PNG" width="320" /></a></div>
And run it to see the result:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://4.bp.blogspot.com/-R2o7r-tuR3U/W7Xv95JmyNI/AAAAAAAABo0/99aE1fxsWc8ou-FZUTIuSEjhEmAp8iKtQCLcBGAs/s1600/Script%2Bdone.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="651" data-original-width="1600" height="130" src="https://4.bp.blogspot.com/-R2o7r-tuR3U/W7Xv95JmyNI/AAAAAAAABo0/99aE1fxsWc8ou-FZUTIuSEjhEmAp8iKtQCLcBGAs/s320/Script%2Bdone.PNG" width="320" /></a></div>
<br />
It's good to log the things script does and say something at the end of execution.<br />
<br />
Done! I hope that was interesting lesson of using Sitecore PowerShell to apply changes after deployments. Enjoy!<br />
<br />Radoslaw Kozlowskihttp://www.blogger.com/profile/06810133427607221124noreply@blogger.com0Newcastle upon Tyne, UK54.978252 -1.617780000000038954.8325385 -1.9405035000000388 55.1239655 -1.2950565000000389tag:blogger.com,1999:blog-4507372088071200408.post-20433341204366181162018-09-11T17:12:00.000+02:002018-11-24T17:18:55.492+01:00Sitecore Module - Dynamic Sitemap XML version 2.0I have released updated and rewritten version of my Dynamic Sitemap XML module.Version 2.0 comes with better structure of the code and gives much more flexibility in extending it. Now it uses Sitecore Web index by default to improve the performance.<br />
<br />
Whole code is hosted on GitHub just like before at <a href="https://github.com/ReoKzK/Sitecore.SharedSource.DynamicSitemap">https://github.com/ReoKzK/Sitecore.SharedSource.DynamicSitemap</a>.<br />
<br />
<br />
It can be added to solution by nuget package:<br />
<br />
<pre>Install-Package Sitecore.SharedSource.DynamicSitemap -Version 2.0.0</pre>
<br />Radoslaw Kozlowskihttp://www.blogger.com/profile/06810133427607221124noreply@blogger.com0Newcastle upon Tyne, UK54.978252 -1.617780000000038954.8325385 -1.9405035000000388 55.1239655 -1.2950565000000389tag:blogger.com,1999:blog-4507372088071200408.post-67948713999181127032018-08-21T14:30:00.000+02:002018-11-28T21:44:20.743+01:00HelixComponents - Gallery of frequently used website modulesI have released first part of my HelixComponents project. It's aim is to create reusable components that can be used across Helix-based projects. <br />
<br />
<br />
Each module will be released as a separate repository, which is basically a Helix project. All of them can be taken from my repo at Github: <a href="https://github.com/ReoKzK/HelixComponents">https://github.com/ReoKzK/HelixComponents</a>.<br />
It is based on Helixbase and contains all of these modules.<br />
<br />
Here are the first projects:<br />
<h4>
HelixComponents.Feature.Recommended</h4>
Contains modules used for content promotion<br />
<h4>
HelixComponents.Feature.Tabs</h4>
Tabs components - Work in progress<br />
<br />
Soon I'm going to release more and fix any outstanding issues <br />
Radoslaw Kozlowskihttp://www.blogger.com/profile/06810133427607221124noreply@blogger.com0Newcastle upon Tyne, UK54.978252 -1.617780000000038954.8325385 -1.9405035000000388 55.1239655 -1.2950565000000389tag:blogger.com,1999:blog-4507372088071200408.post-47619273014221163592018-06-10T14:19:00.000+02:002018-11-24T20:10:55.407+01:00Sitecore 9 installation scriptsAs Sitecore 9 installation is much different than in previous versions and we have now Sitecore Installation Framework, I would like to share with you my installation PowerShell scripts.<br />
<br />
First of all, many thanks to George Chang for the Sitecore 9 install script which I based mine (<a href="https://blogs.perficientdigital.com/2017/10/23/how-to-install-sitecore-9-with-the-sitecore-install-framework/">https://blogs.perficientdigital.com/2017/10/23/how-to-install-sitecore-9-with-the-sitecore-install-framework/</a>).<br />
<br />
First thing you will need to do is have Solr installed. It is required from v.9.0 to have Solr running and on SSL. There is a great post by Jeremy Davis about installing Solr easily by his PS script - <a href="https://jermdavis.wordpress.com/2017/10/30/low-effort-solr-installs/">https://jermdavis.wordpress.com/2017/10/30/low-effort-solr-installs/</a>.<br />
<br />
After we have Solr installed and running on https we can start installing our Sitecore 9 instance.<br />
<br />
We need to have Sitecore Installation Framework installed to our PowerShell. Here is the script that takes care of it:<br />
<br />
<script src="https://gist.github.com/ReoKzK/bd13d8380d6e095b58bea1c197535aec.js"></script> <br />
<br />
And here is the Sitecore 9 installation script itself. There is a configuration object as first in the code, you can specify there Sitecore version to install, SQL Server credentials and Solr configuration.<br />
<br />
<script src="https://gist.github.com/ReoKzK/04db88154207d3f47fdeaa7d62d971f3.js"></script>
<br />
All scripts are available on my GitHub: <a href="https://github.com/ReoKzK/Sitecore9-Installer">https://github.com/ReoKzK/Sitecore9-Installer</a><br />
<br />
<br />Radoslaw Kozlowskihttp://www.blogger.com/profile/06810133427607221124noreply@blogger.com0Newcastle upon Tyne, UK54.978252 -1.617780000000038954.8325385 -1.9405035000000388 55.1239655 -1.2950565000000389tag:blogger.com,1999:blog-4507372088071200408.post-14008248000536600452018-05-19T11:13:00.000+02:002018-10-26T11:19:01.162+02:00SIF Sitecore 9 installation issueA couple days ago I came across a problem while installing Sitecore 9.0.2 using SIF: <br />
<br />
<pre>.Net SqlClient Data Provider: Msg 12809, Level 16, State 1, Line 5
You must remove all users with password before setting the containment property to NONE.</pre>
<br />
I was using MS SQL Server 2016 (13.0.4001.0). After opening Management Studio I realized that some databases were created already because at first run my script went to some point then failed. So the easy fix go go through this issue was just to remove these databases as they were only partially completed.<br />
<br />Radoslaw Kozlowskihttp://www.blogger.com/profile/06810133427607221124noreply@blogger.com0Newcastle upon Tyne, UK54.978252 -1.617780000000038954.8325385 -1.9405035000000388 55.1239655 -1.2950565000000389tag:blogger.com,1999:blog-4507372088071200408.post-36747365373324477192018-04-07T19:00:00.000+02:002018-10-12T13:36:47.178+02:00Configuring Unicorn on Helix projectSetting up synchronization in Helix based solution is one of the most crucial things. With proper configuration all new projects will be easy to maintain and predictable. In this short post I will describe basics of configuring Unicorn.<br />
<h3>
Helix structure configuration</h3>
First of all we should have our <span style="font-family: "courier new" , "courier" , monospace;">Foundation.Serialization</span> project configured. In this project we should install Unicorn - from the nuget feed.<br />
<br />
We should have whole Helix items structure configuration here and this one should be synched as the first in the queue.<br />
<br />
<script src="https://gist.github.com/ReoKzK/c34a295e82433cbbe2e7194d55765836.js"></script> <br />
There is <span style="font-family: "courier new" , "courier" , monospace;">unicornSourceFolder</span> variable which should be pointing /src/ folder of our app code. We can specify it for example in some patch in <span style="font-family: "Courier New", Courier, monospace;">Project.Common</span> project.<br />
<br />
<br />
<script src="https://gist.github.com/ReoKzK/ecb834ffdca86ab2bb8e6cad467e6aa9.js"></script> <br />
<br />
<h3>
Abstract configurations</h3>
It is really good idea to have some basic configuration we can inherit from. It can be placed in for example <span style="font-family: "courier new" , "courier" , monospace;">Foundation.Serialization</span> project.<br />
<br />
<br />
<script src="https://gist.github.com/ReoKzK/7deba03e574b44b2264574fbabe967db.js"></script> <br />
<br />
<br />
Then we can use this abstract configuration in our projects<br />
<br />
<br />
<script src="https://gist.github.com/ReoKzK/5415e742a4333af30fce7830c8e01bab.js"></script> <br />
<br />
We do it by using <span style="font-family: "courier new" , "courier" , monospace;">extends</span> parameter<br />
<br />
<pre>extends="SitecoreCoffee.Base"</pre>
<br />
If our project is relying on some other, e.g. from Foundation layer, then we should specify it by dependencies parameter. Here it depends on whole Foundation layer by using asterix<br />
<br />
<pre>dependencies="Foundation.*"</pre>
<br />
...but it could be as well list of comma-delimited configuration names<br />
<br />
<pre>dependencies="Foundation.Search,Foundation.Extensions"</pre>
<br />
As I mentioned earlier, <span style="font-family: "Courier New", Courier, monospace;">Foundation.Serialization</span> configuration should be synchronized as first, so the our patch should go after that one:<br />
<br />
<pre>patch:after="configuration[@name='Foundation.Serialization']"</pre>
<br />
Don't forget to put descriptive <span style="font-family: "courier new" , "courier" , monospace;">name</span> and <span style="font-family: "courier new" , "courier" , monospace;">description</span> attributes too.<br />
<h3>
Project-specific configurations</h3>
In Helix every project which requires some serialized Sitecore items, should have it's own Unicorn configuration. Above we created <span style="font-family: "courier new" , "courier" , monospace;">Feature.Search</span> project configuration and there we put only project-specific items in the predicate<br />
<br />
<pre><predicate type="Unicorn.Predicates.SerializationPresetPredicate, Unicorn" singleInstance="true">
<include name="SitecoreCoffee.Feature.Search.Templates" database="master" path="/sitecore/templates/Feature/Search" />
<include name="SitecoreCoffee.Feature.Search.Renderings" database="master" path="/sitecore/layout/renderings/Feature/Search" />
</predicate>
</pre>
<br />
Even if you're not using Helix you should consider creating several small configurations instead of one monolithic. It will be easier to synch only specific ones in Unicorn synch panel.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://2.bp.blogspot.com/-CHPSrN4U_Yc/W8B687NN8hI/AAAAAAAABpU/7thSon7T8ZoWVe6V6A838_GIKg1u0ynagCLcBGAs/s1600/configs.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="977" data-original-width="1600" height="195" src="https://2.bp.blogspot.com/-CHPSrN4U_Yc/W8B687NN8hI/AAAAAAAABpU/7thSon7T8ZoWVe6V6A838_GIKg1u0ynagCLcBGAs/s320/configs.PNG" width="320" /></a></div>
<br />
<br />
<br />
<br />Radoslaw Kozlowskihttp://www.blogger.com/profile/06810133427607221124noreply@blogger.com0Newcastle upon Tyne, UK54.978252 -1.617780000000038954.8325385 -1.9405035000000388 55.1239655 -1.2950565000000389tag:blogger.com,1999:blog-4507372088071200408.post-86280841056305966292018-03-12T12:10:00.000+01:002018-10-11T16:17:28.918+02:00Using SitecoreController to change page startupA few days ago I had to implement functionality that will check if external e-commerce system is healthy before any further page processing. I decided to prepare maintenance page in Sitecore and switch to it if there are problems with API. Here the problem appeared - how to make it clean and use already DIed services there?<br />
<br />
I could use <span style="font-family: "courier new" , "courier" , monospace;">httpBeginRequest</span> pipeline and put my processor just after Context.Item is resolved. Sounds alright but I wanted to avoid adding unnecessary processors and patches as much as I could.<br />
<br />
Then I found really interesting post written by Marek Musielak:<br />
<br />
<a class="blog-link" href="https://www.skillcore.net/sitecore/sitecore-item-controller-and-page-rules" style="border-radius: 5px; border: 2px solid #787878; display: block; padding: 6px 12px 10px;" target="_blank">
<span class="title" style="display: block; font-weight: bold;">Sitecore Item Controller - the hidden gem of Sitecore MVC</span>
<span style="display: block;">https://www.skillcore.net/sitecore/sitecore-item-controller-and-page-rules</span>
</a>
<br />
I decided I will go with this approach and utilize SitecoreController. Marek described precisely how to set up that new controller and where to refere it in template. Here I will describe how I used it.<br />
<br />
<h4>
Controller setup</h4>
My controller will be responsible for checking external commerce health before any rendering and API call is made. It should extend <span style="font-family: "courier new" , "courier" , monospace;">SitecoreController</span> that exists in <span style="font-family: "courier new" , "courier" , monospace;">Sitecore.Mvc.Controllers</span> namespace (<span style="font-family: "courier new" , "courier" , monospace;">Sitecore.Mvc</span> assembly). I'm using there two services - one that wraps context item switching and second one for API calls. I found out that there should be only one parameterless constructor in this controller. Unfortunately then you can't inject services properly - only way is to use service locator antipattern!<br />
<br />
<script src="https://gist.github.com/ReoKzK/2c0f7740e6b503276f1c37f91df31a25.js"></script>
Further, you should override <span style="font-family: "courier new" , "courier" , monospace;">Index()</span> method and do your stuff there. I'm calling heartbeat service and if system is dead I'm switching context page item to maintenance page. I'm checking as well if maintenance mode was explicitly set in site settings item. And if we are in Experience Editor we don't want this switching to happen, so I'm checking for that option as well. At the end we need to call base <span style="font-family: "courier new" , "courier" , monospace;">Index()</span> method. <br />
<br />
Be aware: heartbeat check action must be fast as Flash or even faster. You don't want to add much more rendering time to page. Sometimes it's even better to do that check on client side, but that's more SPA approach. Just make sure it finishes in desired period of time and even drop the execution if it takes more! You can use async calls and cancellation tokens - here I found some nice article by Dave Paquette you can begin with, but that's surely something outside Sitecore: <a href="https://www.davepaquette.com/archive/2015/07/19/cancelling-long-running-queries-in-asp-net-mvc-and-web-api.aspx">https://www.davepaquette.com/archive/2015/07/19/cancelling-long-running-queries-in-asp-net-mvc-and-web-api.aspx</a><br />
<br />
<h4>
Page template setup</h4>
As Marek described, we need to bind our controller with template's Standard Values to make it work. <br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://3.bp.blogspot.com/-9d9SXzeZUQY/WqJyqNZVXXI/AAAAAAAABf8/Ryt3jrffT84-e29DEDc81-WvtJUCUVRswCLcBGAs/s1600/Template%2Busing%2BSitecoreController.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img alt="Template using SitecoreController" border="0" data-original-height="387" data-original-width="885" height="279" src="https://3.bp.blogspot.com/-9d9SXzeZUQY/WqJyqNZVXXI/AAAAAAAABf8/Ryt3jrffT84-e29DEDc81-WvtJUCUVRswCLcBGAs/s640/Template%2Busing%2BSitecoreController.PNG" title="" width="640" /></a></div>
<br />
And that's it, this functionality will run before any rendering start to be processed.<br />
<br />
<br />
Whole implementation is available on my Helix examples and experiments project on GitHub: <br />
<br />
<a class="blog-link" href="https://github.com/ReoKzK/SitecoreCoffee/tree/master/src/Feature/Commerce/code" style="border-radius: 5px; border: 2px solid #787878; display: block; padding: 6px 12px 10px;" target="_blank">
<span class="title" style="display: block; font-weight: bold;">ReoKzK/SitecoreCoffee</span>
<span style="display: block;">https://github.com/ReoKzK/SitecoreCoffee/tree/master/src/Feature/Commerce/code</span>
</a>
<br />
<br />Radoslaw Kozlowskihttp://www.blogger.com/profile/06810133427607221124noreply@blogger.com0Newcastle upon Tyne, UK54.978252 -1.617780000000038954.8325385 -1.9405035000000388 55.1239655 -1.2950565000000389tag:blogger.com,1999:blog-4507372088071200408.post-5493410781109343982017-11-27T11:52:00.000+01:002017-12-16T18:56:04.206+01:00Custom Remote Events for Cache Rebuild mechanismA couple of months ago I had to jump into a project for a while and I came across a problem with refreshing custom cache on content delivery servers. There was a custom cache mechanism that was running on each instance separately. It was relying on items based on specific template, every time one of these items was updated or created/removed, cache should be updated. I found out that the best way to refresh that is to prepare custom remote event.<br />
<br />
<h4>
The problem</h4>
I had to make sure that after publishing specific items, cache will be rebuilt. My first thought was to use <span style="font-family: "courier new" , "courier" , monospace;">publish:end</span> event, so I could check if one of that items was published. But here the problem with checking came out. There is a parameter of class <span style="font-family: "courier new" , "courier" , monospace;">Publisher </span>that is put to <span style="font-family: "courier new" , "courier" , monospace;">EventArgs </span>on position 0. Unfortunately, it doesn't contain any list of published items, just the root item:<br />
<br />
<blockquote class="tr_bq">
publisher.Options.RootItem</blockquote>
<br />
...or maybe fortunately, for huge amount of items published :) Anyway, if we are relying only on this property, we need to go through all items recursively to find the specific one:<br />
<br />
<blockquote class="tr_bq">
publisher.Options.RootItem.Axes.GetDescendants().Any(x => x.TemplateID.ToString() == SpecificTemplateId)</blockquote>
You might see that here, on some publish events, using Axes and GetDescendants() is not very good idea (most of times it's not!). And we need to keep in mind that RootItem will be null if user ran full site publish...<br />
<br />
<h4>
Improve the performance </h4>
Okay, maybe some better ideas? Yes. There is an event called <span style="font-family: "courier new" , "courier" , monospace;">publish:itemProcessed</span> that is fired every time an item is processed during publish. We can use it to find if currently processed item is based on specific template and then set some flag.<br />
<br />
<script src="https://gist.github.com/ReoKzK/dd07b93a5382dc5f6430abfb4a8de157.js"></script>
<br />
Flag used here will be static property of the event handler class:<br />
<br />
<pre style="background: #1e1e1e; color: gainsboro; font-family: Consolas; font-size: 13;"><span style="color: #608b4e;">///</span><span style="color: #608b4e;"> </span><span style="color: #608b4e;"><</span><span style="color: #608b4e;">summary</span><span style="color: #608b4e;">></span>
<span style="color: #608b4e;">///</span><span style="color: #608b4e;"> Static flag that indicates if any specific item was published</span>
<span style="color: #608b4e;">///</span><span style="color: #608b4e;"> </span><span style="color: #608b4e;"></</span><span style="color: #608b4e;">summary</span><span style="color: #608b4e;">></span>
<span style="color: #569cd6;">protected</span> <span style="color: #569cd6;">static</span> <span style="color: #569cd6;">bool</span> SpecificItemWasPublished <span style="color: #b4b4b4;">=</span> <span style="color: #569cd6;">false</span>;</pre>
<br />
<br />
After all items have been processed, the <span style="font-family: "courier new" , "courier" , monospace;">publish:end</span> event will be raised. Here we can check if flag is set to true and run cache refresh action. This solution will work gracefully on single server application, but on CM/CD separated instances it will work only on Content Management server. We need to work out a better solution using custom remote events.<br />
<br />
<h3>
Using custom remote event</h3>
Custom remote event will be the best option to solve this problem. Our cache refreshing system will work like this<br />
<ol>
<li>While publishing we check if specific item is published - on <span style="font-family: "courier new" , "courier" , monospace;">publish:itemProcessed</span> event. If there is one, we set up the flag.</li>
<li>When publishing finishes (<span style="font-family: "courier new" , "courier" , monospace;">publish:end</span>) we check the flag. If flag is set up, we raise cache rebuild event</li>
<li>Cache rebuild event will raise remote event for cache rebuild. </li>
</ol>
Using this approach all hard work, like checking specific item published, will take place on the local server, remote servers will just do what first told them. It all works using EventQueue.<br />
<br />
<b>1. Class for remote event representation</b><br />
First thing that we will need will be class that represents an event. There is no base class to derive or interface to implement, it can be plain class but members need to be serializable. In our example we will have a boolean flag that will indicate if full rebuild is needed.<br />
<br />
<script src="https://gist.github.com/ReoKzK/7656ddee1b3e9b7e863d335289044738.js"></script>
<b>2. Event raiser class</b><br />
Next we will need a handy class that will be able to raise the event locally and add request to Event Queue for raising it on remote servers.<br />
<br />
<script src="https://gist.github.com/ReoKzK/84acdcab04fe872398b363efccc13537.js"></script>
<b>3. Pipeline processor for initializing event subscription</b><br />
We need<b> </b>to create a pipeline processor that will subscribe to those remote events.<b> </b><br />
<br />
<script src="https://gist.github.com/ReoKzK/fa99f50e1ee3a6c7460fdb500f5cd39b.js"></script><b>
4. Event handlers class</b><br />
This class will contain our event handlers. As described earlier <span style="font-family: "courier new" , "courier" , monospace;">OnItemProcessed </span>will check if currently processed item is based on specific template and set up flag if found. <span style="font-family: "courier new" , "courier" , monospace;">OnPublishEnd </span>will check that flag when publishing is finished and raise cache rebuild event using prepared earlier event raiser. Last event handler <span style="font-family: "courier new" , "courier" , monospace;">OnCustomCacheRebuild </span>will do the actual call to index mechanism for cache rebuild.<br />
<br />
<script src="https://gist.github.com/ReoKzK/b3872d65c79bb549fd657b873f8bb0ee.js"></script>
<b>5. Sitecore config patch</b><br />
At last we have to bind all event handlers and processors into Sitecore. This Sitecore config patch does that:<br />
<b> </b><br />
<script src="https://gist.github.com/ReoKzK/f1af9fd73224f69a35ce04f3c32878fa.js"></script>
And that's all, with all these parts our system is ready to use.<br />
<br />
<br />
<h4>
<b>Testing solution </b></h4>
To test our solution we need to set up two Sitecore instances on our local machine, first for CM role, latter for CD role.They need to have different InstanceName properties set in <span style="font-family: "courier new" , "courier" , monospace;">App_Config\Include\ScalabilitySettings.config</span>. <br />
<br />
<pre class="tr_bq"><span style="font-size: x-small;"><span style="font-family: "courier new" , "courier" , monospace;"><span style="font-size: small;"><setting name="InstanceName">
<patch:attribute name="value">SitecoreCoffeeCM</patch:attribute>
</setting></span> </span></span></pre>
<br />
As well those two instances need to use the same databases. <br />
<br />
After setting up those instances and publishing item based on specified template on CM server, there will be new record created in Core database in EventQueue table:<br />
<br />
<pre class="tr_bq"><span style="font-size: small;"><span style="font-family: "courier new" , "courier" , monospace;"><b>Id</b>: C3386293-8E1B-4EBB-A490-D57DC663E61B
<b>EventType</b>: SitecoreCoffee.Foundation.RemoteEvents.Events.CacheRebuildEvent, SitecoreCoffee.Foundation.RemoteEvents, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null
<b>InstanceType</b>: SitecoreCoffee.Foundation.RemoteEvents.Events.CacheRebuildEvent, SitecoreCoffee.Foundation.RemoteEvents, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null
<b>InstanceData</b>: {"FullRebuild":true}
<b>InstanceName</b>: SitecoreCoffeeCM
<b>RaiseLocally</b>: 0
<b>RaiseGlobally</b>: 1
<b>UserName</b>: sitecore\admin
<b>Stamp</b>: 0x0000000000032E9E
<b>Created</b>: 2017-11-21 23:20:01.267</span></span></pre>
<br />
And as well on those two instances cache will be rebuilt:<br />
<br />
<pre class="tr_bq"><span style="font-size: small;"><span style="font-family: "courier new" , "courier" , monospace;">ManagedPoolThread #2 23:20:01 INFO CacheRebuildEventHandler: Rebuilding the cache.</span></span>
<span style="font-size: small;"><span style="font-family: "courier new" , "courier" , monospace;">ManagedPoolThread #2 23:20:01 INFO CacheRebuildService: Cache rebuilt (full: True)</span></span>
<span style="font-size: small;"><span style="font-family: "courier new" , "courier" , monospace;">ManagedPoolThread #2 23:20:01 INFO CacheRebuildEventHandler: Cache rebuilt in 0 seconds.</span></span></pre>
<br />
<h4>
Summary</h4>
Solution described above explains how to use custom events in Sitecore to create efficient mechanism that will rebuild cache on local and remote servers, when specific item is published. It can be used to perform any other type of action that will require additional activity taken on remote servers.<br />
<br />
Full code is available in my Helix solution here: <a href="https://github.com/ReoKzK/SitecoreCoffee">https://github.com/ReoKzK/SitecoreCoffee</a><br />
<br />
Happy Sitecoring!Radoslaw Kozlowskihttp://www.blogger.com/profile/06810133427607221124noreply@blogger.com0Newcastle upon Tyne, UK54.978252 -1.617780000000038954.8325385 -1.9405035000000388 55.1239655 -1.2950565000000389tag:blogger.com,1999:blog-4507372088071200408.post-11390415838876236732017-08-31T23:29:00.000+02:002017-09-11T23:35:02.968+02:00Solr queries errors related to Sitecore SocialLast time I saw that there is a a number of Solr error logs on my Sitecore instances:<br />
<br />
<a name='more'></a><br /><br />
<pre id="aui-3-18-0-4_6722">ManagedPoolThread #2 2017:08:06 16:45:50 ERROR Solr Error : ["undefined field 0001-01-01T00"] - Query attempted: [((posted_date_tdt:(0001-01-01T00:00:00Z) AND (final_workflow_state_b:(True) OR workflow_state_s:(00000000000000000000000000000000))) AND (_template:(d7851f00e8694f9381f5b5338eff58a9) OR _template:(06751e29d91b423ca2e1e54afd4f8f0b) OR _template:(e28734ca89eb4530b0e4b81f6645a372)))]</pre>
<br />
<br />
Quick look at the query and it seems like dates are no escaped before putting them inside. This issue is connected with Sitecore Social, as the template ids are coming from that place. I have raised a bug in Sitecore Support and here it goes, patch that solves this issue:<br />
<br />
<a href="https://sitecore.box.com/s/ux7m0wkkgobxndf0ihqjgawhnlhcacp1">https://sitecore.box.com/s/ux7m0wkkgobxndf0ihqjgawhnlhcacp1</a><br />
<br />
It's reference number in Sitecore bug tracking system is 173890. After applying, no more unnecessary error log entries!<br />
<br />
<div style="text-align: center;">
<a href="https://2.bp.blogspot.com/-WZGg4QDCHyg/WbJ1OdBdVlI/AAAAAAAABYo/qnRC8ErP7PUAUt4T6d3nwfcBSudYmTGlgCLcBGAs/s1600/platform-solr-logo-330x200.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="200" data-original-width="330" src="https://2.bp.blogspot.com/-WZGg4QDCHyg/WbJ1OdBdVlI/AAAAAAAABYo/qnRC8ErP7PUAUt4T6d3nwfcBSudYmTGlgCLcBGAs/s1600/platform-solr-logo-330x200.png" /></a></div>
Radoslaw Kozlowskihttp://www.blogger.com/profile/06810133427607221124noreply@blogger.com0Newcastle upon Tyne, Wielka Brytania54.978252 -1.617780000000038954.8325385 -1.9405035000000388 55.1239655 -1.2950565000000389tag:blogger.com,1999:blog-4507372088071200408.post-49308807723851860092017-03-31T19:10:00.000+02:002017-04-03T14:13:07.947+02:00Translating Sitecore ClientTranslating Sitecore Client to another language is not so tough issue. Sitecore comes with a pretty clean solution here. In this article we will use Sitecore 8.2 Update-2.<br />
<br />
There are some ready-to-install client translations at Sitecore download site (section "Client Translations"): <a href="https://dev.sitecore.net/Downloads/Sitecore_Experience_Platform/82/Sitecore_Experience_Platform_82_Update2.aspx">https://dev.sitecore.net/Downloads/Sitecore_Experience_Platform/82/Sitecore_Experience_Platform_82_Update2.aspx</a>. The choice is not too big, there are only for Danish, German and Japanese. Fortunately, we can create our own client translation.<br />
<br />
<h4>
Preparation</h4>
First of all, we need to install language in Sitecore on specific database. We will start with core, where most of our client translations are kept. Let's go to Desktop and switch to Core db. After that let's go to Control Panel. Here we should add new language and set language code for it. In my example I will add Polish language<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://4.bp.blogspot.com/-P3i8jMFmpy8/WMfk_7dQe6I/AAAAAAAABNk/9byIzFJ3gIktE8XFaD15WF61G9hSjDMXACLcB/s1600/AddNewLanguage.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img alt="Sitecore - Control Panel - Add new Language" border="0" height="291" src="https://4.bp.blogspot.com/-P3i8jMFmpy8/WMfk_7dQe6I/AAAAAAAABNk/9byIzFJ3gIktE8XFaD15WF61G9hSjDMXACLcB/s640/AddNewLanguage.PNG" title="" width="640" /></a></div>
<br />
I'm leaving all steps with default values, so my Polish language code will be "pl-PL". After that we can check it in Content Editor under <span style="font-family: "courier new" , "courier" , monospace;">/sitecore/system/Languages</span>:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://4.bp.blogspot.com/-iLpdzD23wc0/WMfo9qZkdRI/AAAAAAAABN4/HnixObWjXBQMDbRT-NQu0LKT_N6ZJooMQCLcB/s1600/LanguageInCoreDb.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img alt="Sitecore - Content Editor - Languages" border="0" height="422" src="https://4.bp.blogspot.com/-iLpdzD23wc0/WMfo9qZkdRI/AAAAAAAABN4/HnixObWjXBQMDbRT-NQu0LKT_N6ZJooMQCLcB/s640/LanguageInCoreDb.PNG" title="" width="640" /></a></div>
<br />
<h4>
Exporting language file</h4>
At this point we need to have a file that will be our source for translation. In other words, we need to export language file from one of existing languages in Sitecore. To achieve that, let's go again to Control Panel. There should be Core database selected as earlier. In Control Panel click on the Export languages and select the language you want to base your translation on:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://2.bp.blogspot.com/-eFK8nspcNHw/WN0DHGxjwmI/AAAAAAAABOc/Hg223ECGPC4aJYChDTW0j6yC4Nxv1NNNACLcB/s1600/Export%2Blanguage.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img alt="Sitecore - Control Panel - Export language" border="0" height="294" src="https://2.bp.blogspot.com/-eFK8nspcNHw/WN0DHGxjwmI/AAAAAAAABOc/Hg223ECGPC4aJYChDTW0j6yC4Nxv1NNNACLcB/s640/Export%2Blanguage.PNG" title="" width="640" /></a></div>
<br />
After clicking next, you can choose which branch to export. For making translations select sitecore root item:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://3.bp.blogspot.com/-9nDjohaRZSo/WN0D4511BMI/AAAAAAAABOk/kMfMmn4fxQcQhW0O1wDeCya8WDdCgHf6gCLcB/s1600/Export%2Blanguage%2B-%2Bselect%2Bitem.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img alt="Sitecore - Control Panel - Export language - select item" border="0" height="400" src="https://3.bp.blogspot.com/-9nDjohaRZSo/WN0D4511BMI/AAAAAAAABOk/kMfMmn4fxQcQhW0O1wDeCya8WDdCgHf6gCLcB/s400/Export%2Blanguage%2B-%2Bselect%2Bitem.PNG" title="" width="325" /></a></div>
<br />
After that you will be prompted for location of generated file. In the end Sitecore will process all items and language xml file will be generated.<br />
<br />
<h4>
Preparing language file</h4>
Let's take a quick glimpse to the exported language file. You can see that this is just xml file with <phrase> elements. Each that element represents single field of item and contains attributes like:<br />
<ul>
<li><span style="font-family: "courier new" , "courier" , monospace;">path </span>- path of the item</li>
<li><span style="font-family: "courier new" , "courier" , monospace;">itemid </span>- id of the item </li>
<li><span style="font-family: "courier new" , "courier" , monospace;">key </span>- key name of field</li>
<li><span style="font-family: "courier new" , "courier" , monospace;">fieldid </span>- name of the field</li>
<li><span style="font-family: "courier new" , "courier" , monospace;">updated </span>- date of field update</li>
</ul>
Inside <phrase>, there is another xml element named after the language code. It surrounds the field value we will translate.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://4.bp.blogspot.com/-loeKzEFHThc/WN0F20GpxhI/AAAAAAAABOw/EEMQVaUYFPkm8D-1ek8_kjYveAv_woRVgCLcB/s1600/Exported%2Blanguage%2Bfile.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img alt="Sitecore - Exported language file" border="0" height="297" src="https://4.bp.blogspot.com/-loeKzEFHThc/WN0F20GpxhI/AAAAAAAABOw/EEMQVaUYFPkm8D-1ek8_kjYveAv_woRVgCLcB/s640/Exported%2Blanguage%2Bfile.PNG" title="" width="640" /></a></div>
<br />
Next thing is to replace language elements with our destination language. In my case it will be <span style="font-family: "courier new" , "courier" , monospace;">pl-PL</span>. The easiest and fastest way will be use some text editor and globally replace:<br />
<ul>
<li><span style="font-family: "courier new" , "courier" , monospace;"><en> </span>to <span style="font-family: "courier new" , "courier" , monospace;"><pl-PL></span></li>
<li><span style="font-family: "courier new" , "courier" , monospace;"></en></span> to <span style="font-family: "courier new" , "courier" , monospace;"></pl-PL></span></li>
</ul>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://1.bp.blogspot.com/-AKLZR12DPlM/WN0QRL2PKAI/AAAAAAAABPQ/98AAyQ1yVhAFzHKLVksl8Egm4sGvdDf4gCLcB/s1600/Replace%2Bglobally.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img alt="Replace globally" border="0" height="270" src="https://1.bp.blogspot.com/-AKLZR12DPlM/WN0QRL2PKAI/AAAAAAAABPQ/98AAyQ1yVhAFzHKLVksl8Egm4sGvdDf4gCLcB/s400/Replace%2Bglobally.PNG" title="" width="400" /></a></div>
<br />
<br />
And that's it! File is prepared for sending to some translation services. They just need to know what they have to translate:<br />
<br />
<blockquote class="tr_bq">
<span style="font-size: x-small;"><span style="font-family: "courier new" , "courier" , monospace;"><phrase path="/sitecore/client/Speak/Layouts/Renderings/Common" key="Common" itemid="{1F2A25A4-A532-4E9B-9942-1FA6F10F61B0}" fieldid="__Short description" updated="20130814T120321Z"><br /> <pl-PL><b>Common controls like buttons, input fields, and lists.</b></pl-PL><br /> </phrase></span></span></blockquote>
In my case it should be translated to:<br />
<br />
<blockquote class="tr_bq">
<span style="font-size: x-small;"><span style="font-family: "courier new" , "courier" , monospace;"><phrase
path="/sitecore/client/Speak/Layouts/Renderings/Common" key="Common"
itemid="{1F2A25A4-A532-4E9B-9942-1FA6F10F61B0}" fieldid="__Short
description" updated="20130814T120321Z"><br /> <pl-PL><b>Wspólne kontrolki, takie jak przyciski, pola wprowadzania, czy listy.</b></pl-PL><br /> </phrase></span></span></blockquote>
<br />
Just trust me ;)<br />
<br />
<h4>
Importing prepared language file</h4>
As we have our language file translated we can import it to Sitecore. Before that, it is highly recommended to backup processed database - in our case Core database. After our backup is done we can import our translation file. To achieve that let's go to Control Panel and click Import languages:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://2.bp.blogspot.com/-WA9rbhkd_No/WN5i629Fy2I/AAAAAAAABP0/vYI5VKhLMg0gO9HtREn_k6u5RKe-bII1QCLcB/s1600/Import%2Blanguages%2B-%2BControl%2Bpanel.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img alt="Sitecore - Control Panel - Import languages" border="0" height="294" src="https://2.bp.blogspot.com/-WA9rbhkd_No/WN5i629Fy2I/AAAAAAAABP0/vYI5VKhLMg0gO9HtREn_k6u5RKe-bII1QCLcB/s640/Import%2Blanguages%2B-%2BControl%2Bpanel.PNG" title="" width="640" /></a></div>
<br />
Then we need to upload our prepared xml file (or put it somewhere in webroot of our Sitecore). After selecting the file, Sitecore should recognize what language we are importing.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://1.bp.blogspot.com/-AWpGOfSOfE8/WN5jhJgyl-I/AAAAAAAABP8/TLHZngnSyScvwB5OwwSW96H6AAV6M-bywCLcB/s1600/Import%2Blanguages%2B-%2BPL.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img alt="Sitecore - Control Panel - Import languages" border="0" height="400" src="https://1.bp.blogspot.com/-AWpGOfSOfE8/WN5jhJgyl-I/AAAAAAAABP8/TLHZngnSyScvwB5OwwSW96H6AAV6M-bywCLcB/s400/Import%2Blanguages%2B-%2BPL.PNG" title="" width="322" /></a></div>
<br />
Then we need to select the database which items we were translating - for us it is the Core database.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://2.bp.blogspot.com/-zAfANa9eVXY/WN5kTRU2mwI/AAAAAAAABQE/J7IymMB_48MX6AtyYVFI41YZ3SxDfqZtACLcB/s1600/Import%2Blanguages%2B-%2Bdatabase.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img alt="Sitecore - Control Panel - Import languages" border="0" height="400" src="https://2.bp.blogspot.com/-zAfANa9eVXY/WN5kTRU2mwI/AAAAAAAABQE/J7IymMB_48MX6AtyYVFI41YZ3SxDfqZtACLcB/s400/Import%2Blanguages%2B-%2Bdatabase.PNG" title="" width="325" /></a></div>
<br />
After a while import will be finished.<br />
<br />
<h4>
Configuring Sitecore client language</h4>
After the import we can use our language. One of the ways is to set globally Sitecore client language in the Control Panel. In the My settings section, there is a Region and languages options link. It opens window where we can set viewing formats and Display language:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://1.bp.blogspot.com/-hdoldAAsVJ8/WN5k0GJfobI/AAAAAAAABQM/mDpCn71hB2gYMRkKLy6exYVifctYzvRVwCLcB/s1600/Control%2BPanel%2B-%2BLanguage%2Boptions.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img alt="Sitecore - Control Panel - Region and languages options" border="0" height="292" src="https://1.bp.blogspot.com/-hdoldAAsVJ8/WN5k0GJfobI/AAAAAAAABQM/mDpCn71hB2gYMRkKLy6exYVifctYzvRVwCLcB/s640/Control%2BPanel%2B-%2BLanguage%2Boptions.PNG" title="" width="640" /></a></div>
<br />
<div class="separator" style="clear: both; text-align: left;">
After setting it, you will be prompted to refresh browser window - and you can enjoy the translated Sitecore! More info on installing translations can be found on Sitecore documentation: <a href="https://dev.sitecore.net/Downloads/Sitecore_Experience_Platform/82/~/link.aspx?_id=D72CBF8CE581436CBBCAEE896C8646F7&_z=z">https://dev.sitecore.net/Downloads/Sitecore_Experience_Platform/82/~/link.aspx?_id=D72CBF8CE581436CBBCAEE896C8646F7&_z=z</a></div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
Another way is to set the language just for the user. We can find it in the User Manager by clicking Edit on selected user and setting Client language on Language settings tab.</div>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://4.bp.blogspot.com/-Thc7s2bt0do/WN5mtO-SkEI/AAAAAAAABQY/2sl1j3Oe16EjaqQluz7eD0EQm1WU6fimQCLcB/s1600/User%2Bmanager%2B-%2Blanguage%2Bsettings.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img alt="Sitecore - User Manager - Language settings" border="0" height="294" src="https://4.bp.blogspot.com/-Thc7s2bt0do/WN5mtO-SkEI/AAAAAAAABQY/2sl1j3Oe16EjaqQluz7eD0EQm1WU6fimQCLcB/s640/User%2Bmanager%2B-%2Blanguage%2Bsettings.PNG" title="" width="640" /></a></div>
<br />
<h4>
Translating master database</h4>
We were translating only core items, but we can also translate master database items. I might not have sense for all Sitecore items, but for short descriptions of main items like content, layouts, templates, etc.<br />
<br />
<br />
Happy translating!<br />
<br />Radoslaw Kozlowskihttp://www.blogger.com/profile/06810133427607221124noreply@blogger.com1Bialystok, Poland53.132488599999988 23.16884030000005652.980044599999985 22.846116800000058 53.284932599999991 23.491563800000055tag:blogger.com,1999:blog-4507372088071200408.post-89484432921524283622017-02-28T21:37:00.000+01:002017-03-03T11:26:51.810+01:00Sitecore development basics - Tools overviewAs a Sitecore beginner it is very hard to get to know with all the tools used in Sitecore development process. Especially that you don't even know that some of them even exist. In this article I will try to collect must-haves that every Sitecore developer should know and use.<br />
<br />
<h4>
Object mapping</h4>
Object mapping frameworks are very useful in Sitecore. Using some objects based on transparent classes with full Intellisense support is more comfy than using Items with fields explicitly. <br />
<br />
<a href="https://1.bp.blogspot.com/-7e-Si0G4uUI/WHTk67-WQjI/AAAAAAAABGI/ebViQUgzh5Efr49XRe4fu2R45QaST6TAACLcB/s1600/glass.png" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" height="200" src="https://1.bp.blogspot.com/-7e-Si0G4uUI/WHTk67-WQjI/AAAAAAAABGI/ebViQUgzh5Efr49XRe4fu2R45QaST6TAACLcB/s200/glass.png" style="background: white; padding: 20px;" width="196" /></a><b>Glass.Mapper</b> is the most popular ORM for Sitecore. It gives the availability to map Sitecore items to strongly typed objects, then they can be used in general code and unit tests as well. Glass is well optimized and easy to use.<br />
<br />
Glass.Mapper has its own website - <a href="http://glass.lu/">http://glass.lu/</a>.<br />
Tutorials can be found there also - <a href="http://glass.lu/Mapper/Sc/Tutorials">http://glass.lu/Mapper/Sc/Tutorials</a>.<br />
<br />
<br />
<br />
<h4>
</h4>
<b>Fortis</b> is a tool similar to Glass but it is more like a wrapper than the mapper. It encapsulates Sitecore items with interfaces. Code is available here: <a href="https://github.com/Fortis-Collection/fortis">https://github.com/Fortis-Collection/fortis</a> and more info about usage here: <a href="http://fortis.ws/quick-start/">http://fortis.ws/quick-start/</a> and here: <a href="http://fortis.ws/about/">http://fortis.ws/about/</a><br />
<b> </b><br />
<br />
<b>Synthesis </b>takes different approach than the two ones described earlier. It generates code based on templates in Sitecore instead of mapping fields or wrapping items. It is also very fast. Synthesis code is available on GitHub - <a href="https://github.com/kamsar/Synthesis">https://github.com/kamsar/Synthesis</a> and more info on wiki there <a href="https://github.com/kamsar/Synthesis/wiki">https://github.com/kamsar/Synthesis/wiki</a><br />
<br />
<h4>
</h4>
<h4>
Serialization</h4>
Data serialization is a must in Sitecore projects. Solution must have a way to transfer templates, layouts and other types of items to different environments. It also should be automated for e.g deployments. Luckily there are some cool tools that solve this problem.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://1.bp.blogspot.com/-WeVI6sQ8gao/WHTooybkKaI/AAAAAAAABGc/7Rl_vmPwoKAhdb3AHnPWsesWtGzPe4GGQCLcB/s1600/tds.png" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" height="112" src="https://1.bp.blogspot.com/-WeVI6sQ8gao/WHTooybkKaI/AAAAAAAABGc/7Rl_vmPwoKAhdb3AHnPWsesWtGzPe4GGQCLcB/s200/tds.png" width="200" /></a></div>
<b>Team Development for Sitecore (TDS)</b> is a tool from Hedgehog Development that gives availability to put and manage Sitecore items from the Visual Studio. Beside the serialization features it has a lot of other functionalities like code generation, <i>.update </i>package generation, delta deployments and many more. It is easy to use as well. <br />
<br />
Official website - <a href="http://www.teamdevelopmentforsitecore.com/">http://www.teamdevelopmentforsitecore.com/</a><br />
Documentation - <a href="http://hedgehogdevelopment.github.io/tds/">http://hedgehogdevelopment.github.io/tds/</a><br />
<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://3.bp.blogspot.com/-hIdUVg3d21Q/WHTo5zRm9wI/AAAAAAAABGg/AdqUwj_88IwLjiDf-ItSWhAK3Tz6Pq8YgCLcB/s1600/unicorn_thumb.jpg" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" height="181" src="https://3.bp.blogspot.com/-hIdUVg3d21Q/WHTo5zRm9wI/AAAAAAAABGg/AdqUwj_88IwLjiDf-ItSWhAK3Tz6Pq8YgCLcB/s200/unicorn_thumb.jpg" width="200" /></a></div>
<b>Unicorn </b>- tool from Connective DX, created by Kam Figy. Solves the same problems as TDS but in a bit different way. Whole serialization setup is configured in config patches and also there is a web console to fire the synchronization. Worth to mention are also Rainbow - new serialization engine using yaml files for items (they merge excellently) and also transparent sync. And off course it is free to use.<br />
<br />
Repo at GitHub - <a href="https://github.com/kamsar/Unicorn">https://github.com/kamsar/Unicorn</a><br />
Kam's blog - <a href="http://kamsar.net/">http://kamsar.net/</a> - highly recommended source for new versions information.<br />
<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://3.bp.blogspot.com/-AGckoigdja8/WLfgwc5pqgI/AAAAAAAABKE/bcC5ykMhqNUYyD1y-UQRpX3qiPZKfKTHQCLcB/s1600/user4919_pic11858_1270227074.jpg" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" height="200" src="https://3.bp.blogspot.com/-AGckoigdja8/WLfgwc5pqgI/AAAAAAAABKE/bcC5ykMhqNUYyD1y-UQRpX3qiPZKfKTHQCLcB/s200/user4919_pic11858_1270227074.jpg" width="200" /></a></div>
<b>Sitecore Courier</b> is a tool that can build Sitecore update packages automatically. It can analyze serialized items and pack only changed ones. It comes with console runner, so builing packages is even easier. You can find it at Sitecore Marketplace: <a href="https://marketplace.sitecore.net/en/Modules/Sitecore_Courier.aspx">https://marketplace.sitecore.net/en/Modules/Sitecore_Courier.aspx</a> and the code is located at GitHub: <a href="https://github.com/adoprog/Sitecore-Courier">https://github.com/adoprog/Sitecore-Courier</a>. More info can be found at blog by Alexander Doroshenko: <a href="http://sitecoresnippets.blogspot.com/2012/10/sitecore-courier-effortless-packaging.html">http://sitecoresnippets.blogspot.com/2012/10/sitecore-courier-effortless-packaging.html</a><br />
<br />
<br />
<br />
<h4>
Continuous Integration</h4>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://1.bp.blogspot.com/-QYlARX7Draw/WLfkV1ClqtI/AAAAAAAABKc/Fi9EBSR81EI6hzcKGnfrASWPWCvAjJDlwCLcB/s1600/1688482.png" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" height="200" src="https://1.bp.blogspot.com/-QYlARX7Draw/WLfkV1ClqtI/AAAAAAAABKc/Fi9EBSR81EI6hzcKGnfrASWPWCvAjJDlwCLcB/s200/1688482.png" style="background: white; padding: 10px;" width="200" /></a></div>
<b>Sitecore Ship</b> is a tool that gives availability to install Sitecore update packages remotely. As TDS and Unicorn have their own hooks for integrating with CI systems, Sitecore Ship fills a lack of it in Sitecore Courier. Full code is available on GitHub: <a href="https://github.com/kevinobee/Sitecore.Ship">https://github.com/kevinobee/Sitecore.Ship</a>. Api documentation is here: <a href="http://docs.sitecoreship.apiary.io/">http://docs.sitecoreship.apiary.io/</a>. There are also PowerShell functions by Patrick Perrone <a href="https://github.com/patrickperrone/Sitecore.Ship-PowerShell-Functions">https://github.com/patrickperrone/Sitecore.Ship-PowerShell-Functions</a><br />
<br />
<br />
<br />
<br />
<b>Sitecore Package Deployer</b> from Hedgehog Development is a similar tool to Sitecore Ship. Instead of deploying packages sent by HTTP it deploys them from file system. More info you can find on TDS website: <a href="https://www.teamdevelopmentforsitecore.com/Blog/sitecore-package-deployer">https://www.teamdevelopmentforsitecore.com/Blog/sitecore-package-deployer</a>. Full codebase is available at GitHub: <a href="https://github.com/HedgehogDevelopment/SitecorePackageDeployer">https://github.com/HedgehogDevelopment/SitecorePackageDeployer</a> - you can find there installer also - built as .update package.<br />
<br />
<h4>
Data migration</h4>
Sometimes we need to transfer data between some Sitecore instances. It might be for update UAT environment with production content or maybe for Sitecore upgrade purposes, with approach of setting fresh new Sitecore instance.<br />
<br />
<div style="text-align: left;">
<a href="https://4.bp.blogspot.com/-ld_IZCHUrr8/WLQEWZctyuI/AAAAAAAABJA/oPJjoymD96M1Xr-nCIHm9ccdqU4-pE98wCLcB/s1600/RazlLogo.PNG" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" height="103" src="https://4.bp.blogspot.com/-ld_IZCHUrr8/WLQEWZctyuI/AAAAAAAABJA/oPJjoymD96M1Xr-nCIHm9ccdqU4-pE98wCLcB/s320/RazlLogo.PNG" width="320" /></a><b>RAZL</b> is another nice tool from Hedgehog Development. It's purpose is to add availability to compare databases of two Sitecore instances and look for differences. It also adds option to move and synchronize data between instances.<br />
<br />
<br />
<b>Content Migrator Sidekick App</b> by Jeff Darchuk is a tool for moving data between instances. It's core is <b>Rainbow </b>- serialization engine designed by Kam Figy for Unicorn. It needs a Sidekick installed first: <a href="https://jeffdarchuk.com/2016/10/03/sitecore-sidekick/">https://jeffdarchuk.com/2016/10/03/sitecore-sidekick/</a>. More info you can find at Jeff's blog: <a href="https://jeffdarchuk.com/2016/10/24/sitecore-sidekick-content-migrator/">https://jeffdarchuk.com/2016/10/24/sitecore-sidekick-content-migrator/</a>. </div>
<br />
<br />
<b>Coast for Sitecore</b> is a module that was designed to give an easy copy-paste functionality for moving items between Sitecore instances. Here is more info about that: <a href="https://www.geekhive.com/buzz/post/2016/11/introducing-coast-for-sitecore/">https://www.geekhive.com/buzz/post/2016/11/introducing-coast-for-sitecore/</a>. Now, there is a version 3.0: <a href="https://www.geekhive.com/buzz/post/2017/02/introducing-coast-for-sitecore-version-3-0/">https://www.geekhive.com/buzz/post/2017/02/introducing-coast-for-sitecore-version-3-0/</a>. You can find it on Sitecore Marketplace: <a href="https://marketplace.sitecore.net/en/Modules/S/Sitecore_Coast.aspx">https://marketplace.sitecore.net/en/Modules/S/Sitecore_Coast.aspx</a>.<br />
<br />
<h4>
Visual Studio plugins</h4>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://4.bp.blogspot.com/-np54tT0UVLA/WLbUc7oLxuI/AAAAAAAABJs/6UU_CP9ItRMIwEszlyt5CGmU0DJEJfXzwCLcB/s1600/Microsoft.VisualStudio.Services.Icons.Default.png" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" src="https://4.bp.blogspot.com/-np54tT0UVLA/WLbUc7oLxuI/AAAAAAAABJs/6UU_CP9ItRMIwEszlyt5CGmU0DJEJfXzwCLcB/s1600/Microsoft.VisualStudio.Services.Icons.Default.png" style="background: white; padding: 10px;" /></a></div>
<b> Sitecore Rocks</b> was designed to integrate whole Sitecore stuff with Visual Studio. You can connect with your instance, edit items and manage just like in the Content Editor. It can really increase developer productivity. Plugin is available here: <a href="https://marketplace.visualstudio.com/items?itemName=JakobChristensen.SitecoreRocks">https://marketplace.visualstudio.com/items?itemName=JakobChristensen.SitecoreRocks</a> and code on GitHub: <a href="https://github.com/JakobChristensen/Sitecore.Rocks">https://github.com/JakobChristensen/Sitecore.Rocks</a><br />
<br />
<h4>
Unit testing</h4>
<b>FakeDb </b>is a unit testing framework for Sitecore. It enables creating fake Sitecore database, so then it can be used in tests. It can be found on GitHub: <a href="https://github.com/sergeyshushlyapin/Sitecore.FakeDb">https://github.com/sergeyshushlyapin/Sitecore.FakeDb</a>. There is also a pretty nice documentation: <a href="https://github.com/sergeyshushlyapin/Sitecore.FakeDb/wiki">https://github.com/sergeyshushlyapin/Sitecore.FakeDb/wiki</a><br />
<br />
<br />
<b>AutoSitecore </b>is a bunch of AutoFixture customizations prepared to use new testability features in Sitecore 8.2. It was created by Dan Soloway and it is available here <a href="https://github.com/dsolovay/AutoSitecore">https://github.com/dsolovay/AutoSitecore</a><br />
<br />
<br />
<h4>
Solution architecture</h4>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://4.bp.blogspot.com/-xJswfoEhYtw/WLfvh8I0aII/AAAAAAAABK0/4PbdXrq-6Qgzh4e-jdoilSN8WMwWjPshgCLcB/s1600/helix-logo.png" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" height="94" src="https://4.bp.blogspot.com/-xJswfoEhYtw/WLfvh8I0aII/AAAAAAAABK0/4PbdXrq-6Qgzh4e-jdoilSN8WMwWjPshgCLcB/s200/helix-logo.png" width="200" /></a></div>
<b>Helix</b>, as the documentation says, is a set of overall design principles and conventions for Sitecore
development. You might heard of this from Habitat project, which was the introduction to that approach. Helix was prepared to structurize all of that principals. Full documentation is here: <a href="http://helix.sitecore.net/">http://helix.sitecore.net/</a>. Full code of Habitat is here: <a href="https://github.com/sitecore/habitat">https://github.com/sitecore/habitat</a>. <br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://2.bp.blogspot.com/-AIkuw_nHZRs/WLfv1uBSlYI/AAAAAAAABK4/jXxQFN2veIEHFyVxvhvZBJLt9KckIoSYACLcB/s1600/19982958.png" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" height="200" src="https://2.bp.blogspot.com/-AIkuw_nHZRs/WLfv1uBSlYI/AAAAAAAABK4/jXxQFN2veIEHFyVxvhvZBJLt9KckIoSYACLcB/s200/19982958.png" style="background: white; padding: 0px;" width="200" /></a></div>
<b>Ignition </b>- this is a development accelerator designed by team at Perficient. You can read more about that at Perficient website <a href="http://blogs.perficient.com/microsoft/2016/06/sitecore-developers-start-your-ignition/">http://blogs.perficient.com/microsoft/2016/06/sitecore-developers-start-your-ignition/</a>. Whole code is available on GitHub <a href="https://github.com/sitecoreignition/SitecoreIgnition">https://github.com/sitecoreignition/SitecoreIgnition</a>. Here is also quick start guide: <a href="https://www.youtube.com/watch?v=rtd1XkWFKhw">https://www.youtube.com/watch?v=rtd1XkWFKhw</a>.<br />
<br />
<br />
<br />
<br />
<br />
<br />
<h4>
Sitecore official modules</h4>
<b>Web Forms For Marketers (WFFM)</b><br />
Module that adds availability to create forms in Sitecore and use them to collect user information and store it for analytics purposes. Official documentation is here: <a href="https://doc.sitecore.net/web_forms_for_marketers/">https://doc.sitecore.net/web_forms_for_marketers/</a><br />
<br />
<b>Email Experience Manager (EXM)</b><br />
EXM is a module that enables creating e-mail campaigns. Official documentation: <a href="https://doc.sitecore.net/email_experience_manager">https://doc.sitecore.net/email_experience_manager</a><br />
<br />
<b>Federated Experience Manager (FXM)</b><br />
FXM module is used to integrate non-Sitecore sites with existing Sitecore instance. You can track user information and collect that to extend whole user profile in Sitecore. Official documentation: <a href="https://doc.sitecore.net/sitecore_experience_platform/digital_marketing/federated_experience_manager">https://doc.sitecore.net/sitecore_experience_platform/digital_marketing/federated_experience_manager</a><br />
<br />
<b>Sitecore Experience Accelerator (SXA) </b><br />
SXA provides reusable layouts and components for rapid website development. Official documentation: <a href="https://doc.sitecore.net/sitecore_experience_accelerator">https://doc.sitecore.net/sitecore_experience_accelerator</a> <br />
<br />
<h4>
Sitecore marketplace modules</h4>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://1.bp.blogspot.com/-3_tr3YfZu3E/WLfwrQwMkNI/AAAAAAAABLA/DzHF5zqwsco2QKcWlSchT0vAYphHKx98ACLcB/s1600/0.jpg" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" height="150" src="https://1.bp.blogspot.com/-3_tr3YfZu3E/WLfwrQwMkNI/AAAAAAAABLA/DzHF5zqwsco2QKcWlSchT0vAYphHKx98ACLcB/s200/0.jpg" width="200" /></a></div>
<b>Sitecore PowerShell Extensions</b> - this module gives you the power of PowerShell inside Sitecore. It is incredibly useful and fast for advanced usage. A lot of examples can be found on blog by Adam Najmanowicz: <a href="http://blog.najmanowicz.com/sitecore-powershell-console/">http://blog.najmanowicz.com/sitecore-powershell-console/.</a> You can download it from Sitecore Marketplace: <a href="https://marketplace.sitecore.net/en/Modules/Sitecore_PowerShell_console.aspx">https://marketplace.sitecore.net/en/Modules/Sitecore_PowerShell_console.aspx</a>.<br />
<br />
<br />
<br />
<h4>
Front-End development</h4>
<a href="https://2.bp.blogspot.com/-eEYLPMggffA/WLk25LV2sSI/AAAAAAAABLg/Tt6eh3xK8asaf-BOPBo70AXmDaNsh5MGwCLcB/s1600/feydra-logo.png" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" src="https://2.bp.blogspot.com/-eEYLPMggffA/WLk25LV2sSI/AAAAAAAABLg/Tt6eh3xK8asaf-BOPBo70AXmDaNsh5MGwCLcB/s1600/feydra-logo.png" style="background: white; padding: 15px;" /></a><b>Feydra</b> is another great tool from Hedgehog development. It gives front-end developers availability to work directly on virtualized Sitecore instance using their own tools. They can commit changes without intervention of back-end developers. More info about Feydra can be found here: <a href="http://www.teamdevelopmentforsitecore.com/Feydra">http://www.teamdevelopmentforsitecore.com/Feydra</a>.<br />
<br />
<br />
<h4>
Other stuff</h4>
<b>Dianoga </b>is a tool from Kam Figy that optimizes images for the media library. Full code is available here: <a href="https://github.com/kamsar/Dianoga">https://github.com/kamsar/Dianoga</a>.<br />
<br />
<b>Sitecore Instance Manager (SIM)</b> is a great app that will help you manage your Sitecore instances. You can rapidly install new fresh instance with just few clicks. That is really helpful while investigating if some bugs are present in clean Sitecore or just in your code. You can download it from Marketplace: <a href="https://marketplace.sitecore.net/en/Modules/Sitecore_Instance_Manager.aspx">https://marketplace.sitecore.net/en/Modules/Sitecore_Instance_Manager.aspx</a> and the code is available on GitHub: <a href="https://github.com/Sitecore/Sitecore-Instance-Manager">https://github.com/Sitecore/Sitecore-Instance-Manager</a><br />
<br />
<b>Sitecore Log Analyzer (SCLA)</b> is a tool for analyzing Sitecore logs. It is very handy in situation when you need to find some entries but logs are splitted. You can search by dates and entry types. You can download it from Marketplace: <a href="https://marketplace.sitecore.net/en/Modules/Sitecore_Log_Analyzer.aspx">https://marketplace.sitecore.net/en/Modules/Sitecore_Log_Analyzer.aspx</a><br />
<br />
<b>Sitecore Support Package Generator (SSPG)</b> was designed for helping developers collecting all crucial data needed to investigate problem by Sitecore Support. It is very useful - it can take all required Sitecore and IIS logs, pack it and send right to Support. It is available at Sitecore Marketplace: <a href="https://marketplace.sitecore.net/en/Modules/Sitecore_Support_Package_Generator.aspx">https://marketplace.sitecore.net/en/Modules/Sitecore_Support_Package_Generator.aspx</a><br />
<br />
<h4>
Summary </h4>
Off course this list is just a quick overview of available Sitecore tools, but I hope it will give you more information how efficiently develop Sitecore applications. Happy Sitecoring!<br />
<br />
<br />
<h3>
</h3>
Radoslaw Kozlowskihttp://www.blogger.com/profile/06810133427607221124noreply@blogger.com5Bialystok, Poland53.132488599999988 23.16884030000005652.980044599999985 22.846116800000058 53.284932599999991 23.491563800000055tag:blogger.com,1999:blog-4507372088071200408.post-72966753497184470452017-01-13T14:54:00.000+01:002017-01-13T14:54:54.218+01:00Razl scripting with PowerShellRazl, tool from Hedgehog Development, that was designed to transfer items between Sitecore instances and compare them, has some nice scripting features.<br />
<br />
I needed to use Razl scripting for Sitecore upgrade process. I created new fresh Sitecore instance (it was big jump, from 6.5 to 8.1) and started preparing what should be moved to new database. Old instance had a lot of datasource items and huge amount of media library items. Transfer all of this things was huge deal and was processing for over a dozen of hours. I decided to make some changes in my approach.<br />
<br />
<h3>
Preparation of Sitecore instances</h3>
I was using Razl 3.0.5. Unfortunately I had some problems with my solution that I couldn't connect with this tool to the Sitecore that had all of solution code deployed, so I've created a clean instance of version 6.5 and a clean version of 8.1. I've changed the connection strings of this two to the correct solution databases and I used this two clean instances just for transferring purposes - worked like a charm. You might not have exact problem, but this is how I went through that.<br />
<br />
<h3>
Preparing Razl script file</h3>
First you have to prepare the script file in the Razl. You can do it just like in general, by adding tasks to Task List:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://3.bp.blogspot.com/-oJrtE0EtnNA/WHi8p0xbOgI/AAAAAAAABHA/o2ODDDXywnwnESna7RzSTPWFNdpwE4obACLcB/s1600/Razl%2Bset%2Btasks.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="339" src="https://3.bp.blogspot.com/-oJrtE0EtnNA/WHi8p0xbOgI/AAAAAAAABHA/o2ODDDXywnwnESna7RzSTPWFNdpwE4obACLcB/s640/Razl%2Bset%2Btasks.PNG" width="640" /></a></div>
<br />
Then, instead of running transfer, you can click 'Export Tasks' button. You will be prompted to save the script file. Let's take a look into the one:<br />
<pre style="background: #1e1e1e; color: gainsboro; font-family: Consolas; font-size: 13;"><span style="color: grey;"><?</span><span style="color: #569cd6;">xml</span><span style="color: grey;"> </span><span style="color: #92caf4;">version</span><span style="color: grey;">=</span><span style="color: grey;">"</span><span style="color: #c8c8c8;">1.0</span><span style="color: grey;">"</span><span style="color: grey;"> </span><span style="color: #92caf4;">encoding</span><span style="color: grey;">=</span><span style="color: grey;">"</span><span style="color: #c8c8c8;">utf-8</span><span style="color: grey;">"</span><span style="color: grey;">?></span>
<span style="color: grey;"><</span><span style="color: #569cd6;">razl</span><span style="color: grey;">></span>
<span style="color: grey;"> <</span><span style="color: #569cd6;">connection</span><span style="color: grey;"> </span><span style="color: #92caf4;">name</span><span style="color: grey;">=</span><span style="color: grey;">"</span><span style="color: #c8c8c8;">SC65VanillaWithSW.Master</span><span style="color: grey;">"</span><span style="color: grey;"> </span><span style="color: #92caf4;">readOnly</span><span style="color: grey;">=</span><span style="color: grey;">"</span><span style="color: #c8c8c8;">false</span><span style="color: grey;">"</span><span style="color: grey;"> </span><span style="color: #92caf4;">install</span><span style="color: grey;">=</span><span style="color: grey;">"</span><span style="color: #c8c8c8;">true</span><span style="color: grey;">"</span><span style="color: grey;">></span>
<span style="color: grey;"> <</span><span style="color: #569cd6;">url</span><span style="color: grey;">></span><span style="color: #c8c8c8;">http://sc650vanilla/</span><span style="color: grey;"></</span><span style="color: #569cd6;">url</span><span style="color: grey;">></span>
<span style="color: grey;"> <</span><span style="color: #569cd6;">accessGuid</span><span style="color: grey;">></span><span style="color: #c8c8c8;">047c5600-e111-449c-9e2b-179b06f17190</span><span style="color: grey;"></</span><span style="color: #569cd6;">accessGuid</span><span style="color: grey;">></span>
<span style="color: grey;"> <</span><span style="color: #569cd6;">database</span><span style="color: grey;">></span><span style="color: #c8c8c8;">master</span><span style="color: grey;"></</span><span style="color: #569cd6;">database</span><span style="color: grey;">></span>
<span style="color: grey;"> <</span><span style="color: #569cd6;">path</span><span style="color: grey;">></span><span style="color: #c8c8c8;">C:\inetpub\wwwroot\sc650Vanilla\Website</span><span style="color: grey;"></</span><span style="color: #569cd6;">path</span><span style="color: grey;">></span>
<span style="color: grey;"> </</span><span style="color: #569cd6;">connection</span><span style="color: grey;">></span>
<span style="color: grey;"> <</span><span style="color: #569cd6;">connection</span><span style="color: grey;"> </span><span style="color: #92caf4;">name</span><span style="color: grey;">=</span><span style="color: grey;">"</span><span style="color: #c8c8c8;">SC81VanillaForSW.Master</span><span style="color: grey;">"</span><span style="color: grey;"> </span><span style="color: #92caf4;">readOnly</span><span style="color: grey;">=</span><span style="color: grey;">"</span><span style="color: #c8c8c8;">false</span><span style="color: grey;">"</span><span style="color: grey;"> </span><span style="color: #92caf4;">install</span><span style="color: grey;">=</span><span style="color: grey;">"</span><span style="color: #c8c8c8;">true</span><span style="color: grey;">"</span><span style="color: grey;">></span>
<span style="color: grey;"> <</span><span style="color: #569cd6;">url</span><span style="color: grey;">></span><span style="color: #c8c8c8;">http://sc81u2vanillaforconnection/</span><span style="color: grey;"></</span><span style="color: #569cd6;">url</span><span style="color: grey;">></span>
<span style="color: grey;"> <</span><span style="color: #569cd6;">accessGuid</span><span style="color: grey;">></span><span style="color: #c8c8c8;">8db29355-a8d4-4102-969a-537cc8c54f30</span><span style="color: grey;"></</span><span style="color: #569cd6;">accessGuid</span><span style="color: grey;">></span>
<span style="color: grey;"> <</span><span style="color: #569cd6;">database</span><span style="color: grey;">></span><span style="color: #c8c8c8;">master</span><span style="color: grey;"></</span><span style="color: #569cd6;">database</span><span style="color: grey;">></span>
<span style="color: grey;"> <</span><span style="color: #569cd6;">path</span><span style="color: grey;">></span><span style="color: #c8c8c8;">C:\inetpub\wwwroot\sc81u2vanillaforconnection\Website</span><span style="color: grey;"></</span><span style="color: #569cd6;">path</span><span style="color: grey;">></span>
<span style="color: grey;"> </</span><span style="color: #569cd6;">connection</span><span style="color: grey;">></span>
<span style="color: grey;"> <</span><span style="color: #569cd6;">operation</span><span style="color: grey;"> </span><span style="color: #92caf4;">name</span><span style="color: grey;">=</span><span style="color: grey;">"</span><span style="color: #c8c8c8;">CopyAll</span><span style="color: grey;">"</span><span style="color: grey;"> </span><span style="color: #92caf4;">source</span><span style="color: grey;">=</span><span style="color: grey;">"</span><span style="color: #c8c8c8;">SC65VanillaWithSW.Master</span><span style="color: grey;">"</span><span style="color: grey;"> </span><span style="color: #92caf4;">target</span><span style="color: grey;">=</span><span style="color: grey;">"</span><span style="color: #c8c8c8;">SC81VanillaForSW.Master</span><span style="color: grey;">"</span><span style="color: grey;">></span>
<span style="color: grey;"> <!--</span><span style="color: #57a64a;">Copy with overwrite '/sitecore/templates/SW', all missing parents and all child items from 'SC65VanillaWithSW.Master' to 'SC81VanillaForSW.Master'</span><span style="color: grey;">--></span>
<span style="color: grey;"> <</span><span style="color: #569cd6;">parameter</span><span style="color: grey;"> </span><span style="color: #92caf4;">name</span><span style="color: grey;">=</span><span style="color: grey;">"</span><span style="color: #c8c8c8;">itemId</span><span style="color: grey;">"</span><span style="color: grey;">></span><span style="color: #c8c8c8;">b80ae69f-4212-43e6-af97-2f86ddcddae1</span><span style="color: grey;"></</span><span style="color: #569cd6;">parameter</span><span style="color: grey;">></span>
<span style="color: grey;"> <</span><span style="color: #569cd6;">parameter</span><span style="color: grey;"> </span><span style="color: #92caf4;">name</span><span style="color: grey;">=</span><span style="color: grey;">"</span><span style="color: #c8c8c8;">overwrite</span><span style="color: grey;">"</span><span style="color: grey;">></span><span style="color: #c8c8c8;">True</span><span style="color: grey;"></</span><span style="color: #569cd6;">parameter</span><span style="color: grey;">></span>
<span style="color: grey;"> <</span><span style="color: #569cd6;">parameter</span><span style="color: grey;"> </span><span style="color: #92caf4;">name</span><span style="color: grey;">=</span><span style="color: grey;">"</span><span style="color: #c8c8c8;">lightningMode</span><span style="color: grey;">"</span><span style="color: grey;">></span><span style="color: #c8c8c8;">False</span><span style="color: grey;"></</span><span style="color: #569cd6;">parameter</span><span style="color: grey;">></span>
<span style="color: grey;"> </</span><span style="color: #569cd6;">operation</span><span style="color: grey;">></span>
<span style="color: grey;"> <</span><span style="color: #569cd6;">operation</span><span style="color: grey;"> </span><span style="color: #92caf4;">name</span><span style="color: grey;">=</span><span style="color: grey;">"</span><span style="color: #c8c8c8;">CopyAll</span><span style="color: grey;">"</span><span style="color: grey;"> </span><span style="color: #92caf4;">source</span><span style="color: grey;">=</span><span style="color: grey;">"</span><span style="color: #c8c8c8;">SC65VanillaWithSW.Master</span><span style="color: grey;">"</span><span style="color: grey;"> </span><span style="color: #92caf4;">target</span><span style="color: grey;">=</span><span style="color: grey;">"</span><span style="color: #c8c8c8;">SC81VanillaForSW.Master</span><span style="color: grey;">"</span><span style="color: grey;">></span>
<span style="color: grey;"> <!--</span><span style="color: #57a64a;">Copy with overwrite '/sitecore/templates/User Defined', all missing parents and all child items from 'SC65VanillaWithSW.Master' to 'SC81VanillaForSW.Master'</span><span style="color: grey;">--></span>
<span style="color: grey;"> <</span><span style="color: #569cd6;">parameter</span><span style="color: grey;"> </span><span style="color: #92caf4;">name</span><span style="color: grey;">=</span><span style="color: grey;">"</span><span style="color: #c8c8c8;">itemId</span><span style="color: grey;">"</span><span style="color: grey;">></span><span style="color: #c8c8c8;">b29ee504-861c-492f-95a3-0d890b6fca09</span><span style="color: grey;"></</span><span style="color: #569cd6;">parameter</span><span style="color: grey;">></span>
<span style="color: grey;"> <</span><span style="color: #569cd6;">parameter</span><span style="color: grey;"> </span><span style="color: #92caf4;">name</span><span style="color: grey;">=</span><span style="color: grey;">"</span><span style="color: #c8c8c8;">overwrite</span><span style="color: grey;">"</span><span style="color: grey;">></span><span style="color: #c8c8c8;">True</span><span style="color: grey;"></</span><span style="color: #569cd6;">parameter</span><span style="color: grey;">></span>
<span style="color: grey;"> <</span><span style="color: #569cd6;">parameter</span><span style="color: grey;"> </span><span style="color: #92caf4;">name</span><span style="color: grey;">=</span><span style="color: grey;">"</span><span style="color: #c8c8c8;">lightningMode</span><span style="color: grey;">"</span><span style="color: grey;">></span><span style="color: #c8c8c8;">False</span><span style="color: grey;"></</span><span style="color: #569cd6;">parameter</span><span style="color: grey;">></span>
<span style="color: grey;"> </</span><span style="color: #569cd6;">operation</span><span style="color: grey;">></span>
<span style="color: grey;"> <</span><span style="color: #569cd6;">operation</span><span style="color: grey;"> </span><span style="color: #92caf4;">name</span><span style="color: grey;">=</span><span style="color: grey;">"</span><span style="color: #c8c8c8;">CopyAll</span><span style="color: grey;">"</span><span style="color: grey;"> </span><span style="color: #92caf4;">source</span><span style="color: grey;">=</span><span style="color: grey;">"</span><span style="color: #c8c8c8;">SC65VanillaWithSW.Master</span><span style="color: grey;">"</span><span style="color: grey;"> </span><span style="color: #92caf4;">target</span><span style="color: grey;">=</span><span style="color: grey;">"</span><span style="color: #c8c8c8;">SC81VanillaForSW.Master</span><span style="color: grey;">"</span><span style="color: grey;">></span>
<span style="color: grey;"> <!--</span><span style="color: #57a64a;">Copy with overwrite '/sitecore/layout/Layouts/SW', all missing parents and all child items from 'SC65VanillaWithSW.Master' to 'SC81VanillaForSW.Master'</span><span style="color: grey;">--></span>
<span style="color: grey;"> <</span><span style="color: #569cd6;">parameter</span><span style="color: grey;"> </span><span style="color: #92caf4;">name</span><span style="color: grey;">=</span><span style="color: grey;">"</span><span style="color: #c8c8c8;">itemId</span><span style="color: grey;">"</span><span style="color: grey;">></span><span style="color: #c8c8c8;">2141e479-3f72-447c-9afa-3b4db1ea283d</span><span style="color: grey;"></</span><span style="color: #569cd6;">parameter</span><span style="color: grey;">></span>
<span style="color: grey;"> <</span><span style="color: #569cd6;">parameter</span><span style="color: grey;"> </span><span style="color: #92caf4;">name</span><span style="color: grey;">=</span><span style="color: grey;">"</span><span style="color: #c8c8c8;">overwrite</span><span style="color: grey;">"</span><span style="color: grey;">></span><span style="color: #c8c8c8;">True</span><span style="color: grey;"></</span><span style="color: #569cd6;">parameter</span><span style="color: grey;">></span>
<span style="color: grey;"> <</span><span style="color: #569cd6;">parameter</span><span style="color: grey;"> </span><span style="color: #92caf4;">name</span><span style="color: grey;">=</span><span style="color: grey;">"</span><span style="color: #c8c8c8;">lightningMode</span><span style="color: grey;">"</span><span style="color: grey;">></span><span style="color: #c8c8c8;">False</span><span style="color: grey;"></</span><span style="color: #569cd6;">parameter</span><span style="color: grey;">></span>
<span style="color: grey;"> </</span><span style="color: #569cd6;">operation</span><span style="color: grey;">></span>
<span style="color: grey;"></</span><span style="color: #569cd6;">razl</span><span style="color: grey;">></span></pre>
<br />
It has a two connections for the instances which will be used in transfer. It comes from the Razl configuration, where firstly I created that connections. Under that elements there is a list of operations with specified source instance, target instance, ID of the item and configuration of the operation type - in my case it will be CopyAll with overwriting the target instance.<br />
<br />
As far as I knew at that time, there was no way to edit exported script with Razl, so I was editing it manually.<br />
<br />
<h3>
Preparing PowerShell run script</h3>
At last I wanted to have a PowerShell script that will run my transfer script with just one click. I have prepared a PSs that run razl.exe with specified scripts. For core database this is quite simple - set your directory where Razl script are located in:<br />
<br />
<script src="https://gist.github.com/ReoKzK/4bb7b72a99801d74163b771fb54b6b18.js"></script>
<br />
For master database I decided to split Razl script into smaller parts, so the I was able to comment out some of them to run just specific ones:<br />
<br />
<script src="https://gist.github.com/ReoKzK/08b3e1b9d2c1e11e4fe0e62248fba051.js"></script>
<br />
Also these scripts log full log into specific files. So everything that happens while transfer is saved for analysis. Here is some example part of the log:<br />
<br />
<blockquote class="tr_bq">
<span style="font-size: small;"> 1 13:00:31,579 INFO CopyAll Started Id: 563a2ddb-ad89-4182-9706-eb1512abe0b1, Path: /sitecore/system/Field types/List Types/Google Maps Multilist, From: SC65VanillaWithSW.Core, To: SC81VanillaForSW.Core, Overwrite: True<br /> 1 13:00:31,579 INFO CopyAll Processing /sitecore/system/Field types/List Types/Google Maps Multilist<br /> 1 13:00:31,580 INFO CopyItem Started Id: 563a2ddb-ad89-4182-9706-eb1512abe0b1, Path: /sitecore/system/Field types/List Types/Google Maps Multilist, From: SC65VanillaWithSW.Core, To: SC81VanillaForSW.Core<br /> 1 13:00:31,847 INFO CopyItem Finish Id: 563a2ddb-ad89-4182-9706-eb1512abe0b1, Path: /sitecore/system/Field types/List Types/Google Maps Multilist, From: SC65VanillaWithSW.Core, To: SC81VanillaForSW.Core<br /> 1 13:00:31,928 INFO CopyAll processing children of /sitecore/system/Field types/List Types/Google Maps Multilist<br /> 1 13:00:31,928 INFO CopyAll Processing /sitecore/system/Field types/List Types/Google Maps Multilist/Menu<br /> 1 13:00:31,929 INFO CopyItem Started Id: 60daf681-8069-46a2-aa39-5490741f6cec, Path: /sitecore/system/Field types/List Types/Google Maps Multilist/Menu, From: SC65VanillaWithSW.Core, To: SC81VanillaForSW.Core<br /> 1 13:00:32,196 INFO CopyItem Finish Id: 60daf681-8069-46a2-aa39-5490741f6cec, Path: /sitecore/system/Field types/List Types/Google Maps Multilist/Menu, From: SC65VanillaWithSW.Core, To: SC81VanillaForSW.Core<br /> 1 13:00:32,252 INFO CopyAll processing children of /sitecore/system/Field types/List Types/Google Maps Multilist/Menu<br /> 1 13:00:32,252 INFO CopyAll Processing /sitecore/system/Field types/List Types/Google Maps Multilist/Menu/Show Map<br /> 1 13:00:32,252 INFO CopyItem Started Id: ce073686-11cb-4921-b4db-61c98bc1f54a, Path: /sitecore/system/Field types/List Types/Google Maps Multilist/Menu/Show Map, From: SC65VanillaWithSW.Core, To: SC81VanillaForSW.Core<br /> 1 13:00:32,519 INFO CopyItem Finish Id: ce073686-11cb-4921-b4db-61c98bc1f54a, Path: /sitecore/system/Field types/List Types/Google Maps Multilist/Menu/Show Map, From: SC65VanillaWithSW.Core, To: SC81VanillaForSW.Core<br /> 1 13:00:32,576 INFO CopyAll processing children of /sitecore/system/Field types/List Types/Google Maps Multilist/Menu/Show Map<br /> 1 13:00:32,576 INFO CopyAll Processing /sitecore/system/Field types/List Types/Google Maps Multilist/Menu/Select All<br /> 1 13:00:32,577 INFO CopyItem Started Id: bbe0cd71-aac7-47bc-971a-49265078d17c, Path: /sitecore/system/Field types/List Types/Google Maps Multilist/Menu/Select All, From: SC65VanillaWithSW.Core, To: SC81VanillaForSW.Core<br /> 1 13:00:33,153 INFO CopyItem Finish Id: bbe0cd71-aac7-47bc-971a-49265078d17c, Path: /sitecore/system/Field types/List Types/Google Maps Multilist/Menu/Select All, From: SC65VanillaWithSW.Core, To: SC81VanillaForSW.Core<br /> 1 13:00:33,209 INFO CopyAll processing children of /sitecore/system/Field types/List Types/Google Maps Multilist/Menu/Select All<br /> 1 13:00:33,209 INFO CopyAll Processing /sitecore/system/Field types/List Types/Google Maps Multilist/Menu/Deselect All<br /> 1 13:00:33,209 INFO CopyItem Started Id: b54acbc5-0fc0-4d6d-a863-0f8657e50504, Path: /sitecore/system/Field types/List Types/Google Maps Multilist/Menu/Deselect All, From: SC65VanillaWithSW.Core, To: SC81VanillaForSW.Core<br /> 1 13:00:38,480 INFO CopyItem Finish Id: b54acbc5-0fc0-4d6d-a863-0f8657e50504, Path: /sitecore/system/Field types/List Types/Google Maps Multilist/Menu/Deselect All, From: SC65VanillaWithSW.Core, To: SC81VanillaForSW.Core<br /> 1 13:00:38,537 INFO CopyAll processing children of /sitecore/system/Field types/List Types/Google Maps Multilist/Menu/Deselect All<br /> 1 13:00:38,593 INFO CopyAll Finish Id: 563a2ddb-ad89-4182-9706-eb1512abe0b1, Path: /sitecore/system/Field types/List Types/Google Maps Multilist, From: SC65VanillaWithSW.Core, To: SC81VanillaForSW.Core, Overwrite: True<br /> 1 13:00:38,705 INFO CopyAll Started Id: 5cee31bf-120d-4936-b9c6-930cbf63cb57, Path: /sitecore/system/Field types/Simple Types/Google Maps Single Point, From: SC65VanillaWithSW.Core, To: SC81VanillaForSW.Core, Overwrite: True</span></blockquote>
<br />
More info about Razl scripting is in official Razl documentation: <a href="https://hedgehogdevelopment.github.io/razl/script.html">https://hedgehogdevelopment.github.io/razl/script.html</a>.<br />
<br />Radoslaw Kozlowskihttp://www.blogger.com/profile/06810133427607221124noreply@blogger.com0Bialystok, Poland53.132488599999988 23.16884030000005652.980044599999985 22.846116800000058 53.284932599999991 23.491563800000055tag:blogger.com,1999:blog-4507372088071200408.post-12213566929003100572017-01-10T10:35:00.001+01:002017-02-17T15:42:59.268+01:00Sitecore Module - Dynamic Sitemap XMLAfter a lot of work spent on creating project specific sitemap xml implementations I have prepared my own generic sitemap xml module. It is based on original marketplace sitemap module but adds some new great features.<br />
<br />
<br />
It has two main assumptions:<ul>
<li>Flexible configuration - to give end user as many as possible configuration options, because it is easier to edit Sitecore items than edit and deploy config files.</li>
</ul>
<ul>
<li>Extensibility - code functionality should be extensible and override-able. It should be easy to extend or override functionality, without decompiling and copy-pasting a lot of code.</li>
</ul>
<br />
<h4>
Specifying your own logic</h4>
To use or not to use marketplace module - that is the question! Most times main reason to write your own sitemap implementation is thought if there will be some custom tricky functionalities needed. Something like some static html pages or other links that exist outside Sitecore.<br />
<br />
<br />
You can specify your own logic, that can add your custom items to the sitemap. <br />
<br />
You should create class that implements <span style="font-family: "courier new" , "courier" , monospace;">IItemsProcessor</span> interface, put it in your assembly and attach your class to the site configuration item, in format <span style="font-family: "courier new" , "courier" , monospace;">MyType, MyAssembly</span>.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://1.bp.blogspot.com/-2hFvt2DrSFw/WHSmV72qMJI/AAAAAAAABFw/C6PLi0wCP3MXHQnTMNEiBemt6kCUqfUeACLcB/s1600/AdditionalLogic.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="70" src="https://1.bp.blogspot.com/-2hFvt2DrSFw/WHSmV72qMJI/AAAAAAAABFw/C6PLi0wCP3MXHQnTMNEiBemt6kCUqfUeACLcB/s640/AdditionalLogic.png" width="640" /></a></div>
<br />
In this approach, main functionality of module can be easily changed. More info here <a href="https://github.com/ReoKzK/Sitecore.SharedSource.DynamicSitemap/wiki/Specifying-your-own-logic">https://github.com/ReoKzK/Sitecore.SharedSource.DynamicSitemap/wiki/Specifying-your-own-logic</a><br />
<br />
<h4>
Separation from content</h4>
I also decided to definitely separate sitemap things from the actual content. So deciding whether the item goes to sitemap or nor or setting the change frequency or priority, is set on the sitemap configuration item in Sitecore. This approach will keep your items clean. More info here <a href="https://github.com/ReoKzK/Sitecore.SharedSource.DynamicSitemap/wiki/Creating-new-sitemap-configuration">https://github.com/ReoKzK/Sitecore.SharedSource.DynamicSitemap/wiki/Creating-new-sitemap-configuration</a><br />
<br />
<h4>
That's all :)</h4>
Module is uploaded to official Sitecore Marketplace <a href="https://marketplace.sitecore.net/Modules/D/Dynamic_Sitemap_XML_Module.aspx">https://marketplace.sitecore.net/Modules/D/Dynamic_Sitemap_XML_Module.aspx</a><br />
<br />
Whole documentation is available here <a href="https://github.com/ReoKzK/Sitecore.SharedSource.DynamicSitemap/wiki">https://github.com/ReoKzK/Sitecore.SharedSource.DynamicSitemap/wiki</a><br />
<br />
Library is also available at nuget:<br />
<blockquote class="tr_bq">
<code>Install-Package Sitecore.SharedSource.DynamicSitemap</code></blockquote>
Hope that my module will be useful and will improve your websites development process.Radoslaw Kozlowskihttp://www.blogger.com/profile/06810133427607221124noreply@blogger.com0Białystok, Polska53.132488599999988 23.16884030000005652.980044599999985 22.846116800000058 53.284932599999991 23.491563800000055tag:blogger.com,1999:blog-4507372088071200408.post-33183328778360979402016-12-06T18:46:00.000+01:002016-12-06T18:46:07.187+01:00Language Fallback on Final LayoutLast time I was struggling with translating items to different languages. I was using the ClayTablet Sitecore Translation Connector module - it basically sends the content to translator, waits till it will be returned, receives the translated content and creates new version in desired language. Sitecore was in Initial Release of 8.1.<br />
<br />
Then I realized, that new versions of items in other languages had missing value in Final Renderings field. Unfortunately solution which I was working on, was using this field widely from the beginning - by the Experience Editor. I tried to set the Language Fallback on that field but in vain.<br />
<br />
I have successfully reproduced this behaviour on clean instance of 8.1 Initial Release. I have enabled Language Fallback:<br />
<br />
<blockquote class="tr_bq">
<sites><br /> <site name="shell"><br /> <patch:attribute name="enableItemLanguageFallback"><b>true</b></patch:attribute><br /> <patch:attribute name="enableFieldLanguageFallback"><b>true</b></patch:attribute><br /> </site><br /> <site name="website"><br /> <patch:attribute name="enableItemLanguageFallback"><b>true</b></patch:attribute><br /> <patch:attribute name="enableFieldLanguageFallback"><b>true</b></patch:attribute><br /> </site><br /> </sites></blockquote>
<br />
Also I have set the fallback path in the language item:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://1.bp.blogspot.com/-lpTbIp3urlk/WEb3pn_DexI/AAAAAAAABEo/kJwKcw_CcFYpVvaSkPzXuyleRNmcATwuACLcB/s1600/Language%2Bfallback.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://1.bp.blogspot.com/-lpTbIp3urlk/WEb3pn_DexI/AAAAAAAABEo/kJwKcw_CcFYpVvaSkPzXuyleRNmcATwuACLcB/s1600/Language%2Bfallback.PNG" /></a></div>
<br />
After that I have added new rendering from Experience Editor:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://1.bp.blogspot.com/-yLJAPxBUPDY/WEb4F3nG4AI/AAAAAAAABEs/ckHaaX2Nu4Yy_rVKmJ8wDm2_YFsUKC9GgCLcB/s1600/1.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="120" src="https://1.bp.blogspot.com/-yLJAPxBUPDY/WEb4F3nG4AI/AAAAAAAABEs/ckHaaX2Nu4Yy_rVKmJ8wDm2_YFsUKC9GgCLcB/s640/1.PNG" width="640" /></a></div>
<br />
Unfortunately, I wasn't able to fallback this field from the base language. I have sent my problem to Sitecore Support and they confirmed, that this feature is missing. Sadly I had nothing more to do but manually set these renderings or use a PowerShell to automate it. Fortunately this bug reported by me was labelled as feature request and now it is present on version 8.2 Update-1!<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://1.bp.blogspot.com/-jSjDa8_OII8/WEVht1UiTkI/AAAAAAAABD8/JjuBO2ywNuMwM3TxGRDYYXwHMY4JfUKPACLcB/s1600/i201%255Ecimgpsh_orig.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="260" src="https://1.bp.blogspot.com/-jSjDa8_OII8/WEVht1UiTkI/AAAAAAAABD8/JjuBO2ywNuMwM3TxGRDYYXwHMY4JfUKPACLcB/s640/i201%255Ecimgpsh_orig.jpg" width="640" /></a></div>
<br />
The public reference number was set to 105306.<br />
<br />
I have downloaded the package and started to testing it out. Fresh instance was set up by the SIM.<br />
I went to the Final Renderings field:<br />
<br />
<blockquote class="tr_bq">
/sitecore/templates/System/Templates/Sections/Layout/Layout/__Final Renderings</blockquote>
<br />
And I have enabled field level fallback:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://4.bp.blogspot.com/-47CeU2wOm64/WEb1EtzwQgI/AAAAAAAABEU/zWQFNgnSep82fPT0uDvMCdNBkGq91afygCLcB/s1600/Enable%2Bfield%2Blevel%2Bfallback.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="122" src="https://4.bp.blogspot.com/-47CeU2wOm64/WEb1EtzwQgI/AAAAAAAABEU/zWQFNgnSep82fPT0uDvMCdNBkGq91afygCLcB/s640/Enable%2Bfield%2Blevel%2Bfallback.PNG" width="640" /></a></div>
<br />
Everything works ok now - additional "Sample rendering" added from Experience Editor is present now on other languages that have Fallback set:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://1.bp.blogspot.com/-tFhJSfClY6s/WEb1UHGrMtI/AAAAAAAABEY/pqB--spIeBshNS2PtBECLvv7mFl0NSZKwCLcB/s1600/Fallback%2Bvalue.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="134" src="https://1.bp.blogspot.com/-tFhJSfClY6s/WEb1UHGrMtI/AAAAAAAABEY/pqB--spIeBshNS2PtBECLvv7mFl0NSZKwCLcB/s640/Fallback%2Bvalue.PNG" width="640" /></a></div>
<br />
<br />
Also, the Update-1 comes with really great features like wide Azure support. You should definitely check this out! <br />
<br />
<br />Radoslaw Kozlowskihttp://www.blogger.com/profile/06810133427607221124noreply@blogger.com0Bialystok, Poland53.132488599999988 23.16884030000005652.980044599999985 22.846116800000058 53.284932599999991 23.491563800000055tag:blogger.com,1999:blog-4507372088071200408.post-41203524180498765282016-09-08T10:06:00.000+02:002016-12-06T19:09:51.553+01:00Error while using WFFM save action Send Email Campaign MessageLast time while I was playing with EXM and WFFM I have experienced strange issue. I am using Sitecore 8.1 Update-2, EXM 3.2.1 and WFFM 8.1 Update-2. I have added <b>Send Email Campaign Message</b> Save Action to my form, set up message and destination e-mail.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://4.bp.blogspot.com/-em-e8PbKS1E/V6CEA5ky8GI/AAAAAAAAA_s/3IyBzGFeYrMZY3BBKqP6XzHTqz72ZjkDQCLcB/s1600/Save.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://4.bp.blogspot.com/-em-e8PbKS1E/V6CEA5ky8GI/AAAAAAAAA_s/3IyBzGFeYrMZY3BBKqP6XzHTqz72ZjkDQCLcB/s1600/Save.PNG" /></a></div>
<br />
<br />
After form submit I got an error: <br />
<br />
<blockquote class="tr_bq">
5276 15:43:58 INFO AUDIT (extranet\Anonymous): [WFFM] Form {B9C58542-7A02-4191-94B1-186C87EC74D9} is saving to db
5276 15:43:58 WARN [WFFM] Object reference not set to an instance of an object.
Exception: System.NullReferenceException
Message: Object reference not set to an instance of an object.
Source: Sitecore.Forms.Custom
at Sitecore.Form.Submit.SendStandardMessage.Send(AdaptedResultList fields)
at Sitecore.Forms.Core.Dependencies.DefaultImplActionExecutor.ExecuteSaving(ID formID, ControlResult[] fields, IActionDefinition[] actionDefinitions, Boolean simpleAdapt, ID sessionID)
5276 15:43:58 WARN [WFFM] The 'Send Email Campaign Message[id={EB59E095-5B61-4C04-8286-9469DAFD9A13}]' save action failed: We experienced a technical difficulty while processing your request. Your data may not have been correctly saved.
5276 15:43:58 WARN [WFFM] Web Forms for Marketers: an exception: We experienced a technical difficulty while processing your request. Your data may not have been correctly saved. has occured while trying to execute an action. </blockquote>
<br />
NullReferenceException was rather strange for me, so I started deep investigation. I have decompiled some WFFM and EXM classes and I found the problem. Some missing checks caused that issue.<br />
<br />
The main cause of that situation is the EXM Message is being in state other than Active. Sitecore Support provided me with package, that solves this glitch.<br />
<br />
Public reference number is 120449.<br />
<br />
<div id="aui-3-5-1-4_7102">
To resolve the issue, I had to:</div>
<ol id="aui-3-5-1-4_7105">
<li id="aui-3-5-1-4_7104">Put the Sitecore.Support.120449.dll into bin folder</li>
<li id="aui-3-5-1-4_7107">Navigate to the /sitecore/system/Modules/Web
Forms for Marketers/Settings/Actions/Save Actions/Send Email Campaign
Message item and perform the following changes with its fields:</li>
</ol>
<ul id="aui-3-5-1-4_7093">
<li id="aui-3-5-1-4_7092" style="margin-left: 40px;">Assembly -> Sitecore.Support.120449</li>
<li id="aui-3-5-1-4_7109" style="margin-left: 40px;">Class -> Sitecore.Support.Form.Submit.SendStandardMessage</li>
</ul>
<div id="aui-3-5-1-4_7090">
3. Publish the changes</div>
<br />
After that it worked for me. Hope that post will be helpful :) Radoslaw Kozlowskihttp://www.blogger.com/profile/06810133427607221124noreply@blogger.com0Białystok, Polska53.132488599999988 23.16884030000005652.980044599999985 22.846116800000058 53.284932599999991 23.491563800000055tag:blogger.com,1999:blog-4507372088071200408.post-66804602292571611982016-06-25T22:00:00.003+02:002018-11-24T20:25:56.219+01:00Error in event item:saved when migrating old WFFM items by Razl<div class="tr_bq">
Last time when I was upgrading another website from version 6.5 to 8.1, I have faced the problem with WFFM forms. I was transferring all content from old database to new one, using Razl. Almost everything went OK, but WFFM Form items.</div>
<br />
The error I got, was rather misterious:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://2.bp.blogspot.com/-orcmml255h0/V20IbvdJreI/AAAAAAAAA8Y/6nijK9TEUg08FzCHlacasahW3y7LafJjACLcB/s1600/itemSaved.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://2.bp.blogspot.com/-orcmml255h0/V20IbvdJreI/AAAAAAAAA8Y/6nijK9TEUg08FzCHlacasahW3y7LafJjACLcB/s1600/itemSaved.PNG" /></a></div>
<br />
<br />
<pre>18684 11:12:39 ERROR One or more exceptions occurred while processing the subscribers to the 'item:saved' event.
Exception[1]: System.FormatException
Message[1]: Unrecognized Guid format.
Source[1]: mscorlib
at System.Guid.GuidResult.SetFailure(ParseFailureKind failure, String failureMessageID, Object failureMessageFormatArgument, String failureArgumentName, Exception innerException)
at System.Guid.TryParseGuid(String g, GuidStyles flags, GuidResult& result)
at System.Guid..ctor(String g)
at Sitecore.Analytics.Data.TrackingField.<>c__DisplayClass21.<get_Events>b__20(XElement e)
at System.Linq.Enumerable.WhereSelectEnumerableIterator`2.MoveNext()
at Sitecore.Analytics.Data.TrackingField.ValidateLinks(LinksValidationResult result)
at Sitecore.Links.ItemLinks.AddLinks(Field field, List`1 links, ItemLinkState linkState)
at Sitecore.Links.ItemLinks.GetLinks(ItemLinkState linkState, Boolean allVersions, Boolean includeStandardValuesLinks)
at Sitecore.Links.SqlLinkDatabase.UpdateItemVersionReferences(Item item)
at Sitecore.Links.ItemEventHandler.OnItemSaved(Object sender, EventArgs args)
at Sitecore.Events.Event.EventSubscribers.RaiseEvent(String eventName, Object[] parameters, EventResult result)
18684 11:12:39 ERROR Razl service error
Exception: System.AggregateException
Message: One or more exceptions occurred while processing the subscribers to the 'item:saved' event.
Source: Sitecore.Kernel
at Sitecore.Events.Event.EventSubscribers.RaiseEvent(String eventName, Object[] parameters, EventResult result)
at Sitecore.Events.Event.RaiseEvent(String eventName, Object[] parameters)
at Sitecore.Events.Event.RaiseItemSaved(Object sender, ItemSavedEventArgs args)
at System.EventHandler`1.Invoke(Object sender, TEventArgs e)
at Sitecore.Data.Engines.EngineCommand`2.RaiseEvent[TArgs](EventHandler`1 handlers, Func`2 argsCreator)
at Sitecore.Data.Engines.EngineCommand`2.Execute()
at Sitecore.Data.Engines.DataEngine.SaveItem(Item item)
at Sitecore.Data.Managers.ItemProvider.SaveItem(Item item)
at Sitecore.Data.Managers.PipelineBasedItemProvider.ExecuteAndReturnResult[TArgs,TResult](String pipelineName, String pipelineDomain, Func`1 pipelineArgsCreator, Func`1 fallbackResult)
at Sitecore.Data.Managers.PipelineBasedItemProvider.SaveItem(Item item)
at Sitecore.Data.Items.ItemEditing.AcceptChanges(Boolean updateStatistics, Boolean silent)
at Sitecore.Data.Items.EditContext.Dispose()
at HedgehogDevelopment.Razl.Service.RazlService.SetItemDetails(Guid accessGuid, String database, Guid itemId, ItemDetails itemDetails)</pre>
<br />
It was really confusing for me. Later, I realized that it was caused by value of field <i>Tracking </i>in <i>Personalization </i>section. In my old database the value was:<br />
<br />
<pre><tracking>
<event name="Field Changed" />
<event name="Field Completed" />
<event name="Field Not Completed" />
<event name="Field Out of Boundary" />
<event name="Invalid Field Syntax" />
</tracking></pre>
<br />
In new version those events need an id parameter, not only name.<br />
<br />
I decided to prepare that items by hand and put them in Sitecore package. I really wanted to make it all automated, but on the other hand, that solution wasn't really bad.<br />
<br />
So I prepared that field in a way like this (<i>Tracking </i>field in 8.1 is in <i>Advanced </i>section):<br />
<br />
<pre><tracking>
<event id="{AA3AE715-E87D-4B4D-80C7-4290546F770F}" name="Field changed" />
<event id="{F0113A93-570A-4F69-8C7C-BA08037D1E34}" name="Field Completed" />
<event id="{7E86B2F5-ACEC-4C60-8922-4EB5AE5D9874}" name="Field Not Completed" />
<event id="{F3D7B20C-675C-4707-84CC-5E5B4481B0EE}" name="Field Out of Boundary" />
<event id="{844BBD40-91F6-42CE-8823-5EA4D089ECA2}" name="Invalid Field Syntax" />
</tracking></pre>
<br />
And it works :)<br />
<br />
<br />Radoslaw Kozlowskihttp://www.blogger.com/profile/06810133427607221124noreply@blogger.com0Białystok, Polska53.132488599999988 23.16884030000005652.980044599999985 22.846116800000058 53.284932599999991 23.491563800000055