<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:blogger='http://schemas.google.com/blogger/2008' xmlns:georss='http://www.georss.org/georss' xmlns:gd="http://schemas.google.com/g/2005" xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-6112035634047142246</id><updated>2026-02-28T13:44:58.502+01:00</updated><category term="TFS"/><category term="sitecore"/><category term="sql"/><category term="debian"/><category term="transmission"/><category term="azure"/><category term="beyond compare"/><category term="deploy"/><category term="deployment"/><category term="iis"/><category term="plex"/><category term="replication"/><category term="sickbeard"/><category term="sxa"/><category term="wcf"/><category term="windows service"/><category term="Soap"/><category term="config"/><category term="git"/><category term="json"/><category term="manager"/><category term="mono"/><category term="msbuild"/><category term="multi language"/><category term="nancyfx"/><category term="nginx"/><category term="octopus deploy"/><category term="petapoco"/><category term="powershell"/><category term="python"/><category term="queue"/><category term="service bus"/><category term="services"/><category term="source control"/><category term="tfs2010"/><category term="toolbar"/><category term="tv-shows"/><category term="user rights"/><category term="version number"/><category term="versioning"/><category term="visual studio"/><category term="vs2010"/><category term="vsts"/><category term="Content Security Policy"/><category term="SoapUI"/><category term="Testing"/><category term="Webservices"/><category term="ajax"/><category term="api"/><category term="arguments"/><category term="asmx"/><category term="assemblyinfo"/><category term="attribute"/><category term="audit"/><category term="basic authentication"/><category term="binding"/><category term="books"/><category term="bootloader"/><category term="build"/><category term="build agent"/><category term="caliburn micro"/><category term="change data capture"/><category term="cicd"/><category term="cmder"/><category term="compare"/><category term="context menu"/><category term="cookie"/><category term="core"/><category term="crlf"/><category term="cross domain"/><category term="csp"/><category term="custom dialog"/><category term="data tools"/><category term="django"/><category term="dotnet"/><category term="e-mail"/><category term="environments"/><category term="error logging"/><category term="eventlog"/><category term="excel"/><category term="experience editor"/><category term="favicon"/><category term="fiddler"/><category term="flickr"/><category term="github"/><category term="gitlab"/><category term="hashing"/><category term="hosting"/><category term="hreflang"/><category term="htmlcontrolfield"/><category term="hyper-v"/><category term="informix"/><category term="installer"/><category term="installutil"/><category term="interop"/><category term="invalid"/><category term="ip"/><category term="issue"/><category term="jquery"/><category term="kendo"/><category term="kendoui"/><category term="lf"/><category term="linkprovider"/><category term="linq"/><category term="log"/><category term="logger"/><category term="mapping"/><category term="md5"/><category term="merge tool"/><category term="message size"/><category term="mobile"/><category term="modelsbuilder"/><category term="monitor"/><category term="monitoring"/><category term="msdeploy"/><category term="msi"/><category term="multi line"/><category term="named parameters"/><category term="npoi"/><category term="options request"/><category term="orm"/><category term="outlook"/><category term="plain text"/><category term="pushover"/><category term="raygun"/><category term="redis"/><category term="repository"/><category term="resources"/><category term="rest"/><category term="restful"/><category term="restfull"/><category term="schema compare"/><category term="scootersoftware"/><category term="sentry"/><category term="server"/><category term="setparams"/><category term="setup"/><category term="sharepoint"/><category term="ssdt"/><category term="svc"/><category term="tail"/><category term="targets"/><category term="template"/><category term="topic"/><category term="transactional"/><category term="transform"/><category term="transformation"/><category term="triggers"/><category term="umbraco"/><category term="undo"/><category term="unicorn"/><category term="update button"/><category term="web"/><category term="web.config"/><category term="webhttpbinding"/><category term="wix"/><category term="work item"/><category term="workitem"/><category term="wpf"/><category term="xp0"/><category term="yml"/><category term="ymltransfrom"/><title type='text'>&amp;gt;Same problem, more code</title><subtitle type='html'></subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://sameproblemmorecode.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6112035634047142246/posts/default?redirect=false'/><link rel='alternate' type='text/html' href='http://sameproblemmorecode.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><link rel='next' type='application/atom+xml' href='http://www.blogger.com/feeds/6112035634047142246/posts/default?start-index=26&amp;max-results=25&amp;redirect=false'/><author><name>Luuk</name><uri>http://www.blogger.com/profile/17727572272200996660</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>56</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>25</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-6112035634047142246.post-6413478527027537271</id><published>2022-05-31T21:07:00.004+02:00</published><updated>2022-05-31T21:19:03.738+02:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="arguments"/><category scheme="http://www.blogger.com/atom/ns#" term="cicd"/><category scheme="http://www.blogger.com/atom/ns#" term="core"/><category scheme="http://www.blogger.com/atom/ns#" term="dotnet"/><category scheme="http://www.blogger.com/atom/ns#" term="gitlab"/><category scheme="http://www.blogger.com/atom/ns#" term="iis"/><category scheme="http://www.blogger.com/atom/ns#" term="issue"/><category scheme="http://www.blogger.com/atom/ns#" term="msbuild"/><category scheme="http://www.blogger.com/atom/ns#" term="msdeploy"/><category scheme="http://www.blogger.com/atom/ns#" term="powershell"/><category scheme="http://www.blogger.com/atom/ns#" term="setparams"/><title type='text'>Build and deploy .net framework / .net core to IIS with Gitlab and some awesome templates</title><content type='html'>In this blog I&#39;ll explain the way we do our builds with gitlab. It took some time to get to this, so I&#39;m happy to share it with you. At first we set the ground-rules:


&lt;div&gt;&lt;ol style=&quot;text-align: left;&quot;&gt;&lt;li&gt;You use GitLab&lt;/li&gt;&lt;li&gt;You have GitLab runners on windows machines on powershell (core)&lt;/li&gt;&lt;li&gt;Make use of merge requests to merge code changes to the default branch&lt;/li&gt;&lt;li&gt;Create release tags in the form of semver &#39;1.0.0&#39;&lt;/li&gt;&lt;li&gt;The default branch always gets deployed to your development IIS server&lt;/li&gt;&lt;li&gt;After creating a release in GitLab, a production build is generated&lt;/li&gt;&lt;li&gt;Manual trigger starts the deployment to your production IIS server&lt;/li&gt;&lt;li&gt;There is a solution file in the root of the project&lt;/li&gt;&lt;li&gt;There is only 1 deployable webproject in your solution&lt;/li&gt;&lt;li&gt;The dotnet-* templates reside in a shared repository&lt;/li&gt;&lt;/ol&gt;&lt;div&gt;Challenges we faced we&#39;re especially with the msdeploy command which behaves really funky under powershell (I dare you to do a duckduckgo search on this and see what you&#39;ll find). I really like the way everything is parameterized, so the core just works, but if you need a bit more, you just adjust where needed without breaking all the defaults in the build an deploy pipelines. This makes maintaining them a lot easier when environments change and forces you to use a standardized way of work.&amp;nbsp;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;I also like the validation of the release tag numbering using the .pre step validate_tag job. It only runs when a tag is set and it&#39;s not in the form of a semver. You can never build a production packages without a proper number.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;The .gitlab.yml is the ci file for your end project, it sets urls and can customize some configuration. The dotnet-framework.v1.gitlab-ci.yml and dotnet-core.v1.gitlab-ci.yml files are the base templates you can inherit in the .gitlab-ci.yml.&amp;nbsp;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Below are all the gists needed to get you going or just to get inspired. If you have any feedback, I&#39;m happy to learn about your experiences. Comment on the gist or this blog!&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Happy deploying,&lt;/div&gt;&lt;div&gt;Luuk&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;/div&gt;

&lt;script src=&quot;https://gist.github.com/luuksommers/7dd10db8435d7d3624343021abecd53d.js&quot;&gt;&lt;/script&gt;</content><link rel='replies' type='application/atom+xml' href='http://sameproblemmorecode.blogspot.com/feeds/6413478527027537271/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://sameproblemmorecode.blogspot.com/2022/05/build-and-deploy-net-framework-net-core.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6112035634047142246/posts/default/6413478527027537271'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6112035634047142246/posts/default/6413478527027537271'/><link rel='alternate' type='text/html' href='http://sameproblemmorecode.blogspot.com/2022/05/build-and-deploy-net-framework-net-core.html' title='Build and deploy .net framework / .net core to IIS with Gitlab and some awesome templates'/><author><name>Luuk</name><uri>http://www.blogger.com/profile/17727572272200996660</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6112035634047142246.post-1585684652140987166</id><published>2021-02-24T13:51:00.008+01:00</published><updated>2021-02-24T13:55:18.554+01:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="crlf"/><category scheme="http://www.blogger.com/atom/ns#" term="git"/><category scheme="http://www.blogger.com/atom/ns#" term="lf"/><category scheme="http://www.blogger.com/atom/ns#" term="modelsbuilder"/><category scheme="http://www.blogger.com/atom/ns#" term="umbraco"/><title type='text'>Umbraco modelsbuilder line endings</title><content type='html'>&lt;p&gt;Everytime the modelsbuilder detects a change in LiveAppData moe, the generated file will be touched.&lt;/p&gt;&lt;p&gt;Git uses auto line-endings, meaning CRLF on windows, while the umbraco models builder uses LF (https://github.com/modelsbuilder/ModelsBuilder.Original/blob/v4/dev/src/Our.ModelsBuilder/Building/CodeWriterBase.cs#L65) This is seen as a change, but when running &lt;b&gt;git add&lt;/b&gt; this change is corrected by git and then dropped.&lt;/p&gt;&lt;p&gt;This is very annoying, but easy to fix with a .gitattributes file. As a base I&#39;ve used the one in the UmbracoCms repository, and extended it with the path to the models builder output:&lt;p&gt;

&lt;script src=&quot;https://gist.github.com/luuksommers/0c092634295e0e606b294608b3cc7634.js&quot;&gt;&lt;/script&gt;</content><link rel='replies' type='application/atom+xml' href='http://sameproblemmorecode.blogspot.com/feeds/1585684652140987166/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://sameproblemmorecode.blogspot.com/2021/02/umbraco-modelsbuilder-line-endings.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6112035634047142246/posts/default/1585684652140987166'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6112035634047142246/posts/default/1585684652140987166'/><link rel='alternate' type='text/html' href='http://sameproblemmorecode.blogspot.com/2021/02/umbraco-modelsbuilder-line-endings.html' title='Umbraco modelsbuilder line endings'/><author><name>Luuk</name><uri>http://www.blogger.com/profile/17727572272200996660</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6112035634047142246.post-4800913664557348456</id><published>2018-12-04T09:57:00.001+01:00</published><updated>2018-12-04T15:54:11.392+01:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="experience editor"/><category scheme="http://www.blogger.com/atom/ns#" term="sitecore"/><category scheme="http://www.blogger.com/atom/ns#" term="sxa"/><title type='text'>Remove format on paste in SXA Experience Editor</title><content type='html'>The experience editor uses the &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/contenteditable&quot;&gt;contenteditable&lt;/a&gt; feature. To remove formatting on paste you cannot use the Telerik RTE feature, because that one isn&#39;t used.



&lt;br /&gt;
&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEijGvMPkFfJb16vHr5_Nz8L7e2w5j08c0OvdQsHfAahkpPOtG34v7h-1ajf8tCbBlIPO3xcTGkJ70_Unnx4-ZokVUrE0ofy2s6DyxztBJ0-2VuSZDL_3TjQI6QZcEJQgjV_krph1KLJsFP0/s1600/sxa_screenshot.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; data-original-height=&quot;383&quot; data-original-width=&quot;1076&quot; height=&quot;113&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEijGvMPkFfJb16vHr5_Nz8L7e2w5j08c0OvdQsHfAahkpPOtG34v7h-1ajf8tCbBlIPO3xcTGkJ70_Unnx4-ZokVUrE0ofy2s6DyxztBJ0-2VuSZDL_3TjQI6QZcEJQgjV_krph1KLJsFP0/s320/sxa_screenshot.png&quot; width=&quot;320&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;br /&gt;&lt;/div&gt;
To solve, I&#39;ve created a new Editing Theme in the medialibrary\Base Themes:&lt;br /&gt;
&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiVKdfYP401XhTIFt0YX9Me1WC_wz51k4t0p1odfVnudxRjVTCLAceQsmvSiXgv3ncLyzNQXBPO5F0-0C_QgiTsdLSrVqW6vdEovywIdKANPUvIOJ86s6UCTbmwH02xBSsSQ58zO4B5VZh8/s1600/my-editing-theme.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; data-original-height=&quot;455&quot; data-original-width=&quot;544&quot; height=&quot;267&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiVKdfYP401XhTIFt0YX9Me1WC_wz51k4t0p1odfVnudxRjVTCLAceQsmvSiXgv3ncLyzNQXBPO5F0-0C_QgiTsdLSrVqW6vdEovywIdKANPUvIOJ86s6UCTbmwH02xBSsSQ58zO4B5VZh8/s320/my-editing-theme.png&quot; width=&quot;320&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;br /&gt;
Upload the editor.js file containing:&lt;br /&gt;
&lt;br /&gt;
&lt;pre class=&quot;brush:js;&quot;&gt;window.$xa(document).ready(function () {
    $(&#39;[contenteditable]&#39;).on(&#39;paste&#39;, function(e) {
     e.preventDefault();
     var text = &#39;&#39;;
     if (e.clipboardData || e.originalEvent.clipboardData) {
       text = (e.originalEvent || e).clipboardData.getData(&#39;text/plain&#39;);
     } else if (window.clipboardData) {
       text = window.clipboardData.getData(&#39;Text&#39;);
     }
     if (document.queryCommandSupported(&#39;insertText&#39;)) {
       document.execCommand(&#39;insertText&#39;, false, text);
     } else {
       document.execCommand(&#39;paste&#39;, false, text);
     }
 });
});
&lt;/pre&gt;
&lt;br /&gt;
Then add My Editing Theme to the Editing Theme of your site:&lt;br /&gt;
&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEju1qzMAREBMuu94mfvXy1tRdkOPXEEeb8suLZRnArh0ve1Su4pPaBDK5DXbPyIE560MpVEBaTTApCufnrxfqGNwKcinLPLFoQ1EAsmAElcBWXNwDADLRhTNA36oB45Yal4OZ81i6YUS0xx/s1600/add-editing-theme.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; data-original-height=&quot;876&quot; data-original-width=&quot;1600&quot; height=&quot;348&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEju1qzMAREBMuu94mfvXy1tRdkOPXEEeb8suLZRnArh0ve1Su4pPaBDK5DXbPyIE560MpVEBaTTApCufnrxfqGNwKcinLPLFoQ1EAsmAElcBWXNwDADLRhTNA36oB45Yal4OZ81i6YUS0xx/s640/add-editing-theme.png&quot; width=&quot;640&quot; /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;
&lt;br /&gt;
Now you can do paste from word without keeping the content. Happy content editors, happy developers!&lt;br /&gt;
&lt;br /&gt;
Cheers,
Luuk
</content><link rel='replies' type='application/atom+xml' href='http://sameproblemmorecode.blogspot.com/feeds/4800913664557348456/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://sameproblemmorecode.blogspot.com/2018/12/remove-format-on-pase-in-sxa-experience.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6112035634047142246/posts/default/4800913664557348456'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6112035634047142246/posts/default/4800913664557348456'/><link rel='alternate' type='text/html' href='http://sameproblemmorecode.blogspot.com/2018/12/remove-format-on-pase-in-sxa-experience.html' title='Remove format on paste in SXA Experience Editor'/><author><name>Luuk</name><uri>http://www.blogger.com/profile/17727572272200996660</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEijGvMPkFfJb16vHr5_Nz8L7e2w5j08c0OvdQsHfAahkpPOtG34v7h-1ajf8tCbBlIPO3xcTGkJ70_Unnx4-ZokVUrE0ofy2s6DyxztBJ0-2VuSZDL_3TjQI6QZcEJQgjV_krph1KLJsFP0/s72-c/sxa_screenshot.png" height="72" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6112035634047142246.post-6357546148693820163</id><published>2018-11-21T16:57:00.003+01:00</published><updated>2018-11-21T16:57:41.462+01:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Content Security Policy"/><category scheme="http://www.blogger.com/atom/ns#" term="csp"/><category scheme="http://www.blogger.com/atom/ns#" term="invalid"/><category scheme="http://www.blogger.com/atom/ns#" term="kendo"/><category scheme="http://www.blogger.com/atom/ns#" term="kendoui"/><category scheme="http://www.blogger.com/atom/ns#" term="template"/><title type='text'>Kendo UI Invalid template message</title><content type='html'>Just in case you&#39;ll get:&lt;br /&gt;
&lt;br /&gt;
&lt;span style=&quot;color: red; font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace; font-size: x-small;&quot;&gt;Invalid template:&#39;&amp;lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;yes&quot;?&amp;gt;

&amp;lt;cp:coreProperties xmlns:cp=&quot;http://schemas.openxmlformats.org/package/2006/metadata/core-properties&quot; xmlns:dc=&quot;http://purl.org/dc/elements/1.1/&quot; xmlns:dcterms=&quot;http://purl.org/dc/terms/&quot; xmlns:dcmitype=&quot;http://purl.org/dc/dcmitype/&quot; xmlns:xsi=&quot;http://www.w3.org/2001/XMLSchema-instance&quot;&amp;gt;&amp;lt;dc:creator&amp;gt;${creator}&amp;lt;/dc:creator&amp;gt;&amp;lt;cp:lastModifiedBy&amp;gt;${lastModifiedBy}&amp;lt;/cp:lastModifiedBy&amp;gt;&amp;lt;dcterms:created xsi:type=&quot;dcterms:W3CDTF&quot;&amp;gt;${created}&amp;lt;/dcterms:created&amp;gt;&amp;lt;dcterms:modified xsi:type=&quot;dcterms:W3CDTF&quot;&amp;gt;${modified}&amp;lt;/dcterms:modified&amp;gt;&amp;lt;/cp:coreProperties&amp;gt;&#39; Generated code:&#39;var $kendoOutput, $kendoHtmlEncode = kendo.htmlEncode;with(data){$kendoOutput=&#39;&amp;lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;yes&quot;?&amp;gt;\r\n&amp;lt;cp:coreProperties xmlns:cp=&quot;http://schemas.openxmlformats.org/package/2006/metadata/core-properties&quot; xmlns:dc=&quot;http://purl.org/dc/elements/1.1/&quot; xmlns:dcterms=&quot;http://purl.org/dc/terms/&quot; xmlns:dcmitype=&quot;http://purl.org/dc/dcmitype/&quot; xmlns:xsi=&quot;http://www.w3.org/2001/XMLSchema-instance&quot;&amp;gt;&amp;lt;dc:creator&amp;gt;&#39;+($kendoHtmlEncode(creator))+&#39;&amp;lt;/dc:creator&amp;gt;&amp;lt;cp:lastModifiedBy&amp;gt;&#39;+($kendoHtmlEncode(lastModifiedBy))+&#39;&amp;lt;/cp:lastModifiedBy&amp;gt;&amp;lt;dcterms:created xsi:type=&quot;dcterms:W3CDTF&quot;&amp;gt;&#39;+($kendoHtmlEncode(created))+&#39;&amp;lt;/dcterms:created&amp;gt;&amp;lt;dcterms:modified xsi:type=&quot;dcterms:W3CDTF&quot;&amp;gt;&#39;+($kendoHtmlEncode(modified))+&#39;&amp;lt;/dcterms:modified&amp;gt;&amp;lt;/cp:coreProperties&amp;gt;&#39;;}return $kendoOutput;&#39;&amp;nbsp;
&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
With firefox I got the message &#39;&lt;span style=&quot;color: red; font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace;&quot;&gt;Content Security Policy: The page’s settings blocked the loading of a resource at eval (“script-src”).&lt;/span&gt;&#39;&lt;br /&gt;
&lt;br /&gt;
So in your&amp;nbsp;&lt;span class=&quot;message-body-wrapper&quot;&gt;Content Security Policy&amp;nbsp;&lt;/span&gt;policy add &#39;unsave-eval&#39; to the script-src.&lt;br /&gt;
&lt;br /&gt;
Cheers,&lt;br /&gt;
L</content><link rel='replies' type='application/atom+xml' href='http://sameproblemmorecode.blogspot.com/feeds/6357546148693820163/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://sameproblemmorecode.blogspot.com/2018/11/kendo-ui-invalid-template-message.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6112035634047142246/posts/default/6357546148693820163'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6112035634047142246/posts/default/6357546148693820163'/><link rel='alternate' type='text/html' href='http://sameproblemmorecode.blogspot.com/2018/11/kendo-ui-invalid-template-message.html' title='Kendo UI Invalid template message'/><author><name>Luuk</name><uri>http://www.blogger.com/profile/17727572272200996660</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6112035634047142246.post-444608644611507764</id><published>2018-11-06T23:37:00.002+01:00</published><updated>2018-11-06T23:38:39.687+01:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="cookie"/><category scheme="http://www.blogger.com/atom/ns#" term="hreflang"/><category scheme="http://www.blogger.com/atom/ns#" term="linkprovider"/><category scheme="http://www.blogger.com/atom/ns#" term="multi language"/><category scheme="http://www.blogger.com/atom/ns#" term="sitecore"/><category scheme="http://www.blogger.com/atom/ns#" term="sxa"/><title type='text'>Extend Sitecore SXA metadata with hreflang and better favicon support (pt. 2 - hreflang)</title><content type='html'>When you&#39;re creating a multi lingual site, you probably want to tell the search engines to tell where to find the content in a different language. The way to do this is using &lt;a href=&quot;https://en.wikipedia.org/wiki/Hreflang&quot;&gt;hreflang&lt;/a&gt;.&lt;br /&gt;
&lt;br /&gt;
Using the hreflang from the &lt;a href=&quot;https://github.com/luuksommers/sitecore-sxa-metadataextended&quot;&gt;MetadataExtended&lt;/a&gt;&amp;nbsp;this is really easy peasy!&lt;br /&gt;
&lt;br /&gt;
You&#39;ll only have to add the hreflang rendering to the metadata partial design (like with the FaviconExtension in &lt;a href=&quot;https://sameproblemmorecode.blogspot.com/2018/11/extend-sitecore-sxa-metadata-with.html&quot;&gt;the previous post&lt;/a&gt;) manually, the rest is in the config.&lt;br /&gt;
&lt;br /&gt;
The idea is that you don&#39;t use the language cookie, but always use the language from the url. To do so we need to enable the custom link manager and add a pipeline to remove the language cookie:&lt;br /&gt;
&lt;br /&gt;
&lt;pre class=&quot;brush:xml;&quot;&gt;&amp;lt;configuration xmlns:patch=&quot;http://www.sitecore.net/xmlconfig/&quot;&amp;gt;
  &amp;lt;sitecore&amp;gt;
    &amp;lt;linkManager defaultProvider=&quot;sitecore&quot;&amp;gt;
      &amp;lt;providers&amp;gt;
        &amp;lt;add name=&quot;ExtendedLinkProvider&quot; 
             type=&quot;SXA.Feature.MetadataExtended.Providers.ExtendedLinkProvider, SXA.Feature.MetadataExtended&quot; 
             cacheExpiration=&quot;5&quot; 
             addAspxExtension=&quot;false&quot; 
             alwaysIncludeServerUrl=&quot;false&quot; 
             lowercaseUrls=&quot;true&quot; 
             encodeNames=&quot;true&quot; 
             languageEmbedding=&quot;always&quot; 
             languageLocation=&quot;filePath&quot; 
             shortenUrls=&quot;false&quot; 
             useDisplayName=&quot;true&quot;&amp;gt;
        &amp;lt;/add&amp;gt;
      &amp;lt;/providers&amp;gt;
      &amp;lt;patch:attribute name=&quot;defaultProvider&quot;&amp;gt;switchableLinkProvider&amp;lt;/patch:attribute&amp;gt;
    &amp;lt;/linkManager&amp;gt;
    &amp;lt;pipelines&amp;gt;
      &amp;lt;httpRequestProcessed&amp;gt;
        &amp;lt;processor type=&quot;SXA.Feature.MetadataExtended.Pipelines.HttpRequestProcessed.LanguageCookieRemover, SXA.Feature.MetadataExtended&quot; resolve=&quot;true&quot; /&amp;gt;
      &amp;lt;/httpRequestProcessed&amp;gt;
    &amp;lt;/pipelines&amp;gt;
  &amp;lt;/sitecore&amp;gt;
&amp;lt;/configuration&amp;gt;
&lt;/pre&gt;
&lt;br /&gt;
Then enable the ExtendedLinkProvider in your SXA site, and disable language cookie support. Browse to&amp;nbsp;/sitecore/content/{tenant}/{site}/Settings/Site Grouping/{site} and update the Link Provider Name. You&#39;ll also need to set the&amp;nbsp;disableLanguageCookie to true:&lt;br /&gt;
&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg1WD_ADnNIENvGX-5KYIT5K2gqTTIya8uIHo9Y5s4uMzM1-QgvOMRTgTfqm2uExvRgIulsn4EPuLUEo1QjUgf4JVg-5X8EdkQ-b44Zp3fdTpj4abL80HSS2cGDym2UeJPIfMzu4iArZUKd/s1600/firefox_2018-11-06_22-53-46.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; data-original-height=&quot;694&quot; data-original-width=&quot;1600&quot; height=&quot;172&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg1WD_ADnNIENvGX-5KYIT5K2gqTTIya8uIHo9Y5s4uMzM1-QgvOMRTgTfqm2uExvRgIulsn4EPuLUEo1QjUgf4JVg-5X8EdkQ-b44Zp3fdTpj4abL80HSS2cGDym2UeJPIfMzu4iArZUKd/s400/firefox_2018-11-06_22-53-46.png&quot; width=&quot;400&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
The ExtendedLinkProvider does a bit of magic, it adds the language to the url for all languages, except for &#39;en&#39;. You can always modify this behavior, but I like it this way.&lt;br /&gt;
&lt;br /&gt;
To get the right localized url which uses the displayname instead of the item name (see LinkManager config above &#39;useDisplayName&#39;), you&#39;ll have to do something weird, I would expect that it works when you use the language switcher it will pick up the displayname in that language. Too bad it doesn&#39;t do that, you&#39;ll need to get the language item. But the language item itself doesn&#39;t add the language in front of the url, so wrapping it around a LanguageSwitcher does the magic:&lt;br /&gt;
&lt;br /&gt;
&lt;pre class=&quot;brush:csharp;&quot;&gt;var language = Language.Parse(languageCode);

// We have to get the language item for the right display-name
var languageItem = item.Database.GetItem(item.ID, language);

// And use the Language switcher to get the right language in the url
using (new LanguageSwitcher(language))
{
    return LinkManager.GetItemUrl(languageItem); &lt;/pre&gt;
&lt;pre class=&quot;brush:csharp;&quot;&gt;    // NOTE: The actual code has an option to return the full server url&lt;/pre&gt;
&lt;pre class=&quot;brush:csharp;&quot;&gt;    // which is needed for hreflang
}
&lt;/pre&gt;
&lt;br /&gt;
With this, you&#39;ll get the hreflang:&lt;br /&gt;
&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj65wkoaVKazAfQ_PShArF1CbwKoZoqEC4ZKhQ5998BPlmTb_ZiF8VlGOcODEhKirWaogrkQBJIwp5uXk2Jwcb4F5rpiLUv6i1fD3etsVPqqzLUaoUGiI0C_BMJdlf-QFql8t4eJFqEqgo4/s1600/chrome_2018-11-06_23-31-57.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; data-original-height=&quot;162&quot; data-original-width=&quot;1278&quot; height=&quot;80&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj65wkoaVKazAfQ_PShArF1CbwKoZoqEC4ZKhQ5998BPlmTb_ZiF8VlGOcODEhKirWaogrkQBJIwp5uXk2Jwcb4F5rpiLUv6i1fD3etsVPqqzLUaoUGiI0C_BMJdlf-QFql8t4eJFqEqgo4/s640/chrome_2018-11-06_23-31-57.png&quot; width=&quot;640&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
If you have any questions or issues, please hit me a message below or file a ticket on:&lt;br /&gt;
&lt;a href=&quot;https://github.com/luuksommers/sitecore-sxa-metadataextended&quot;&gt;https://github.com/luuksommers/sitecore-sxa-metadataextended&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
[dutch]Computer ze![/dutch]&lt;br /&gt;
&lt;br /&gt;
Luuk&lt;br /&gt;
&lt;br /&gt;</content><link rel='replies' type='application/atom+xml' href='http://sameproblemmorecode.blogspot.com/feeds/444608644611507764/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://sameproblemmorecode.blogspot.com/2018/11/extend-sitecore-sxa-metadata-with_6.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6112035634047142246/posts/default/444608644611507764'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6112035634047142246/posts/default/444608644611507764'/><link rel='alternate' type='text/html' href='http://sameproblemmorecode.blogspot.com/2018/11/extend-sitecore-sxa-metadata-with_6.html' title='Extend Sitecore SXA metadata with hreflang and better favicon support (pt. 2 - hreflang)'/><author><name>Luuk</name><uri>http://www.blogger.com/profile/17727572272200996660</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg1WD_ADnNIENvGX-5KYIT5K2gqTTIya8uIHo9Y5s4uMzM1-QgvOMRTgTfqm2uExvRgIulsn4EPuLUEo1QjUgf4JVg-5X8EdkQ-b44Zp3fdTpj4abL80HSS2cGDym2UeJPIfMzu4iArZUKd/s72-c/firefox_2018-11-06_22-53-46.png" height="72" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6112035634047142246.post-7865624583737505292</id><published>2018-11-03T23:15:00.003+01:00</published><updated>2018-11-03T23:16:08.304+01:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="favicon"/><category scheme="http://www.blogger.com/atom/ns#" term="mobile"/><category scheme="http://www.blogger.com/atom/ns#" term="sitecore"/><category scheme="http://www.blogger.com/atom/ns#" term="sxa"/><title type='text'>Extend Sitecore SXA metadata with hreflang and better favicon support</title><content type='html'>Sitecore SXA only supports a simple favicon OOTB. Because we have a full blown mobile supported website, we want to support all the native font formats as generated by &lt;a href=&quot;https://realfavicongenerator.net/&quot;&gt;https://realfavicongenerator.net/&lt;/a&gt;. For this I&#39;ve created &lt;a href=&quot;https://github.com/luuksommers/sitecore-sxa-metadataextended&quot;&gt;MetadataExtended&lt;/a&gt; feature for SXA.&lt;br /&gt;
&lt;br /&gt;
To use it add the _FaviconExtended template to the Settings template that has been generated for your website:&lt;br /&gt;
&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEirZiuSwiTtGbS7cC4ORYbDTrxne7UNbUhA2vpXzjil6TJ1jDf02m61hu4RFT6Kkmo_qDIB_Rs47sEZnOe_pTTbim_zqgb-4lFNQ2ALvNVgLmGgwNn-2GlhWpDshmGyDdWSBXP2WSinfkmA/s1600/firefox_2018-11-03_22-53-34.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; data-original-height=&quot;1055&quot; data-original-width=&quot;1600&quot; height=&quot;262&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEirZiuSwiTtGbS7cC4ORYbDTrxne7UNbUhA2vpXzjil6TJ1jDf02m61hu4RFT6Kkmo_qDIB_Rs47sEZnOe_pTTbim_zqgb-4lFNQ2ALvNVgLmGgwNn-2GlhWpDshmGyDdWSBXP2WSinfkmA/s400/firefox_2018-11-03_22-53-34.png&quot; width=&quot;400&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
After adding this template, you&#39;ll get a lot more options in the favicon section of your settings:&lt;br /&gt;
&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg73KiFgw9hOGL6aiq6WqjtRFs3w6umQ2Q8Un9CA1cMkJoVVszfhHCc0A7b9T3HSKetkkLoS1jYFk2MT_hu6ewVSrLxZkl0zZ3TEsYzSgbL181-DgT_g-xUWQDBFADz1fppEb9_zDSaEGnI/s1600/firefox_2018-11-03_22-55-57.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; data-original-height=&quot;1169&quot; data-original-width=&quot;1600&quot; height=&quot;291&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg73KiFgw9hOGL6aiq6WqjtRFs3w6umQ2Q8Un9CA1cMkJoVVszfhHCc0A7b9T3HSKetkkLoS1jYFk2MT_hu6ewVSrLxZkl0zZ3TEsYzSgbL181-DgT_g-xUWQDBFADz1fppEb9_zDSaEGnI/s400/firefox_2018-11-03_22-55-57.png&quot; width=&quot;400&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
Here you can upload all the files that are generated by&amp;nbsp;&lt;a href=&quot;https://realfavicongenerator.net/&quot;&gt;https://realfavicongenerator.net/&lt;/a&gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Please note &lt;/b&gt;that the site.webmanifest and browserconfig.xml contain a link to an icon. There files are not automatically generated in the initial version, so update them with the right media path.&lt;br /&gt;
&lt;br /&gt;
Now all we need to do is add the right rendering to the medatdata partial design (/sitecore/content/{tenant}/{site}/Presentation/Partial Designs/Metadata). You can do this by adding the rendering to the /sitecore/content/{tenant}/{site}/Presentation/Available Renderings and add it using the experience editor, or directly using the Presentation Details. And voila on the favicon checker, all is green!&lt;br /&gt;
&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg4aPYN0ae8WpAzmRogvVm2xSV7P1mfIQKbPNsL2UhC0DRmeqoGCEBn97mSBrOABHLG2wpRQVlt3Xjm7GXQHeJhX7qI3EBOOLG6TRABWkJZt92kPot4Mh1L6RBhpRKk6wrFb4NKm4fPajhg/s1600/chrome_2018-11-03_23-11-38.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; data-original-height=&quot;908&quot; data-original-width=&quot;1600&quot; height=&quot;181&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg4aPYN0ae8WpAzmRogvVm2xSV7P1mfIQKbPNsL2UhC0DRmeqoGCEBn97mSBrOABHLG2wpRQVlt3Xjm7GXQHeJhX7qI3EBOOLG6TRABWkJZt92kPot4Mh1L6RBhpRKk6wrFb4NKm4fPajhg/s320/chrome_2018-11-03_23-11-38.png&quot; width=&quot;320&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
On the next post I&#39;ll explain the hreflang extension.&lt;br /&gt;
&lt;br /&gt;
All code is available on&amp;nbsp;&lt;a href=&quot;https://github.com/luuksommers/sitecore-sxa-metadataextended&quot;&gt;https://github.com/luuksommers/sitecore-sxa-metadataextended&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
Happy faviconning,&lt;br /&gt;
&lt;br /&gt;
Luuk</content><link rel='replies' type='application/atom+xml' href='http://sameproblemmorecode.blogspot.com/feeds/7865624583737505292/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://sameproblemmorecode.blogspot.com/2018/11/extend-sitecore-sxa-metadata-with.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6112035634047142246/posts/default/7865624583737505292'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6112035634047142246/posts/default/7865624583737505292'/><link rel='alternate' type='text/html' href='http://sameproblemmorecode.blogspot.com/2018/11/extend-sitecore-sxa-metadata-with.html' title='Extend Sitecore SXA metadata with hreflang and better favicon support'/><author><name>Luuk</name><uri>http://www.blogger.com/profile/17727572272200996660</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEirZiuSwiTtGbS7cC4ORYbDTrxne7UNbUhA2vpXzjil6TJ1jDf02m61hu4RFT6Kkmo_qDIB_Rs47sEZnOe_pTTbim_zqgb-4lFNQ2ALvNVgLmGgwNn-2GlhWpDshmGyDdWSBXP2WSinfkmA/s72-c/firefox_2018-11-03_22-53-34.png" height="72" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6112035634047142246.post-2117860726307752329</id><published>2018-06-01T13:40:00.001+02:00</published><updated>2018-06-01T13:43:51.389+02:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="azure"/><category scheme="http://www.blogger.com/atom/ns#" term="deploy"/><category scheme="http://www.blogger.com/atom/ns#" term="deployment"/><category scheme="http://www.blogger.com/atom/ns#" term="sitecore"/><category scheme="http://www.blogger.com/atom/ns#" term="transform"/><category scheme="http://www.blogger.com/atom/ns#" term="transformation"/><category scheme="http://www.blogger.com/atom/ns#" term="web.config"/><title type='text'>Patching Sitecore web.config on Azure using VSTS WebApp deploy</title><content type='html'>&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiA5oMHm7djGAdWuleIyr6PChqTI6Xu9oQD4mcb-nBIuT9kd9jndAWH1dIUwYN9d-RSZJruhPHIzppXj8qDkMn7pTz3vuNbqQ9Z50Dfus4hDWygc1QTqKDcuoLNnYBO9gOeWLRequ97-PBr/s1600/Kudu.png&quot; imageanchor=&quot;1&quot; style=&quot;clear: left; float: left; margin-bottom: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; data-original-height=&quot;100&quot; data-original-width=&quot;100&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiA5oMHm7djGAdWuleIyr6PChqTI6Xu9oQD4mcb-nBIuT9kd9jndAWH1dIUwYN9d-RSZJruhPHIzppXj8qDkMn7pTz3vuNbqQ9Z50Dfus4hDWygc1QTqKDcuoLNnYBO9gOeWLRequ97-PBr/s1600/Kudu.png&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
With Sitecore, it&#39;s a best practice to not copy the web.config to your project, but use transformations. This is a really nice idea, but when deploying Sitecore using the ARM templates to Azure and apply your&amp;nbsp;solution on top of it, you cannot edit the web.config. With the solution below I want to show how to apply config transformations on Azure using the VSTS Web App Service Deploy task. The method is kinda easy once you know how to do it.&lt;br /&gt;
&lt;br /&gt;
First, add the code from configtransfrom to your App_Data\tools folder, the binaries and postdeployment command are stored here. Secondly add a web.azure.config to the project, with the build action set to Content. Lastly,&amp;nbsp;update the release definition and add the postdeployment task to the Web App Service Deploy.&lt;br /&gt;
&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgtdvZOG0gQ6s6zgpivCQ-ws_jCUnOGs9ndfGO_9_QRPTW_AqpNL4vn2v2IyxbYCb-p4ZqXJcrtj58rTvgBH1fsDA7yxRgL-we46gf673LS_31vO4I0BWvIOrEHoQrA6G0v98csetpIyf4W/s1600/VSTS-PostDeploy.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; data-original-height=&quot;308&quot; data-original-width=&quot;1264&quot; height=&quot;154&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgtdvZOG0gQ6s6zgpivCQ-ws_jCUnOGs9ndfGO_9_QRPTW_AqpNL4vn2v2IyxbYCb-p4ZqXJcrtj58rTvgBH1fsDA7yxRgL-we46gf673LS_31vO4I0BWvIOrEHoQrA6G0v98csetpIyf4W/s640/VSTS-PostDeploy.png&quot; width=&quot;640&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;br /&gt;
The line in the postdeploy.cmd that does the magic is:&lt;br /&gt;
&lt;pre&gt;&quot;%WEBROOT_PATH%\App_Data\tools\configtransform\SlowCheetah.Xdt.exe&quot; &quot;%WEBROOT_PATH%\web.config&quot; &quot;%WEBROOT_PATH%\web.azure.config&quot; &quot;%WEBROOT_PATH%\web.config&quot;
&lt;/pre&gt;
&lt;br /&gt;
To see all other available environment variables run &#39;set&#39; from the kudu console.&lt;br /&gt;
&lt;br /&gt;
Offcourse the source is available on Github: &lt;a href=&quot;https://github.com/luuksommers/sitecore-azure-configtransform&quot;&gt;https://github.com/luuksommers/sitecore-azure-configtransform&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
Happy transforming!&lt;br /&gt;
Luuk</content><link rel='replies' type='application/atom+xml' href='http://sameproblemmorecode.blogspot.com/feeds/2117860726307752329/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://sameproblemmorecode.blogspot.com/2018/06/patching-sitecore-webconfig-on-azure.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6112035634047142246/posts/default/2117860726307752329'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6112035634047142246/posts/default/2117860726307752329'/><link rel='alternate' type='text/html' href='http://sameproblemmorecode.blogspot.com/2018/06/patching-sitecore-webconfig-on-azure.html' title='Patching Sitecore web.config on Azure using VSTS WebApp deploy'/><author><name>Luuk</name><uri>http://www.blogger.com/profile/17727572272200996660</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiA5oMHm7djGAdWuleIyr6PChqTI6Xu9oQD4mcb-nBIuT9kd9jndAWH1dIUwYN9d-RSZJruhPHIzppXj8qDkMn7pTz3vuNbqQ9Z50Dfus4hDWygc1QTqKDcuoLNnYBO9gOeWLRequ97-PBr/s72-c/Kudu.png" height="72" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6112035634047142246.post-4726643093883082014</id><published>2018-04-06T16:31:00.001+02:00</published><updated>2018-04-06T16:31:15.810+02:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="deployment"/><category scheme="http://www.blogger.com/atom/ns#" term="environments"/><category scheme="http://www.blogger.com/atom/ns#" term="sitecore"/><category scheme="http://www.blogger.com/atom/ns#" term="unicorn"/><category scheme="http://www.blogger.com/atom/ns#" term="vsts"/><category scheme="http://www.blogger.com/atom/ns#" term="yml"/><category scheme="http://www.blogger.com/atom/ns#" term="ymltransfrom"/><title type='text'>Transforming Unicorn files in a release pipeline using YmlTransform</title><content type='html'>&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;/div&gt;
&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;/div&gt;
&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgtGArijRXqw4UsIBadH8_KzJ5DN9_QSsAC4tQZIhTrtpYBelb8JR5-ixbCYLZBnh_1eSarew9Dd2uEq5fN50yt0AKUyG9Zx_AqL3SFIYZqCoIlRtm06ul2mOlPoR6I5x8tZk71JWmiZ_OC/s1600/unicorn.png&quot; imageanchor=&quot;1&quot; style=&quot;clear: left; float: left; margin-bottom: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; data-original-height=&quot;195&quot; data-original-width=&quot;444&quot; height=&quot;140&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgtGArijRXqw4UsIBadH8_KzJ5DN9_QSsAC4tQZIhTrtpYBelb8JR5-ixbCYLZBnh_1eSarew9Dd2uEq5fN50yt0AKUyG9Zx_AqL3SFIYZqCoIlRtm06ul2mOlPoR6I5x8tZk71JWmiZ_OC/s320/unicorn.png&quot; width=&quot;320&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
When you use an automated deployment to different environments that also need changes in unicorn files (without having to update the sitecore configuration manually) you can use YmlTransform. This is an easy tool that uses an input Json file to update unicorn files before copying them to the server. Together with the &lt;a href=&quot;https://marketplace.visualstudio.com/items?itemName=qetza.replacetokens&quot;&gt;ReplaceTokens&lt;/a&gt; task this is a very powerfull solution.&lt;br /&gt;
&lt;br /&gt;
Our deployment process looks like this before we publish the web application to Azure.&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiTBYyhWysLQCkO8f2f2n99Hrb-Vu0hZQJB4DBmZbJkSSoq3NjQymkO_4JcaURWNH68F7TsSc2Ev1q7XepnaUsFMQGCfTa8VrhLQWWHTbT99byzyPuVGlZWJFBHiKnEQSOIl45c5bgX6Jpt/s1600/YmlTransform+VSTS+1.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; data-original-height=&quot;167&quot; data-original-width=&quot;627&quot; height=&quot;85&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiTBYyhWysLQCkO8f2f2n99Hrb-Vu0hZQJB4DBmZbJkSSoq3NjQymkO_4JcaURWNH68F7TsSc2Ev1q7XepnaUsFMQGCfTa8VrhLQWWHTbT99byzyPuVGlZWJFBHiKnEQSOIl45c5bgX6Jpt/s320/YmlTransform+VSTS+1.png&quot; width=&quot;320&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
First you&#39;ll need to create a Json file containing the fields you want to replace, it currently supports shared and language fields. In our case we call it unicorn.ymltransform with the following content:&lt;br /&gt;
&lt;pre class=&quot;json;&quot;&gt;[
    {
        &quot;FieldId&quot;: &quot;379de7bc-88f2-42ae-8d4a-50dd0b8796ea&quot;,
        &quot;Languages&quot;: &quot;&quot;,
        &quot;Path&quot;: &quot;/sitecore/content/Home/Item1&quot;,
        &quot;Type&quot;: &quot;Shared&quot;,
        &quot;Value&quot;: &quot;#{ApiUrl1}#&quot;
    },
    {
        &quot;FieldId&quot;: &quot;379de7bc-88f2-42ae-8d4a-50dd0b8796ea&quot;,
        &quot;Languages&quot;: &quot;*&quot;,
        &quot;Path&quot;: &quot;/sitecore/content/Home/Item2&quot;,
        &quot;Type&quot;: &quot;Shared&quot;,
        &quot;Value&quot;: &quot;#{ApiUrl2}#&quot;
    },
    {
        &quot;FieldId&quot;: &quot;86ee9731-e7fb-47c9-bab6-5cb282c3a920&quot;,
        &quot;Languages&quot;: &quot;*&quot;,
        &quot;Path&quot;: &quot;/sitecore/content/Home/Item3&quot;,
        &quot;Type&quot;: &quot;Shared&quot;,
        &quot;Value&quot;: &quot;#{OtherSetting}#&quot;
    }
]
&lt;/pre&gt;
&lt;br /&gt;
When you parse this file through the ReplaceTokens and run it over your *.ymltransform files, the unicorn files will be transformed using the actual value from the VSTS variables (which could also be loaded from a keyfault).&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;/div&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;/div&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgxI1zzANBzwk2W1fiH-9GwODDSX6fznfH1OuJrXekVfHPWICHxwBe0-xJ-bCONih1zLG7ZxjXmX-YmJZtg_MWCbcYhyphenhyphen6zS1IQDauFT-mr7QOl92m0AuyLOa3NMdSserQ1gOPyamrwluQtF/s1600/YmlTransform+VSTS+2.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; data-original-height=&quot;454&quot; data-original-width=&quot;664&quot; height=&quot;218&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgxI1zzANBzwk2W1fiH-9GwODDSX6fznfH1OuJrXekVfHPWICHxwBe0-xJ-bCONih1zLG7ZxjXmX-YmJZtg_MWCbcYhyphenhyphen6zS1IQDauFT-mr7QOl92m0AuyLOa3NMdSserQ1gOPyamrwluQtF/s320/YmlTransform+VSTS+2.png&quot; width=&quot;320&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
In the next step you can run a command with the following settings to transform the actual unicorn files:&lt;br /&gt;
&lt;pre&gt;ymltransform.exe -p &quot;App_Data/unicorn&quot; -r -t &quot;unicorn.ymltransform&quot; &lt;/pre&gt;
&lt;br /&gt;
The output of this command:
&lt;br /&gt;
&lt;pre&gt;2018-04-06T06:28:47.6709328Z Updating file D:\a\r1\a\TestProject\drop\artifacts\Website\App_Data/unicorn\Project\serialization\Content\Home\Item1.yml section Shared id 379de7bc-88f2-42ae-8d4a-50dd0b8796ea to https://apiurl1.com
2018-04-06T06:28:47.6711423Z Transformed: D:\a\r1\a\TestProject\drop\artifacts\Website\App_Data/unicorn\Project\serialization\Content\Home\Item1.yml
2018-04-06T06:28:47.7732198Z Updating file D:\a\r1\a\TestProject\drop\artifacts\Website\App_Data/unicorn\Project\serialization\Content\Home\Item2.yml section Shared id 379de7bc-88f2-42ae-8d4a-50dd0b8796ea to https://apiurl2.com
2018-04-06T06:28:47.7735015Z Transformed: D:\a\r1\a\TestProject\drop\artifacts\Website\App_Data/unicorn\Project\serialization\Content\Home\Item2.yml
2018-04-06T06:28:47.9817169Z Updating file D:\a\r1\a\TestProject\drop\artifacts\Website\App_Data/unicorn\Project\serialization\Content\Home\Item3.yml section Shared id 86ee9731-e7fb-47c9-bab6-5cb282c3a920 to HelloWorld
2018-04-06T06:28:47.9819775Z Transformed: D:\a\r1\a\TestProject\drop\artifacts\Website\App_Data/unicorn\Project\serialization\Content\Home\Item3.yml
&lt;/pre&gt;
&lt;br /&gt;
Now the yml files contain the correct information for your environment, you can upload the yml files and run a unicorn sync (automatically). &lt;br /&gt;
&lt;br /&gt;
The full sourcecode is available on Github:&lt;br /&gt;
&lt;a href=&quot;https://github.com/luuksommers/ymltransform&quot;&gt;https://github.com/luuksommers/ymltransform&amp;nbsp;&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
Happy transforming!&lt;br /&gt;
Luuk </content><link rel='replies' type='application/atom+xml' href='http://sameproblemmorecode.blogspot.com/feeds/4726643093883082014/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://sameproblemmorecode.blogspot.com/2018/04/transforming-unicorn-files-in-release.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6112035634047142246/posts/default/4726643093883082014'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6112035634047142246/posts/default/4726643093883082014'/><link rel='alternate' type='text/html' href='http://sameproblemmorecode.blogspot.com/2018/04/transforming-unicorn-files-in-release.html' title='Transforming Unicorn files in a release pipeline using YmlTransform'/><author><name>Luuk</name><uri>http://www.blogger.com/profile/17727572272200996660</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgtGArijRXqw4UsIBadH8_KzJ5DN9_QSsAC4tQZIhTrtpYBelb8JR5-ixbCYLZBnh_1eSarew9Dd2uEq5fN50yt0AKUyG9Zx_AqL3SFIYZqCoIlRtm06ul2mOlPoR6I5x8tZk71JWmiZ_OC/s72-c/unicorn.png" height="72" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6112035634047142246.post-1440455744087355119</id><published>2018-03-23T10:29:00.001+01:00</published><updated>2018-03-23T10:30:16.961+01:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="azure"/><category scheme="http://www.blogger.com/atom/ns#" term="bootloader"/><category scheme="http://www.blogger.com/atom/ns#" term="deployment"/><category scheme="http://www.blogger.com/atom/ns#" term="redis"/><category scheme="http://www.blogger.com/atom/ns#" term="sitecore"/><category scheme="http://www.blogger.com/atom/ns#" term="xp0"/><title type='text'>Using the Sitecore bootloader to add Redis to an Sitecore 8.2 XP0 installation</title><content type='html'>&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjGNm6CNkM6j7Dx9CYbk7FrGcX61pGi4i6surzE3avGoyzSQk975-H4wDIn697v0MvXGGhgt92UHwcbuiaC3S1TFUCSqdwFbGNZZbE-NXgkScJ7_Rcn6Dveaidep0O2xyZUKBheYcEg6v1y/s1600/SitecoreRedis.png&quot; imageanchor=&quot;1&quot; style=&quot;clear: left; float: left; margin-bottom: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; data-original-height=&quot;600&quot; data-original-width=&quot;1212&quot; height=&quot;158&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjGNm6CNkM6j7Dx9CYbk7FrGcX61pGi4i6surzE3avGoyzSQk975-H4wDIn697v0MvXGGhgt92UHwcbuiaC3S1TFUCSqdwFbGNZZbE-NXgkScJ7_Rcn6Dveaidep0O2xyZUKBheYcEg6v1y/s320/SitecoreRedis.png&quot; width=&quot;320&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
The Sitecore bootloader is a nifty little-underdocumented thing that can be used to easily extend a Sitecore installation. When you&#39;ll install EXM using the web deploy packages, you&#39;ll notice that it has to add some connection strings to the ConnectionStrings.config, but you cannot modify that file without restarting the application. So I was wondering, how does that work.&lt;br /&gt;
It appears that the bootloader scans directories and can apply xdt transforms to all configs. Just by placing a file called ConnectionStrings.config.xdt on the Azure WebApp in the following folder: App_Data\Transforms\Redis\Xdts\App_Config, the bootloader will try to match the filename without xdt and run the transformation. So the path after Xdts should match the folder structure from your site root.&lt;br /&gt;
The Redis package does exactly the same: I&#39;ve created a WebDeploy package containing this file, so we can deploy Redis to Sitecore without any modifications to the Sitecore installation beforehand.&lt;br /&gt;
&lt;br /&gt;
The content of the xdt file:
&lt;br /&gt;
&lt;pre class=&quot;xml;&quot;&gt;&amp;lt;?xml version=&quot;1.0&quot;?&amp;gt;
&amp;lt;connectionStrings xmlns:xdt=&quot;http://schemas.microsoft.com/XML-Document-Transform&quot;&amp;gt;
 &amp;lt;add name=&quot;redis.sessions&quot; connectionString=&quot;Redis Connection String&quot; xdt:Transform=&quot;Insert&quot; /&amp;gt;
&amp;lt;/connectionStrings&amp;gt;
&lt;/pre&gt;
&lt;br /&gt;
By adding a parameter to the web deploy package called &#39;Redis ConnectionString&#39; we can now push the Redis connection string to the web deployment package.
&lt;pre class=&quot;json;&quot;&gt;
{
  &amp;quot;name&amp;quot;: &amp;quot;[concat(variables(&#39;singleWebAppNameTidy&#39;), &#39;/&#39;, &#39;MSDeploy&#39;)]&amp;quot;,
  &amp;quot;type&amp;quot;: &amp;quot;Microsoft.Web/sites/extensions&amp;quot;,
  &amp;quot;location&amp;quot;: &amp;quot;[parameters(&#39;location&#39;)]&amp;quot;,
  &amp;quot;apiVersion&amp;quot;: &amp;quot;[variables(&#39;webApiVersion&#39;)]&amp;quot;,
  &amp;quot;properties&amp;quot;: {
    &amp;quot;addOnPackages&amp;quot;: [
      {
        &amp;quot;packageUri&amp;quot;: &amp;quot;[parameters(&#39;redisMsDeployPackageUrl&#39;)]&amp;quot;,
        &amp;quot;setParameters&amp;quot;: {
          &amp;quot;Application Path&amp;quot;: &amp;quot;[variables(&#39;singleWebAppNameTidy&#39;)]&amp;quot;,
          &amp;quot;Redis Connection String&amp;quot;: &amp;quot;[concat(reference(resourceId(&#39;Microsoft.Cache/Redis&#39;, 
                   variables(&#39;redisCacheNameTidy&#39;)), variables(&#39;redisApiVersion&#39;)).hostName, &#39;:&#39;, reference(resourceId(&#39;Microsoft.Cache/Redis&#39;, 
                   variables(&#39;redisCacheNameTidy&#39;)), variables(&#39;redisApiVersion&#39;)).sslPort, &#39;,password=&#39;, listKeys(resourceId(&#39;Microsoft.Cache/Redis&#39;, 
                   variables(&#39;redisCacheNameTidy&#39;)), variables(&#39;redisApiVersion&#39;)).primaryKey, &#39;,ssl=True,abortConnect=False&#39;)]&amp;quot;
        }
      }
    ]
  }
}
&lt;/pre&gt;
&lt;br /&gt;
During the first hit of the site, the bootloader will scan the App_Data\Transforms directory. The bootloader then runs an installer in a separated process on the Web App to apply the transformation.&lt;br /&gt;
&lt;br /&gt;
Supporting code:&lt;br /&gt;
&lt;a href=&quot;https://github.com/luuksommers/sitecore-xp0-redis&quot;&gt;https://github.com/luuksommers/sitecore-xp0-redis&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
Happy caching!&lt;br /&gt;
Luuk</content><link rel='replies' type='application/atom+xml' href='http://sameproblemmorecode.blogspot.com/feeds/1440455744087355119/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://sameproblemmorecode.blogspot.com/2018/03/using-sitecore-bootloader-to-add-redis.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6112035634047142246/posts/default/1440455744087355119'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6112035634047142246/posts/default/1440455744087355119'/><link rel='alternate' type='text/html' href='http://sameproblemmorecode.blogspot.com/2018/03/using-sitecore-bootloader-to-add-redis.html' title='Using the Sitecore bootloader to add Redis to an Sitecore 8.2 XP0 installation'/><author><name>Luuk</name><uri>http://www.blogger.com/profile/17727572272200996660</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjGNm6CNkM6j7Dx9CYbk7FrGcX61pGi4i6surzE3avGoyzSQk975-H4wDIn697v0MvXGGhgt92UHwcbuiaC3S1TFUCSqdwFbGNZZbE-NXgkScJ7_Rcn6Dveaidep0O2xyZUKBheYcEg6v1y/s72-c/SitecoreRedis.png" height="72" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6112035634047142246.post-3269408734963244056</id><published>2016-04-25T22:11:00.000+02:00</published><updated>2016-04-25T22:13:59.046+02:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="build"/><category scheme="http://www.blogger.com/atom/ns#" term="git"/><category scheme="http://www.blogger.com/atom/ns#" term="github"/><category scheme="http://www.blogger.com/atom/ns#" term="octopus deploy"/><category scheme="http://www.blogger.com/atom/ns#" term="version number"/><category scheme="http://www.blogger.com/atom/ns#" term="versioning"/><category scheme="http://www.blogger.com/atom/ns#" term="vsts"/><title type='text'>First steps towards an awesome build and deploy pipeline</title><content type='html'>So we moved to the new awesome scripted build from VSTS and GitHub as our main code repository. But how do we handle the build and deployments? In this post I will show all the tips and tricks we did to get it working. Please note that this is a continues improving plan, but it will get you started.&lt;br /&gt;
&lt;h3&gt;
Code setup&lt;/h3&gt;
First our code setup. In the root of our project we have a couple of folders to not mix up code with other tools. So we have the following folders defined:&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;src (for sources)&lt;/li&gt;
&lt;li&gt;build (for build scripts, see versioning below)&lt;/li&gt;
&lt;li&gt;tools (for external tools)&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;
Build setup&lt;/h3&gt;
&lt;div&gt;
For the build server we&#39;ve created the following steps. See the specific configurations below each name.&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;h4&gt;
Build Tab&lt;/h4&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiUJbw0IYBmOr4YqMf5oc79O_5In3W2W2yu5RVpLPaOeDPrMay_aMYI24Gep8QRXCSmHmJBVR2cRnF0hq4doJ59xXXprZki0DvJ9HuqvNX5E5DjuV-cwg_fr0tBD_zlciS-JHT8YNbnau5u/s1600/vsts-scripted-build.png&quot; imageanchor=&quot;1&quot; style=&quot;clear: left; float: left; margin-bottom: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;195&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiUJbw0IYBmOr4YqMf5oc79O_5In3W2W2yu5RVpLPaOeDPrMay_aMYI24Gep8QRXCSmHmJBVR2cRnF0hq4doJ59xXXprZki0DvJ9HuqvNX5E5DjuV-cwg_fr0tBD_zlciS-JHT8YNbnau5u/s200/vsts-scripted-build.png&quot; width=&quot;200&quot; /&gt;&lt;/a&gt;&lt;b&gt;Delete files&lt;/b&gt;&lt;br /&gt;
Contents: **\&amp;lt;Namespace&amp;gt;*.nupkg (this is because we don&#39;t do a clean checkout each time)&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Powershell&lt;/b&gt;&lt;br /&gt;
Script Filename: build/ApplyVersionToAssemblies.ps1&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;NuGet Installer&lt;/b&gt;&lt;br /&gt;
Path to Solution: **\*.sln&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Visual Studio Build&lt;/b&gt;&lt;br /&gt;
Solution:&amp;nbsp;**\*.sln&lt;br /&gt;
MSBuild Arguments: /p:RunOctoPack=true&lt;br /&gt;
&lt;b&gt;&lt;br /&gt;&lt;/b&gt;
&lt;b&gt;Visual Studio Test&lt;/b&gt;&lt;br /&gt;
Test Assembly:&amp;nbsp;**\bin\$(BuildConfiguration)\*test*.dll; -:**\xunit.runner.visualstudio.testadapter.dll; -:**\Microsoft.VisualStudio.QualityTools.UnitTestFramework.dll;-:**\&amp;lt;NameSpace&amp;gt;.TestUtils.dll&lt;br /&gt;
&lt;b&gt;&lt;br /&gt;&lt;/b&gt;
&lt;b&gt;NuGet Publisher&lt;/b&gt;&lt;br /&gt;
Path/Pattern to nupkg&amp;nbsp;**\bin\**\MeteoGroup.RouteGuard*.nupkg&lt;br /&gt;
NuGet Server Endpoint: Octopus Deploy (see Octopus Deploy, below)&lt;br /&gt;
&lt;h4&gt;
Triggers Tab&lt;/h4&gt;
&lt;div&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgR4EELX5l6MCdleVN6ztWamcyc-IK0XKa5uWCCZYcOXPS1zHshMwHVgK6K1DX7dheHlg9bCp0OYKRu5yri1VHcMOHlwmbWy_U6CDlMaz7NRriWPJGkTIboYL9jJ7j35FZpgWnkDvXrjLQP/s1600/vsts-trigger.png&quot; imageanchor=&quot;1&quot; style=&quot;clear: left; float: left; margin-bottom: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;123&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgR4EELX5l6MCdleVN6ztWamcyc-IK0XKa5uWCCZYcOXPS1zHshMwHVgK6K1DX7dheHlg9bCp0OYKRu5yri1VHcMOHlwmbWy_U6CDlMaz7NRriWPJGkTIboYL9jJ7j35FZpgWnkDvXrjLQP/s200/vsts-trigger.png&quot; width=&quot;200&quot; /&gt;&lt;/a&gt;The triggers trigger only the master, feature and hotfix branches. All other branches are not automatically build. The branch prefixes for feature and hotfix are based on the &lt;a href=&quot;http://nvie.com/posts/a-successful-git-branching-model/&quot; target=&quot;_blank&quot;&gt;GitFlow&lt;/a&gt; naming, so if we want to use GitFlow, the naming is at least the same.&lt;/div&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;h4&gt;
&lt;/h4&gt;
&lt;h4&gt;
General Tab&lt;/h4&gt;
Build Number Format: &amp;lt;YourProjectName&amp;gt;_2.$(Year:yy)$(DayOfYear)$(rev:.r)&lt;br /&gt;
&lt;h3&gt;
Version Updater&lt;/h3&gt;
&lt;div&gt;
The version updating script is a nifty little thing that uses regex to set the version number of the build in your assemblies. And with the assemblies properly versioned, your OctoPack will also use the proper version and so will your deployment. This brings the awesomeness that everything is connected to each other!&lt;/div&gt;
&lt;div&gt;
It will create versions like 2.16109.1.0 (for master branch builds) and 2.16109-feature-&amp;lt;FEATURENAME&amp;gt; for feature builds. The versions should be SemVer 1 compatible due to limitations in the NuGet 2.0 protocol. Safe the powershell script below in the build directory as ApplyVersionToAssemblies.ps1&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;pre class=&quot;brush:powershell;&quot;&gt;##-----------------------------------------------------------------------
## &amp;lt;copyright file=&quot;ApplyVersionToAssemblies.ps1&quot;&amp;gt;(c) Microsoft Corporation.
## This source is subject to the Microsoft Permissive License.
## See http://www.microsoft.com/resources/sharedsource/licensingbasics/sharedsourcelicenses.mspx.
## All other rights reserved.&amp;lt;/copyright&amp;gt;
##-----------------------------------------------------------------------
# Look for a 0.0.0.0 pattern in the build number. 
# If found use it to version the assemblies.
#
# For example, if the &#39;Build number format&#39; build process parameter 
# $(BuildDefinitionName)_$(Year:yyyy).$(Month).$(DayOfMonth)$(Rev:.r)
# then your build numbers come out like this:
# &quot;Build HelloWorld_2013.07.19.1&quot;
# This script would then apply version 2013.07.19.1 to your assemblies.

# Enable -Verbose option
[CmdletBinding()]

# Regular expression pattern to find the version in the build number 
# and then apply it to the assemblies
$BuildVersionRegex = &quot;\d+\.\d+\.\d+&quot;
$FileVersionRegex = &quot;\d+\.\d+\.\d+\.\d+&quot;
$VersionTagRegex = &quot;refs\/heads\/(\w*)\/([\w-]*)&quot;

# If this script is not running on a build server, remind user to 
# set environment variables so that this script can be debugged
if(-not ($Env:BUILD_SOURCESDIRECTORY -and $Env:BUILD_BUILDNUMBER))
{
    Write-Error &quot;You must set the following environment variables&quot;
    Write-Error &quot;to test this script interactively.&quot;
    Write-Host &#39;$Env:BUILD_SOURCESDIRECTORY - For example, enter something like:&#39;
    Write-Host &#39;$Env:BUILD_SOURCESDIRECTORY = &quot;C:\code\FabrikamTFVC\HelloWorld&quot;&#39;
    Write-Host &#39;$Env:BUILD_BUILDNUMBER - For example, enter something like:&#39;
    Write-Host &#39;$Env:BUILD_BUILDNUMBER = &quot;Build HelloWorld_0000.00.00.0&quot;&#39;
    exit 1
}

# Make sure path to source code directory is available
if (-not $Env:BUILD_SOURCESDIRECTORY)
{
    Write-Error (&quot;BUILD_SOURCESDIRECTORY environment variable is missing.&quot;)
    exit 1
}
elseif (-not (Test-Path $Env:BUILD_SOURCESDIRECTORY))
{
    Write-Error &quot;BUILD_SOURCESDIRECTORY does not exist: $Env:BUILD_SOURCESDIRECTORY&quot;
    exit 1
}
Write-Verbose &quot;BUILD_SOURCESDIRECTORY: $Env:BUILD_SOURCESDIRECTORY&quot;

# Make sure there is a build number
if (-not $Env:BUILD_BUILDNUMBER)
{
    Write-Error (&quot;BUILD_BUILDNUMBER environment variable is missing.&quot;)
    exit 1
}
Write-Verbose &quot;BUILD_BUILDNUMBER: $Env:BUILD_BUILDNUMBER&quot;
Write-Verbose &quot;BUILD_SOURCEBRANCH: $Env:BUILD_SOURCEBRANCH&quot;

# Get and validate the version data
$VersionData = [regex]::matches($Env:BUILD_BUILDNUMBER,$BuildVersionRegex)
switch($VersionData.Count)
{
   0        
      { 
         Write-Error &quot;Could not find version number data in BUILD_BUILDNUMBER.&quot;
         exit 1
      }
   1 {}
   default 
      { 
         Write-Warning &quot;Found more than instance of version data in BUILD_BUILDNUMBER.&quot; 
         Write-Warning &quot;Will assume empty version tag.&quot;
      }
}

$VersionTagData = [regex]::matches($Env:BUILD_SOURCEBRANCH,$VersionTagRegex)
switch($VersionTagData.Captures.Groups.Count)
{
   0 {}
   3 
      {
        $VersionTag = $VersionTagData.Captures.Groups[1].value + &#39;-&#39; + $VersionTagData.Captures.Groups[2].value
      }
   default 
      { 
         Write-Error &quot;Invalid version tag data in BUILD_SOURCEBRANCH.&quot; 
      }
}

$NewVersion = $VersionData[0].value
Write-Verbose &quot;Version: $NewVersion&quot;
if($VersionTag){
    Write-Verbose &quot;VersionTag: $VersionTag&quot;  
}

# Apply the version to the assembly property files
$files = gci $Env:BUILD_SOURCESDIRECTORY -recurse -include &quot;*Properties*&quot;,&quot;My Project&quot; | 
    ?{ $_.PSIsContainer } | 
    foreach { gci -Path $_.FullName -Recurse -include AssemblyInfo.* }
if($files)
{
    Write-Verbose &quot;Will apply $NewVersion to $($files.count) files.&quot;

    foreach ($file in $files) {
        $filecontent = Get-Content($file)
        attrib $file -r
        $FileVersion = $NewVersion + &quot;.0&quot;
        $filecontent -replace $FileVersionRegex, $FileVersion | Out-File $file

        if($VersionTag) {
            Add-Content $file &quot;`n[assembly: AssemblyInformationalVersion(`&quot;$NewVersion-$VersionTag`&quot;)]&quot;
            Write-Verbose &quot;$file.FullName - version tag applied&quot;
        }
        else {
            Write-Verbose &quot;$file.FullName - version applied&quot;
        }
    }
}
else
{
    Write-Warning &quot;Found no files.&quot;
}
&lt;/pre&gt;
&lt;br /&gt;
&lt;h3&gt;
Octopus Deploy&lt;/h3&gt;
&lt;div&gt;
You&#39;ve probably already heard of &lt;a href=&quot;http://www.octopus.com/&quot; target=&quot;_blank&quot;&gt;Octopus Deploy&lt;/a&gt;. Your build server builds, and Octopus Deploys.&lt;/div&gt;
&lt;div&gt;
In the previous step you&#39;ve seen that we&#39;ve created a service endpoint in VSTS. You can add it by clicking on the Settings button and add a service.&lt;/div&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgcyvERI_Y3PBOko9-R16yEFjFXJLohNlEBLUae7qOjDpH4ohcZ8D2e1VAW4OilV4KwJQqh_MR2k7rZQrb3pOIJ3AbqS2LzuG6ysDwXVrTjCGBgmfyLWYoPowR5y_eMw8iQYb7TG2m51UmL/s1600/img%25252Ftfsbuild-connectedservice1.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;82&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgcyvERI_Y3PBOko9-R16yEFjFXJLohNlEBLUae7qOjDpH4ohcZ8D2e1VAW4OilV4KwJQqh_MR2k7rZQrb3pOIJ3AbqS2LzuG6ysDwXVrTjCGBgmfyLWYoPowR5y_eMw8iQYb7TG2m51UmL/s320/img%25252Ftfsbuild-connectedservice1.png&quot; width=&quot;320&quot; /&gt;&amp;nbsp;&lt;/a&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEje5jsISJ4-Z191Ntq0f8xSlcHY0iQXelliKyCYIf_YVqK-glQIxgtsymxtNDMeW8RArLPKb19nPPhDEBnNKeo8utoK-E7XO_WHCMae7oeH8srMFIG4GaK8nzh9YPNLkVb3JXKuKbuC8hWd/s1600/img%25252Ftfsbuild-connectedservice2.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;90&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEje5jsISJ4-Z191Ntq0f8xSlcHY0iQXelliKyCYIf_YVqK-glQIxgtsymxtNDMeW8RArLPKb19nPPhDEBnNKeo8utoK-E7XO_WHCMae7oeH8srMFIG4GaK8nzh9YPNLkVb3JXKuKbuC8hWd/s200/img%25252Ftfsbuild-connectedservice2.png&quot; width=&quot;200&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
With the versioning in place, everything will work fine in Octopus, and because we have names like &#39;Feature&#39; or &#39;Hotfix&#39; in the package, you can even setup channels to quickly deploy hotfix patches to production and allow feature packages only to be deployed on your development environment. But this is something we still need to setup (maybe in a future blog post).&lt;/div&gt;
&lt;div&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiKkFsejkb-T7Zh-waMk8RuLfNUsoik9ukZvlDBXeZSXtoREo4a75FSdrAS1B99lfq1xRmHsfo77RRAGTTzGeHnSIfUUroBmE0gWOehjrxo1-njy0xkkaUeFAOB6uUdBMNlxxTedg9R0hDr/s1600/Dashboard.png&quot; imageanchor=&quot;1&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;153&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiKkFsejkb-T7Zh-waMk8RuLfNUsoik9ukZvlDBXeZSXtoREo4a75FSdrAS1B99lfq1xRmHsfo77RRAGTTzGeHnSIfUUroBmE0gWOehjrxo1-njy0xkkaUeFAOB6uUdBMNlxxTedg9R0hDr/s320/Dashboard.png&quot; width=&quot;320&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
Because the applications in the end don&#39;t know the release version / environment name, we&#39;ve created a Variable set which is called &#39;Default Environment&#39; and added the following 2 keys in it:&lt;/div&gt;
&lt;div&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi-UvRJJKYc5zGaF2Z69SXbeouSVIpx0TjyGeGOHSvajcSxM17sMb_9r3nkKOnDo2eRy_UNJg741Olz0bNCrXvn6PXieOS6g8qbzS-6H2rhSlbP8lezNhXQSwiDw9NRP6ZbGlEMG-xab58x/s1600/AppSettings+Environment+Variables.png&quot; imageanchor=&quot;1&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;118&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi-UvRJJKYc5zGaF2Z69SXbeouSVIpx0TjyGeGOHSvajcSxM17sMb_9r3nkKOnDo2eRy_UNJg741Olz0bNCrXvn6PXieOS6g8qbzS-6H2rhSlbP8lezNhXQSwiDw9NRP6ZbGlEMG-xab58x/s320/AppSettings+Environment+Variables.png&quot; width=&quot;320&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;div&gt;
All applications that need to do something with it, can now use the Version and Environment name (in our case we use it to log the version to LogStash).&lt;br /&gt;
&lt;br /&gt;
When you want to update more that one project, the &lt;a href=&quot;http://docs.octopusdeploy.com/display/OD/Octo.exe+Command+Line&quot;&gt;octo.exe&lt;/a&gt; is there to help you, with this super simple tool, you can create releases and deploy multiple projects at once. For example:&lt;br /&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;pre class=&quot;brush:shell;&quot;&gt;@echo off
set SERVER=http://&amp;lt;YOUR OCTOPUS SERVER&amp;gt;/
set APIKEY=&amp;lt;API KEY&amp;gt;
set PACKAGEVERSION=&amp;lt;PACKAGE VERSION FROM VSTS, when not Feature/Hotfix, add .0 to it&amp;gt;
set TO=Development
set RELEASENOTES=&quot;&amp;lt;RELEASE NOTES&amp;gt;&quot;

octo create-release --server %SERVER% --releasenotes=%RELEASENOTES% --apiKey %APIKEY% --packageversion %PACKAGEVERSION% --project &quot;&amp;lt;Project Name&amp;gt; Api&quot;
octo create-release --server %SERVER% --releasenotes=%RELEASENOTES% --apiKey %APIKEY% --packageversion %PACKAGEVERSION% --project &quot;&amp;lt;Project Name&amp;gt; Application&quot;
octo create-release --server %SERVER% --releasenotes=%RELEASENOTES% --apiKey %APIKEY% --packageversion %PACKAGEVERSION% --project &quot;&amp;lt;Project Name&amp;gt; Data Ingestor&quot;
octo create-release --server %SERVER% --releasenotes=%RELEASENOTES% --apiKey %APIKEY% --packageversion %PACKAGEVERSION% --project &quot;&amp;lt;Project Name&amp;gt; Product Worker&quot;

octo deploy-release --server %SERVER% --apiKey %APIKEY% --releaseNumber %PACKAGEVERSION% --deployto %TO% --waitfordeployment --project &quot;&amp;lt;Project Name&amp;gt; Api&quot;
octo deploy-release --server %SERVER% --apiKey %APIKEY% --releaseNumber %PACKAGEVERSION% --deployto %TO% --waitfordeployment --project &quot;&amp;lt;Project Name&amp;gt; Application&quot;
octo deploy-release --server %SERVER% --apiKey %APIKEY% --releaseNumber %PACKAGEVERSION% --deployto %TO% --waitfordeployment --project &quot;&amp;lt;Project Name&amp;gt; Data Ingestor&quot;
octo deploy-release --server %SERVER% --apiKey %APIKEY% --releaseNumber %PACKAGEVERSION% --deployto %TO% --waitfordeployment --project &quot;&amp;lt;Project Name&amp;gt; Product Worker&quot;
&lt;/pre&gt;
&lt;div&gt;
&lt;br /&gt;
You&#39;ll be amazed with the nice colored logging that comes out of this beauty. Now a 5 O&#39;clock deployment is nothing more than a click away (but don&#39;t do it :)) !&lt;br /&gt;
&lt;br /&gt;
We&#39;re still in the process of improving the flow of the deployment, but I like the progress we made so far. If you have any tips or questions, let me know in the comments below!&lt;br /&gt;
&lt;br /&gt;
Happy deploying!&lt;br /&gt;
Luuk&lt;/div&gt;
</content><link rel='replies' type='application/atom+xml' href='http://sameproblemmorecode.blogspot.com/feeds/3269408734963244056/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://sameproblemmorecode.blogspot.com/2016/04/first-steps-towards-awesome-build-and.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6112035634047142246/posts/default/3269408734963244056'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6112035634047142246/posts/default/3269408734963244056'/><link rel='alternate' type='text/html' href='http://sameproblemmorecode.blogspot.com/2016/04/first-steps-towards-awesome-build-and.html' title='First steps towards an awesome build and deploy pipeline'/><author><name>Luuk</name><uri>http://www.blogger.com/profile/17727572272200996660</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiUJbw0IYBmOr4YqMf5oc79O_5In3W2W2yu5RVpLPaOeDPrMay_aMYI24Gep8QRXCSmHmJBVR2cRnF0hq4doJ59xXXprZki0DvJ9HuqvNX5E5DjuV-cwg_fr0tBD_zlciS-JHT8YNbnau5u/s72-c/vsts-scripted-build.png" height="72" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6112035634047142246.post-3866549248660063629</id><published>2015-10-07T20:30:00.000+02:00</published><updated>2015-10-07T20:30:00.746+02:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="cmder"/><category scheme="http://www.blogger.com/atom/ns#" term="context menu"/><category scheme="http://www.blogger.com/atom/ns#" term="powershell"/><category scheme="http://www.blogger.com/atom/ns#" term="tail"/><title type='text'>Tail with cmder (or powershell)</title><content type='html'>With powershell it&#39;s really easy to &lt;a href=&quot;http://linux.about.com/library/cmd/blcmdl1_tail.htm&quot; target=&quot;_blank&quot;&gt;tail &lt;/a&gt;log files. But to make it even easier, I&#39;ve added a Tail with Powershell context menu in windows. Just save the next lines as a .reg file and run it.&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;/div&gt;
&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEitHw7AkzIS6Kdiv3U0Mdtj4Rd-DGqbWyE9k-eqT-bBRLoz5MMypPS-QPeTx0uNlAi8a1hDrcjFTBQ2K7HU7fzLQLUFbVe1YBvss83OyVxytykSVguH6Z9SZvUCCmaheL49qjzWiOmhPTs6/s1600/Context+Menu.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEitHw7AkzIS6Kdiv3U0Mdtj4Rd-DGqbWyE9k-eqT-bBRLoz5MMypPS-QPeTx0uNlAi8a1hDrcjFTBQ2K7HU7fzLQLUFbVe1YBvss83OyVxytykSVguH6Z9SZvUCCmaheL49qjzWiOmhPTs6/s1600/Context+Menu.png&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
Btw, mine is called &#39;Tail with &lt;a href=&quot;http://cmder.net/&quot; target=&quot;_blank&quot;&gt;cmder&lt;/a&gt;&#39; just because &lt;a href=&quot;http://cmder.net/&quot; target=&quot;_blank&quot;&gt;cmder &lt;/a&gt;is awesome!&lt;br /&gt;
&lt;br /&gt;
&lt;pre class=&quot;terminal&quot;&gt;Windows Registry Editor Version 5.00

[HKEY_CLASSES_ROOT\*\shell\Tail with cmder\command]
@=&quot;C:\\Windows\\system32\\WindowsPowerShell\\v1.0\\powershell.exe -NoExit -Command Get-Content -Wait -Tail 10 &#39;%1&#39;&quot;
&lt;/pre&gt;
&lt;br /&gt;
Cheers,&lt;br /&gt;
Luuk</content><link rel='replies' type='application/atom+xml' href='http://sameproblemmorecode.blogspot.com/feeds/3866549248660063629/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://sameproblemmorecode.blogspot.com/2015/10/tail-with-cmder-or-powershell.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6112035634047142246/posts/default/3866549248660063629'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6112035634047142246/posts/default/3866549248660063629'/><link rel='alternate' type='text/html' href='http://sameproblemmorecode.blogspot.com/2015/10/tail-with-cmder-or-powershell.html' title='Tail with cmder (or powershell)'/><author><name>Luuk</name><uri>http://www.blogger.com/profile/17727572272200996660</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEitHw7AkzIS6Kdiv3U0Mdtj4Rd-DGqbWyE9k-eqT-bBRLoz5MMypPS-QPeTx0uNlAi8a1hDrcjFTBQ2K7HU7fzLQLUFbVe1YBvss83OyVxytykSVguH6Z9SZvUCCmaheL49qjzWiOmhPTs6/s72-c/Context+Menu.png" height="72" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6112035634047142246.post-3708619671537568096</id><published>2015-09-28T21:21:00.000+02:00</published><updated>2015-09-28T21:21:45.559+02:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="assemblyinfo"/><category scheme="http://www.blogger.com/atom/ns#" term="octopus deploy"/><category scheme="http://www.blogger.com/atom/ns#" term="TFS"/><category scheme="http://www.blogger.com/atom/ns#" term="version number"/><category scheme="http://www.blogger.com/atom/ns#" term="versioning"/><title type='text'>Automatic update of assembly version using TFS2013</title><content type='html'>&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiTJPwbD4GDxmu1y0wT3uF6pu31bYMvZ2oZrAIcsWSlLtDEEi86yXlePfLzpozuQWNZ5LciTRu7fW8bKZxpxl_9wSEaGhd_vxV3Tp5_pvMSt89mEhJUtgTR-rYHi4BsFS5lxaKM8eussJQ0/s1600/tfs.jpg&quot; imageanchor=&quot;1&quot; style=&quot;clear: left; float: left; margin-bottom: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;88&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiTJPwbD4GDxmu1y0wT3uF6pu31bYMvZ2oZrAIcsWSlLtDEEi86yXlePfLzpozuQWNZ5LciTRu7fW8bKZxpxl_9wSEaGhd_vxV3Tp5_pvMSt89mEhJUtgTR-rYHi4BsFS5lxaKM8eussJQ0/s320/tfs.jpg&quot; width=&quot;320&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
To successfully implement &lt;a href=&quot;http://octopus.com&quot;&gt;Octopus Deploy&lt;/a&gt; you need to have unique version numbers for each build. If you don&#39;t want to manually edit the assembly info this could be a real pain in the ***. With the following trick you can automatically generate version numbers using TFS Build server 2013.&lt;br /&gt;
&lt;br /&gt;
What I did was create a BuildCommon.targets that automatically searches for the AssemblyInfo and updates the version number that matches the build number as generated by TFS, and check this file in your codetree. In our case the file is named: BuildCommon.targets and is placed next to the root of the solution:&lt;br /&gt;
&lt;br /&gt;
&lt;pre class=&quot;brush: xml&quot;&gt;&amp;lt;Project xmlns=&quot;http://schemas.microsoft.com/developer/msbuild/2003&quot; ToolsVersion=&quot;4.0&quot;&amp;gt;

&amp;lt;!--
    Defining custom Targets to execute before project compilation starts.
--&amp;gt;
&amp;lt;PropertyGroup&amp;gt;
    &amp;lt;CompileDependsOn&amp;gt;
        CommonBuildDefineModifiedAssemblyVersion;
        $(CompileDependsOn);
    &amp;lt;/CompileDependsOn&amp;gt;
&amp;lt;/PropertyGroup&amp;gt;

&amp;lt;!--
    Creates modified version of AssemblyInfo.cs, replaces [AssemblyVersion] attribute with the one specifying actual build version (from MSBuild properties), and includes that file instead of the original AssemblyInfo.cs in the compilation.

    Works with both, .cs and .vb version of the AssemblyInfo file, meaning it supports C# and VB.Net projects simultaneously.
--&amp;gt;
&amp;lt;Target Name=&quot;CommonBuildDefineModifiedAssemblyVersion&quot; Condition=&quot;&#39;$(VersionAssembly)&#39; != &#39;&#39;&quot;&amp;gt;
    &amp;lt;!-- Find AssemblyInfo.cs or AssemblyInfo.vb in the &quot;Compile&quot; Items. Remove it from &quot;Compile&quot; Items because we will use a modified version instead. --&amp;gt;
    &amp;lt;PropertyGroup&amp;gt;
        &amp;lt;VersionAssembly&amp;gt;$([System.Text.RegularExpressions.Regex]::Replace($(VersionAssembly), `[\w|\D]+_`, ``, System.Text.RegularExpressions.RegexOptions.IgnoreCase))&amp;lt;/VersionAssembly&amp;gt;
    &amp;lt;/PropertyGroup&amp;gt;
    &amp;lt;ItemGroup&amp;gt;
        &amp;lt;OriginalAssemblyInfo Include=&quot;@(Compile)&quot; Condition=&quot;(%(Filename) == &#39;AssemblyInfo&#39;) And (%(Extension) == &#39;.vb&#39; Or %(Extension) == &#39;.cs&#39;)&quot; /&amp;gt;
        &amp;lt;Compile Remove=&quot;**/AssemblyInfo.vb&quot; /&amp;gt;
        &amp;lt;Compile Remove=&quot;**/AssemblyInfo.cs&quot; /&amp;gt;
    &amp;lt;/ItemGroup&amp;gt;
    &amp;lt;!-- Copy the original AssemblyInfo.cs/.vb to obj\ folder, i.e. $(IntermediateOutputPath). The copied filepath is saved into @(ModifiedAssemblyInfo) Item. --&amp;gt;
    &amp;lt;Copy SourceFiles=&quot;@(OriginalAssemblyInfo)&quot;
          DestinationFiles=&quot;@(OriginalAssemblyInfo-&amp;gt;&#39;$(IntermediateOutputPath)%(Identity)&#39;)&quot;&amp;gt;
        &amp;lt;Output TaskParameter=&quot;DestinationFiles&quot; ItemName=&quot;ModifiedAssemblyInfo&quot;/&amp;gt;
    &amp;lt;/Copy&amp;gt;
    &amp;lt;!-- Replace the version bit (in AssemblyVersion and AssemblyFileVersion attributes) using regular expression. Use the defined property: $(VersionAssembly). --&amp;gt;
    &amp;lt;Message Text=&quot;Setting AssemblyVersion to $(VersionAssembly)&quot; /&amp;gt;
    &amp;lt;RegexUpdateFile Files=&quot;@(ModifiedAssemblyInfo)&quot;
                Regex=&quot;Version\(&amp;amp;quot;(\d+)\.(\d+)(\.(\d+)\.(\d+)|\.*)&amp;amp;quot;\)&quot;
                ReplacementText=&quot;Version(&amp;amp;quot;$(VersionAssembly)&amp;amp;quot;)&quot;
                /&amp;gt;
    &amp;lt;!-- Include the modified AssemblyInfo.cs/.vb file in &quot;Compile&quot; items (instead of the original). --&amp;gt;
    &amp;lt;ItemGroup&amp;gt;
        &amp;lt;Compile Include=&quot;@(ModifiedAssemblyInfo)&quot; /&amp;gt;
    &amp;lt;/ItemGroup&amp;gt;
&amp;lt;/Target&amp;gt;

&amp;lt;UsingTask TaskName=&quot;RegexUpdateFile&quot; TaskFactory=&quot;CodeTaskFactory&quot; AssemblyFile=&quot;$(MSBuildToolsPath)\Microsoft.Build.Tasks.v4.0.dll&quot;&amp;gt;
    &amp;lt;ParameterGroup&amp;gt;
        &amp;lt;Files ParameterType=&quot;Microsoft.Build.Framework.ITaskItem[]&quot; Required=&quot;true&quot; /&amp;gt;
        &amp;lt;Regex ParameterType=&quot;System.String&quot; Required=&quot;true&quot; /&amp;gt;
        &amp;lt;ReplacementText ParameterType=&quot;System.String&quot; Required=&quot;true&quot; /&amp;gt;
    &amp;lt;/ParameterGroup&amp;gt;
    &amp;lt;Task&amp;gt;
        &amp;lt;Reference Include=&quot;System.Core&quot; /&amp;gt;
        &amp;lt;Using Namespace=&quot;System&quot; /&amp;gt;
        &amp;lt;Using Namespace=&quot;System.IO&quot; /&amp;gt;
        &amp;lt;Using Namespace=&quot;System.Text.RegularExpressions&quot; /&amp;gt;
        &amp;lt;Using Namespace=&quot;Microsoft.Build.Framework&quot; /&amp;gt;
        &amp;lt;Using Namespace=&quot;Microsoft.Build.Utilities&quot; /&amp;gt;
        &amp;lt;Code Type=&quot;Fragment&quot; Language=&quot;cs&quot;&amp;gt;
            &amp;lt;![CDATA[
            try {
                var rx = new System.Text.RegularExpressions.Regex(this.Regex);
                for (int i = 0; i &amp;lt; Files.Length; ++i)
                {
                    var path = Files[i].GetMetadata(&quot;FullPath&quot;);
                    if (!File.Exists(path)) continue;

                    var txt = File.ReadAllText(path);
                    txt = rx.Replace(txt, this.ReplacementText);
                    File.WriteAllText(path, txt);
                }
                return true;
            }
            catch (Exception ex) {
                Log.LogErrorFromException(ex);
                return false;
            }
        ]]&amp;gt;
        &amp;lt;/Code&amp;gt;
    &amp;lt;/Task&amp;gt;
&amp;lt;/UsingTask&amp;gt;

&amp;lt;/Project&amp;gt;
&lt;/pre&gt;
&lt;br /&gt;
Then change the build number format to:&lt;br /&gt;
&lt;pre class=&quot;terminal&quot;&gt;$(BuildDefinitionName)_0.1.$(Year:yy)$(DayOfYear)$(Rev:.r)&lt;/pre&gt;
&lt;br /&gt;
and the MSBuild arguments:&lt;br /&gt;
&lt;pre class=&quot;terminal&quot;&gt;/p:CustomAfterMicrosoftCommonTargets=&quot;$(TF_BUILD_SOURCESDIRECTORY)\src\BuildCommon.targets&quot; /p:RunOctoPack=true /p:OctoPackPublishApiKey=API-123465 /p:OctoPackPublishPackageToHttp=http://octopus-server/nuget/packages /p:VersionAssembly=$(TF_BUILD_BUILDNUMBER)&lt;/pre&gt;
&lt;br /&gt;
This should result in unique assembly versions for each build.&lt;br /&gt;
&lt;br /&gt;
Many thanks for the creators of these posts to help me create this:&lt;br /&gt;
&lt;a href=&quot;http://www.lionhack.com/2014/02/13/msbuild-override-assembly-version/&quot; target=&quot;_blank&quot;&gt;http://www.lionhack.com/2014/02/13/msbuild-override-assembly-version/&lt;/a&gt;&lt;br /&gt;
&lt;a href=&quot;http://blog.casavian.eu/blog/2014/04/23/increment-version-for-changed-assemblies-only-first-part/&quot; target=&quot;_blank&quot;&gt;http://blog.casavian.eu/blog/2014/04/23/increment-version-for-changed-assemblies-only-first-part/&lt;/a&gt;&lt;br /&gt;
&lt;a href=&quot;http://blogs.msdn.com/b/visualstudio/archive/2010/04/02/msbuild-property-functions.aspx&quot; target=&quot;_blank&quot;&gt;http://blogs.msdn.com/b/visualstudio/archive/2010/04/02/msbuild-property-functions.aspx&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
Cheers,&lt;br /&gt;
Luuk</content><link rel='replies' type='application/atom+xml' href='http://sameproblemmorecode.blogspot.com/feeds/3708619671537568096/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://sameproblemmorecode.blogspot.com/2015/09/automatic-update-of-assembly-version.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6112035634047142246/posts/default/3708619671537568096'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6112035634047142246/posts/default/3708619671537568096'/><link rel='alternate' type='text/html' href='http://sameproblemmorecode.blogspot.com/2015/09/automatic-update-of-assembly-version.html' title='Automatic update of assembly version using TFS2013'/><author><name>Luuk</name><uri>http://www.blogger.com/profile/17727572272200996660</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiTJPwbD4GDxmu1y0wT3uF6pu31bYMvZ2oZrAIcsWSlLtDEEi86yXlePfLzpozuQWNZ5LciTRu7fW8bKZxpxl_9wSEaGhd_vxV3Tp5_pvMSt89mEhJUtgTR-rYHi4BsFS5lxaKM8eussJQ0/s72-c/tfs.jpg" height="72" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6112035634047142246.post-7584969729203652738</id><published>2015-09-15T21:05:00.001+02:00</published><updated>2015-09-15T21:05:37.802+02:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="azure"/><category scheme="http://www.blogger.com/atom/ns#" term="error logging"/><category scheme="http://www.blogger.com/atom/ns#" term="monitoring"/><category scheme="http://www.blogger.com/atom/ns#" term="raygun"/><category scheme="http://www.blogger.com/atom/ns#" term="sentry"/><title type='text'>Install Sentry (an open source error logger) on Azure using Docker containers</title><content type='html'>&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh-AiTMRVPmO5v0CsdejooMlVW6TNQP_8hvsu66b5m7Z3C0o4TW_fA5i30USRBuLh_2kpnP8pGXtAE64bIPWo17WhbwCO0gXhQtWxoFe-_3WV22F8uFIHhGetwsmekAn8Xqfhk-DIjjC3kM/s1600/dockeronubuntu.PNG&quot; imageanchor=&quot;1&quot; style=&quot;clear: right; float: right; margin-bottom: 1em; margin-left: 1em;&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;100&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh-AiTMRVPmO5v0CsdejooMlVW6TNQP_8hvsu66b5m7Z3C0o4TW_fA5i30USRBuLh_2kpnP8pGXtAE64bIPWo17WhbwCO0gXhQtWxoFe-_3WV22F8uFIHhGetwsmekAn8Xqfhk-DIjjC3kM/s320/dockeronubuntu.PNG&quot; width=&quot;320&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
Start with an Azure VM: Docker on Ubuntu Server (create one on &lt;a href=&quot;http://portal.azure.com/&quot;&gt;http://portal.azure.com&lt;/a&gt;) Create an account at &lt;a href=&quot;http://hub.docker.com/&quot;&gt;http://hub.docker.com&lt;/a&gt; so you can pull containers.

Now, when the VM is fully loaded, login with putty or any other ssh client to your Azure vm and type the following commands:&lt;br /&gt;
&lt;pre class=&quot;terminal&quot;&gt;$ docker login
$ docker search redis ### (optional search for redis)
$ docker pull redis
$ docker pull postgres
$ docker pull sentry
$ docker run -d --name sentry-redis redis
$ docker run -d --name sentry-postgres -e POSTGRES_PASSWORD=yourpassword -e POSTGRES_USER=sentry postgres
$ docker run -d --name sentry -p 8080:9000 --link sentry-redis:redis --link sentry-postgres:postgres sentry
$ docker run -it --rm --link sentry-postgres:postgres --link sentry-redis:redis sentry sentry upgrade
$ docker run -d --name sentry-celery1 --link sentry-redis:redis --link sentry-postgres:postgres sentry sentry celery worker
$ docker run -d --name sentry-celery-beat --link sentry-redis:redis --link sentry-postgres:postgres sentry sentry celery beat
&lt;/pre&gt;
For me, the initial user didn&#39;t have enough rights, so I created an additional user using:&lt;br /&gt;
&lt;pre class=&quot;terminal&quot;&gt;$ docker run -it --rm --link sentry-redis:redis --link sentry-postgres:postgres sentry sentry createsuperuser
&lt;/pre&gt;
To make the web portal accessible, you&#39;ll have to open the port Azure, using Settings - Endpoints:&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhh8fIZGNMLvOI7cmtXQD8hr4gE8LC7_dDOeQ0-_O0W7SQJ5MEZfSbLGauYhS33n6ZpuKFlS5bQgUIV8rS8yMUrh_5iraoRywMmki7gkNQ4KSIr4JyIdVDKUEI5pCPpsftavTOGnYIBgt4y/s1600/azurefirewall.PNG&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;248&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhh8fIZGNMLvOI7cmtXQD8hr4gE8LC7_dDOeQ0-_O0W7SQJ5MEZfSbLGauYhS33n6ZpuKFlS5bQgUIV8rS8yMUrh_5iraoRywMmki7gkNQ4KSIr4JyIdVDKUEI5pCPpsftavTOGnYIBgt4y/s400/azurefirewall.PNG&quot; width=&quot;400&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
All kudo&#39;s for this post go to: &lt;a href=&quot;https://hub.docker.com/_/sentry/&quot; target=&quot;_blank&quot;&gt;https://hub.docker.com/_/sentry/&lt;/a&gt;&amp;nbsp;for the excellent description, I&#39;ve only created this post to add the additional docker pull / Azure stuff. I don&#39;t know if this is how you want to run it on production, but at least you have a very easy test environment.&lt;br /&gt;
&lt;br /&gt;
Now you can compare this with other error loggers like:&lt;br /&gt;
&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;http://raygun.io/&quot;&gt;Raygun.io&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.splunk.com/&quot; target=&quot;_blank&quot;&gt;Splunk&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://rollbar.com/&quot; target=&quot;_blank&quot;&gt;Rollbar&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://stackify.com/&quot; target=&quot;_blank&quot;&gt;Stackify&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;
What is your experience with error loggers and monitoring tools and which one would you recommend?&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
Cheers,&lt;/div&gt;
&lt;div&gt;
Luuk&lt;/div&gt;
</content><link rel='replies' type='application/atom+xml' href='http://sameproblemmorecode.blogspot.com/feeds/7584969729203652738/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://sameproblemmorecode.blogspot.com/2015/09/install-sentry-open-source-error-logger.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6112035634047142246/posts/default/7584969729203652738'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6112035634047142246/posts/default/7584969729203652738'/><link rel='alternate' type='text/html' href='http://sameproblemmorecode.blogspot.com/2015/09/install-sentry-open-source-error-logger.html' title='Install Sentry (an open source error logger) on Azure using Docker containers'/><author><name>Luuk</name><uri>http://www.blogger.com/profile/17727572272200996660</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh-AiTMRVPmO5v0CsdejooMlVW6TNQP_8hvsu66b5m7Z3C0o4TW_fA5i30USRBuLh_2kpnP8pGXtAE64bIPWo17WhbwCO0gXhQtWxoFe-_3WV22F8uFIHhGetwsmekAn8Xqfhk-DIjjC3kM/s72-c/dockeronubuntu.PNG" height="72" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6112035634047142246.post-6556241555603759743</id><published>2015-07-03T14:18:00.000+02:00</published><updated>2015-07-03T14:18:03.393+02:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="build agent"/><category scheme="http://www.blogger.com/atom/ns#" term="msbuild"/><category scheme="http://www.blogger.com/atom/ns#" term="TFS"/><category scheme="http://www.blogger.com/atom/ns#" term="tfs2010"/><title type='text'>Unhandled Exception: System.InvalidOperationException: Cannot dispose the build manager because it is not idle.</title><content type='html'>Today we got this really annoying error when building on TFS2010:&lt;br /&gt;
&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgh8NLr3IBLcCznJcckdhS60L3jwYF1bQNoatCUX6qnhAtAlHmcOxIQNeWegdDrT5T8vj7cy-vuB_ESpw3OBQp9B898OcB9aJtshGmWQZLj4OdQeC0CFiwRX2J2OkNPpMDmu0r0O_hUeopv/s1600/TFS+2010+Error.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;152&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgh8NLr3IBLcCznJcckdhS60L3jwYF1bQNoatCUX6qnhAtAlHmcOxIQNeWegdDrT5T8vj7cy-vuB_ESpw3OBQp9B898OcB9aJtshGmWQZLj4OdQeC0CFiwRX2J2OkNPpMDmu0r0O_hUeopv/s640/TFS+2010+Error.png&quot; width=&quot;640&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
Long story short: Not our build server was causing this error, but the TFS server itself... it was out of diskspace..&lt;br /&gt;
&lt;br /&gt;
So please check this first before blaming everything else except TFS :)&lt;br /&gt;
&lt;br /&gt;
Cheers,&lt;br /&gt;
Luuk</content><link rel='replies' type='application/atom+xml' href='http://sameproblemmorecode.blogspot.com/feeds/6556241555603759743/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://sameproblemmorecode.blogspot.com/2015/07/unhandled-exception-systeminvalidoperat.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6112035634047142246/posts/default/6556241555603759743'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6112035634047142246/posts/default/6556241555603759743'/><link rel='alternate' type='text/html' href='http://sameproblemmorecode.blogspot.com/2015/07/unhandled-exception-systeminvalidoperat.html' title='Unhandled Exception: System.InvalidOperationException: Cannot dispose the build manager because it is not idle.'/><author><name>Luuk</name><uri>http://www.blogger.com/profile/17727572272200996660</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgh8NLr3IBLcCznJcckdhS60L3jwYF1bQNoatCUX6qnhAtAlHmcOxIQNeWegdDrT5T8vj7cy-vuB_ESpw3OBQp9B898OcB9aJtshGmWQZLj4OdQeC0CFiwRX2J2OkNPpMDmu0r0O_hUeopv/s72-c/TFS+2010+Error.png" height="72" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6112035634047142246.post-2317237682479742890</id><published>2015-03-04T19:59:00.002+01:00</published><updated>2015-03-09T09:57:15.247+01:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="api"/><category scheme="http://www.blogger.com/atom/ns#" term="books"/><category scheme="http://www.blogger.com/atom/ns#" term="json"/><category scheme="http://www.blogger.com/atom/ns#" term="restful"/><category scheme="http://www.blogger.com/atom/ns#" term="web"/><title type='text'>What I&#39;ve learned from reading RESTful Web APIs</title><content type='html'>I&#39;ve recently finished reading the book &lt;a href=&quot;http://shop.oreilly.com/product/0636920028468.do&quot; target=&quot;_blank&quot;&gt;RESTful Web APIs by Leonard Richardson, Mike Amundsen, Sam Ruby&lt;/a&gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;http://akamaicovers.oreilly.com/images/0636920028468/cat.gif&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;http://akamaicovers.oreilly.com/images/0636920028468/cat.gif&quot; height=&quot;200&quot; width=&quot;152&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
Wish I&#39;ve read this book before building an API. To summarize the things I would have done different (and you&#39;ve should have done probably too):&lt;br /&gt;
&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;Use standard naming conventions for properties from for example:&amp;nbsp;&lt;a href=&quot;http://schema.org/docs/schemas.html&quot;&gt;http://schema.org/docs/schemas.html&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Don&#39;t use application/json but a custom format like application/vnd.sameproblemmorecode.blog+json&lt;/li&gt;
&lt;li&gt;Make better use of the default HTTP Headers (e.g. the WWW-Authenticate and Link header)&lt;/li&gt;
&lt;li&gt;Return errors as described in&amp;nbsp;&lt;a href=&quot;https://tools.ietf.org/html/draft-nottingham-http-problem-06&quot;&gt;https://tools.ietf.org/html/draft-nottingham-http-problem-06&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Create hypermedia links in the HTTP headers to describe possible links. These links should also have standartized names from for example&amp;nbsp;&lt;a href=&quot;http://www.iana.org/assignments/link-relations/link-relations.xhtml&quot;&gt;http://www.iana.org/assignments/link-relations/link-relations.xhtml&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;If time allows; event create hypermedia profiles (this allows the server to change without breaking clients). One of the writers is also &lt;a href=&quot;http://amundsen.com/blog/archives/1157&quot; target=&quot;_blank&quot;&gt;writing a book&lt;/a&gt; on how to create hypermedia driven clients for this.&lt;/li&gt;
&lt;li&gt;Make sure to reuse as much standards as possible, we don&#39;t need another new standard. This enables us to reuse webcomponents (or at least parts of) between projects.&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;
Hope this helps.&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
Cheers,&lt;/div&gt;
&lt;div&gt;
Luuk&lt;/div&gt;
</content><link rel='replies' type='application/atom+xml' href='http://sameproblemmorecode.blogspot.com/feeds/2317237682479742890/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://sameproblemmorecode.blogspot.com/2015/03/what-ive-learned-from-reading-restful.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6112035634047142246/posts/default/2317237682479742890'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6112035634047142246/posts/default/2317237682479742890'/><link rel='alternate' type='text/html' href='http://sameproblemmorecode.blogspot.com/2015/03/what-ive-learned-from-reading-restful.html' title='What I&#39;ve learned from reading RESTful Web APIs'/><author><name>Luuk</name><uri>http://www.blogger.com/profile/17727572272200996660</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6112035634047142246.post-4312533538978791299</id><published>2014-11-02T18:57:00.000+01:00</published><updated>2015-02-26T11:05:01.718+01:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="beyond compare"/><category scheme="http://www.blogger.com/atom/ns#" term="config"/><category scheme="http://www.blogger.com/atom/ns#" term="fiddler"/><category scheme="http://www.blogger.com/atom/ns#" term="setup"/><category scheme="http://www.blogger.com/atom/ns#" term="toolbar"/><category scheme="http://www.blogger.com/atom/ns#" term="visual studio"/><title type='text'>My Development Setup</title><content type='html'>Last week my PC got upgraded. This blogpost serves as a reference for all the stuff I do to personalize Visual Studio and Fiddler.&lt;br /&gt;
&lt;br /&gt;
First thing I do is disable &#39;Automatically adjust visual experience based on client performance&#39; and &#39;Enable rich client visual experience&#39;, but keep &#39;Use hardware graphics acceleration if available&#39; enabled. Speed is everything baby!&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg0M6xWgD-ZVwR2JR8I2X7GDbRl8fnXXn0lO9T-Z1-zib-9XZn5WvdPg1l9mbu9OdwBOFbT94MFT_KY2OtrHsQeQD-SDaLHK9-mwuU326wspq9Tz3bal_z4Hrj8qd528NXzqe-XyObZogaN/s1600/General+settings.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg0M6xWgD-ZVwR2JR8I2X7GDbRl8fnXXn0lO9T-Z1-zib-9XZn5WvdPg1l9mbu9OdwBOFbT94MFT_KY2OtrHsQeQD-SDaLHK9-mwuU326wspq9Tz3bal_z4Hrj8qd528NXzqe-XyObZogaN/s1600/General+settings.png&quot; height=&quot;232&quot; width=&quot;400&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
Then I customize the toolbar and add BC. Pro-tip; remove all toolbar button&#39;s you never use.&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;http://sameproblemmorecode.blogspot.nl/2011/09/how-to-add-big-fat-tfs-source-control.html&quot; target=&quot;_blank&quot;&gt;Add Source control button&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://sameproblemmorecode.blogspot.nl/2012/02/how-to-add-beyond-compare-to-visual.html&quot; target=&quot;_blank&quot;&gt;Add Beyond Compare&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;br /&gt;
I always install the following plugins:&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://www.jetbrains.com/resharper/&quot; target=&quot;_blank&quot;&gt;Resharper&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://visualstudiogallery.msdn.microsoft.com/3ebde8fb-26d8-4374-a0eb-1e4e2665070c?SRC=VSIDE&quot; target=&quot;_blank&quot;&gt;File Nesting&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://visualstudiogallery.msdn.microsoft.com/f3f23845-5b1e-4811-882f-60b7181fa6d6&quot; target=&quot;_blank&quot;&gt;Rename Visual Studio Window Title&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://visualstudiogallery.msdn.microsoft.com/649af44d-95fc-4836-8264-b3af376b5929&quot; target=&quot;_blank&quot;&gt;Scrum Power Tools for Visual Studio 2013&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://visualstudiogallery.msdn.microsoft.com/69023d00-a4f9-4a34-a6cd-7e854ba318b5&quot; target=&quot;_blank&quot;&gt;(optional) SlowCheetah - XML Transforms&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;br /&gt;
Setup the Rename Visual Studio Window Title plugin (to see which branch I&#39;m working in):&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg-MpOt9ywEvSL_UOn0Hlh5P_LwQuRbvgKQFwUIbdyItpqZ_D7VqSg6OR9UonY_4cq_WavhF0uVbNcGF2mtJro_8h512UIgfhK5p-9ccBwLk0XIURE0ar1G3HSqPGGPmXIvWvV02KiqvOkZ/s1600/Rename+VS+Windows+Title.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg-MpOt9ywEvSL_UOn0Hlh5P_LwQuRbvgKQFwUIbdyItpqZ_D7VqSg6OR9UonY_4cq_WavhF0uVbNcGF2mtJro_8h512UIgfhK5p-9ccBwLk0XIURE0ar1G3HSqPGGPmXIvWvV02KiqvOkZ/s1600/Rename+VS+Windows+Title.png&quot; height=&quot;197&quot; width=&quot;400&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
Setup Scrum Power Tools (I use this for code reviews and workitem shortcuts in the toolbar):&lt;br /&gt;
&lt;ol&gt;
&lt;li&gt;Assign the work item and backlog items to Shortcut #1 and Shortcut #2&lt;/li&gt;
&lt;li&gt;Customize the toolbar and add the button for Shortcut #1 and Shortcut #2 to the standard toolbar&lt;/li&gt;
&lt;/ol&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
This is what my final toolbar looks like:&lt;/div&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgZONPSP9cVwvcvETLeo8TFdsUmL_61yqF6fiwza2DM3r2b2NnVoj6vrWp8Py7w0eA7HB5wOpuu3ykA46ezc3HLiwf7WZJSfy6ZgaUsiH9KqDck0gfuZ6I_ui1C8ZMXm-yo-vH4KQ9UgIjQ/s1600/Toolbar.png&quot; imageanchor=&quot;1&quot; style=&quot;clear: left; float: left; margin-bottom: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgZONPSP9cVwvcvETLeo8TFdsUmL_61yqF6fiwza2DM3r2b2NnVoj6vrWp8Py7w0eA7HB5wOpuu3ykA46ezc3HLiwf7WZJSfy6ZgaUsiH9KqDck0gfuZ6I_ui1C8ZMXm-yo-vH4KQ9UgIjQ/s1600/Toolbar.png&quot; height=&quot;14&quot; width=&quot;400&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;br /&gt;
I also use fiddler for API debugging. For API&#39;s its really important to see the HTTP method. To add this column, enable / add the following block in the Rules &amp;gt; Customize rules file:&lt;br /&gt;
&lt;pre class=&quot;terminal&quot;&gt;public static BindUIColumn(&quot;Method&quot;, 60)
function FillMethodColumn(oS: Session): String {
&amp;nbsp; &amp;nbsp;return oS.RequestMethod;
}&lt;/pre&gt;
&lt;br /&gt;
When you also retrieve large binary blocks, fiddler can really slow down when you accidentically click on one. The very powerfull Customize rules file, also has a solution for this. Add the following code inside the OnPeekAtResponseHeadersfunction. This will drop large response bodies, which slows down fiddler.&lt;br /&gt;
&lt;pre class=&quot;terminal&quot;&gt;// This block enables streaming for files larger than 5mb
if (oSession.oResponse.headers.Exists(&quot;Content-Length&quot;))
{
&amp;nbsp; var sLen = oSession.oResponse[&quot;Content-Length&quot;];
&amp;nbsp; var iLen: Int32 = 0;
&amp;nbsp; if (!isNaN(sLen)){
&amp;nbsp; &amp;nbsp; iLen = parseInt(sLen);
&amp;nbsp; &amp;nbsp; if (iLen &amp;gt; 5120000) {
&amp;nbsp; &amp;nbsp; &amp;nbsp; oSession.bBufferResponse = false;
&amp;nbsp; &amp;nbsp; &amp;nbsp; oSession[&quot;ui-color&quot;] = &quot;brown&quot;;
&amp;nbsp; &amp;nbsp; &amp;nbsp; oSession[&quot;log-drop-response-body&quot;] = &quot;save memory&quot;;
&amp;nbsp; &amp;nbsp; }
&amp;nbsp; }
}&lt;/pre&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
</content><link rel='replies' type='application/atom+xml' href='http://sameproblemmorecode.blogspot.com/feeds/4312533538978791299/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://sameproblemmorecode.blogspot.com/2014/11/my-development-setup.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6112035634047142246/posts/default/4312533538978791299'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6112035634047142246/posts/default/4312533538978791299'/><link rel='alternate' type='text/html' href='http://sameproblemmorecode.blogspot.com/2014/11/my-development-setup.html' title='My Development Setup'/><author><name>Luuk</name><uri>http://www.blogger.com/profile/17727572272200996660</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg0M6xWgD-ZVwR2JR8I2X7GDbRl8fnXXn0lO9T-Z1-zib-9XZn5WvdPg1l9mbu9OdwBOFbT94MFT_KY2OtrHsQeQD-SDaLHK9-mwuU326wspq9Tz3bal_z4Hrj8qd528NXzqe-XyObZogaN/s72-c/General+settings.png" height="72" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6112035634047142246.post-4460562232826327054</id><published>2014-09-22T21:30:00.000+02:00</published><updated>2014-09-22T21:30:26.856+02:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="manager"/><category scheme="http://www.blogger.com/atom/ns#" term="queue"/><category scheme="http://www.blogger.com/atom/ns#" term="service bus"/><category scheme="http://www.blogger.com/atom/ns#" term="topic"/><category scheme="http://www.blogger.com/atom/ns#" term="user rights"/><title type='text'>Major update for the SBQueueManager</title><content type='html'>Also having problems managing the service bus for windows server?&lt;br /&gt;
With the latest update of the SBQueueManager you can handle it all.&lt;br /&gt;
&lt;br /&gt;
The improvements include:&lt;br /&gt;
&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;Topic support&lt;/li&gt;
&lt;li&gt;Subscription support&lt;/li&gt;
&lt;li&gt;New user right to manage queues and topics&lt;/li&gt;
&lt;li&gt;Update queue and topic support&lt;/li&gt;
&lt;li&gt;Less crashes&lt;/li&gt;
&lt;li&gt;More feedback&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;
Check it out!&lt;/div&gt;
&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiz3sIXGh0l0LnHzu0zKexxE3KkdIIYQVJJgiR7aZLvRb374GjPAJXFCm298vqZZBNiDWwOVT9PJYwO5AER1jkJIK4Nkg5OD1vMS8nmdYVVq_BgsRIqB_psvF7UkjZNmB9r6dVDJvsEHU7a/s1600/SBQueueManager.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiz3sIXGh0l0LnHzu0zKexxE3KkdIIYQVJJgiR7aZLvRb374GjPAJXFCm298vqZZBNiDWwOVT9PJYwO5AER1jkJIK4Nkg5OD1vMS8nmdYVVq_BgsRIqB_psvF7UkjZNmB9r6dVDJvsEHU7a/s1600/SBQueueManager.png&quot; height=&quot;211&quot; width=&quot;320&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
And offcourse: source is available at Github:&amp;nbsp;&lt;a href=&quot;https://github.com/luuksommers/SBQueueManager&quot;&gt;https://github.com/luuksommers/SBQueueManager&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
Happy managing!&lt;br /&gt;
Luuk</content><link rel='replies' type='application/atom+xml' href='http://sameproblemmorecode.blogspot.com/feeds/4460562232826327054/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://sameproblemmorecode.blogspot.com/2014/09/major-update-for-sbqueuemanager.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6112035634047142246/posts/default/4460562232826327054'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6112035634047142246/posts/default/4460562232826327054'/><link rel='alternate' type='text/html' href='http://sameproblemmorecode.blogspot.com/2014/09/major-update-for-sbqueuemanager.html' title='Major update for the SBQueueManager'/><author><name>Luuk</name><uri>http://www.blogger.com/profile/17727572272200996660</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiz3sIXGh0l0LnHzu0zKexxE3KkdIIYQVJJgiR7aZLvRb374GjPAJXFCm298vqZZBNiDWwOVT9PJYwO5AER1jkJIK4Nkg5OD1vMS8nmdYVVq_BgsRIqB_psvF7UkjZNmB9r6dVDJvsEHU7a/s72-c/SBQueueManager.png" height="72" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6112035634047142246.post-8189964515426100094</id><published>2014-07-08T20:19:00.000+02:00</published><updated>2014-07-08T20:33:22.629+02:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="deploy"/><category scheme="http://www.blogger.com/atom/ns#" term="services"/><category scheme="http://www.blogger.com/atom/ns#" term="targets"/><category scheme="http://www.blogger.com/atom/ns#" term="TFS"/><category scheme="http://www.blogger.com/atom/ns#" term="tfs2010"/><category scheme="http://www.blogger.com/atom/ns#" term="windows service"/><title type='text'>Automatically deploy services using TFS2010</title><content type='html'>All credits for this post goes out to:&amp;nbsp;Hrusikesh Panda and&amp;nbsp;Mike Hadlow (see references below).&lt;br /&gt;
&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh-N7Dp3tFlEtX7e7zh7yKYBV_ah4ZIrSuDUNlMMvrxT7RvIxxG4I1uLb0HU6yoGXzQNXLtafg3LL1atNRiJ5nlPl7GdStXjt6ATKC8uuOA-R-5CGqjSwYWuiESHPXMfHn7QdjJ9TAOLRfB/s1600/TFS.jpg&quot; imageanchor=&quot;1&quot; style=&quot;clear: left; float: left; margin-bottom: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh-N7Dp3tFlEtX7e7zh7yKYBV_ah4ZIrSuDUNlMMvrxT7RvIxxG4I1uLb0HU6yoGXzQNXLtafg3LL1atNRiJ5nlPl7GdStXjt6ATKC8uuOA-R-5CGqjSwYWuiESHPXMfHn7QdjJ9TAOLRfB/s1600/TFS.jpg&quot; height=&quot;146&quot; width=&quot;200&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
To deploy Windows services with TFS2010 there are 2 major challenges; seperate the binaries on a per-project basis and automatically stop and start a service without changing the build workflow. Sounds hard? It isn&#39;t!&lt;br /&gt;
&lt;br /&gt;
If you don&#39;t want any blabla and download the sample solution directly, &lt;a href=&quot;https://github.com/luuksommers/TFSDeployedService&quot; target=&quot;_blank&quot;&gt;goto github&lt;/a&gt;.&lt;br /&gt;
&lt;br /&gt;
First add the following files to your Solution folder and make sure they will be committed to TFS:&lt;br /&gt;
&lt;a href=&quot;https://github.com/luuksommers/TFSDeployedService/blob/master/src/DeployApplication.targets&quot; target=&quot;_blank&quot;&gt;DeployApplication.targets&lt;/a&gt; (this is a copy of the WebDeploy targets from Microsoft with an extra change to copy the .config file).&lt;br /&gt;
&lt;a href=&quot;https://github.com/luuksommers/TFSDeployedService/blob/master/src/DeployService.targets&quot; target=&quot;_blank&quot;&gt;DeployService.targets&lt;/a&gt; (this stops the service, copies the files and starts the service, it also contains the location on where to put the files)&lt;br /&gt;
&lt;a href=&quot;https://github.com/luuksommers/TFSDeployedService/blob/master/src/safeServiceStart.bat&quot; target=&quot;_blank&quot;&gt;safeServiceStart.bat&lt;/a&gt; (helper to start a remote service)&lt;br /&gt;
&lt;a href=&quot;https://github.com/luuksommers/TFSDeployedService/blob/master/src/safeServiceStop.bat&quot;&gt;safeServiceStop.bat&lt;/a&gt; (helper to stop a remote service)&lt;br /&gt;
you can simply add these files to the solution items (right click solution and click add existing item).&lt;br /&gt;
&lt;br /&gt;
Edit the DeployService.targets for the right paths on the remote machine. The directory where the service is located should be available for the user running the build using a standard windows share (\\&amp;lt;servername&amp;gt;\&amp;lt;project directory&amp;gt;\&amp;lt;servicename&amp;gt;, the servername is determined during the build and can be configured for each build quality.&lt;br /&gt;
&lt;br /&gt;
Copy the &lt;a href=&quot;https://github.com/luuksommers/TFSDeployedService/blob/master/src/TFSDeployedService/Deploy.targets&quot;&gt;Deploy.targets&lt;/a&gt; into the project you want to deploy, unload the project file and edit it with visual studio. Lookup the following line:&lt;br /&gt;
&lt;pre class=&quot;brush:xml;&quot;&gt;&amp;lt;Import Project=&quot;$(MSBuildToolsPath)\Microsoft.CSharp.targets&quot; /&amp;gt;&lt;/pre&gt;
And add this line below:&lt;br /&gt;
&lt;pre class=&quot;brush:xml;&quot;&gt;&amp;lt;Import Project=&quot;Deploy.targets&quot; Condition=&quot;&#39;$(DeployOnBuild)&#39;==&#39;True&#39;&quot; /&amp;gt;&lt;/pre&gt;
Save the file and reload the project&lt;br /&gt;
&lt;br /&gt;
Once you&#39;ve reloaded the project, edit the Deploy.targets (just double click on it) and change the service name and service location. Commit all changes to TFS.&lt;br /&gt;
&lt;br /&gt;
The next step is to install the service on the remote machine. (using installutil, or whatever method you like, in the sample we can install a service by running it with the -I command line argument). The automated deployment will only start and stop the service and is not able to install and delete the service. (In my case, the service is running as a domain user, and therefor I prefer to pre-install the service with the right credentials or else you&#39;ll have to enter the credentials in the deployment script).&lt;br /&gt;
&lt;br /&gt;
To enable automatic deployment, create a new Build Configuration on your TFS2010 server and set it up with a scheduled trigger (or whatever trigger you want). In the process section add the following MSBuild arguments:&lt;br /&gt;
&lt;blockquote class=&quot;tr_bq&quot;&gt;
&amp;nbsp;/p:DeployOnBuild=True /p:DeploymentServerName=\\&amp;lt;server-to-deploy-to&amp;gt;&lt;/blockquote&gt;
If you also want to configure transformations (change the .config file during deployment), have a look at &lt;a href=&quot;http://visualstudiogallery.msdn.microsoft.com/69023d00-a4f9-4a34-a6cd-7e854ba318b5&quot; target=&quot;_blank&quot;&gt;SlowCheetah&lt;/a&gt;. This works without a problem with this configuration. To make sure SlowCheetah only works during deployment, I&#39;ve edited the project file again and added AND &#39;$(DeployOnBuild)&#39;==&#39;True&#39; in the following line:&lt;br /&gt;
&lt;pre class=&quot;brush:xml;&quot;&gt;&amp;lt;Import Project=&quot;$(SlowCheetahTargets)&quot; Condition=&quot;Exists(&#39;$(SlowCheetahTargets)&#39;) AND &#39;$(DeployOnBuild)&#39;==&#39;True&#39;&quot; Label=&quot;SlowCheetah&quot; /&amp;gt;&lt;/pre&gt;
&lt;br /&gt;
(If you don&#39;t see this line, make sure you&#39;ve installed SlowCheetah extension and added the transformations by right click on a .config file and click add transformations)&lt;br /&gt;
&lt;br /&gt;
References:&lt;br /&gt;
&lt;a href=&quot;https://gist.github.com/mrchief/4726433&quot; target=&quot;_blank&quot;&gt;http://mrchief.calepin.co/deploying-windows-service-via-msbuild&lt;/a&gt;&lt;br /&gt;
&lt;a href=&quot;http://stackoverflow.com/questions/698855/whats-the-best-way-to-get-tfs-to-output-each-project-to-its-own-directory&quot; target=&quot;_blank&quot;&gt;http://mikehadlow.blogspot.nl/2009/06/tfs-build-publishedwebsites-for-exe-and.html&lt;/a&gt;&lt;br /&gt;
&lt;a href=&quot;https://github.com/luuksommers/TFSDeployedService&quot; target=&quot;_blank&quot;&gt;https://github.com/luuksommers/TFSDeployedService&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
Happy deploying!&lt;br /&gt;
&lt;br /&gt;
Luuk</content><link rel='replies' type='application/atom+xml' href='http://sameproblemmorecode.blogspot.com/feeds/8189964515426100094/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://sameproblemmorecode.blogspot.com/2014/07/automatically-deploy-services-using.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6112035634047142246/posts/default/8189964515426100094'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6112035634047142246/posts/default/8189964515426100094'/><link rel='alternate' type='text/html' href='http://sameproblemmorecode.blogspot.com/2014/07/automatically-deploy-services-using.html' title='Automatically deploy services using TFS2010'/><author><name>Luuk</name><uri>http://www.blogger.com/profile/17727572272200996660</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh-N7Dp3tFlEtX7e7zh7yKYBV_ah4ZIrSuDUNlMMvrxT7RvIxxG4I1uLb0HU6yoGXzQNXLtafg3LL1atNRiJ5nlPl7GdStXjt6ATKC8uuOA-R-5CGqjSwYWuiESHPXMfHn7QdjJ9TAOLRfB/s72-c/TFS.jpg" height="72" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6112035634047142246.post-7755975779707034615</id><published>2014-03-24T21:08:00.000+01:00</published><updated>2014-03-24T21:09:40.738+01:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="transmission"/><category scheme="http://www.blogger.com/atom/ns#" term="windows service"/><title type='text'>Running Transmission as a Windows service</title><content type='html'>I&#39;ve recently updated my netbook server to a full-blown core i3 system with Windows 8.1. Transmission, the torrent client of my choice, can be very easily installed under windows as a service.
&lt;br /&gt;
&lt;br /&gt;
Follow these steps:
&lt;br /&gt;
&lt;br /&gt;
&lt;ol&gt;
&lt;li&gt;Download the client and cygrunsrv &amp;nbsp;(both .zip). from:&amp;nbsp;&lt;a href=&quot;http://sourceforge.net/projects/transmissiondaemon/files/&quot;&gt;http://sourceforge.net/projects/transmissiondaemon/files/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Extract the transmission executables to a folder (in my case c:\apps\transmission)&lt;/li&gt;
&lt;li&gt;Extract cygrunsrv to the same folder&lt;/li&gt;
&lt;li&gt;Starts a command prompt as administrator and go to the transmission directory (&lt;span style=&quot;font-family: Courier New, Courier, monospace;&quot;&gt;cd c:\apps\transmission&lt;/span&gt;)&lt;/li&gt;
&lt;li&gt;Execute &lt;span style=&quot;font-family: Courier New, Courier, monospace;&quot;&gt;cygrunsrv --install TransmissionBT --path c:/Apps/transmission/transmission-daemon.exe -a &quot;--pid-file transmission-daemon.pid --foreground&quot; -e HOME=c:/Apps/transmission/ -e TRANSMISSION_WEB_HOME=c:/Apps/transmission/web --stdout c:/Apps/transmission/log/transmissionbt.log --stderr c:/Apps/transmission/log/transmissionbt.error.log&lt;/span&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;div&gt;
To make the whole setup beyond awesome, install the chrome plugin &lt;a href=&quot;https://chrome.google.com/webstore/detail/torrent-to-transmission/fjfeeonbeiocojnpfboldpckcgcfknll&quot;&gt;.torrent to transmission&lt;/a&gt;. Now you can just right click every .torrent or magnet link and just sent it to transmission.&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
Happy leeching!&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
Luuk&amp;nbsp;&lt;/div&gt;
</content><link rel='replies' type='application/atom+xml' href='http://sameproblemmorecode.blogspot.com/feeds/7755975779707034615/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://sameproblemmorecode.blogspot.com/2014/03/running-transmission-under-windows-as.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6112035634047142246/posts/default/7755975779707034615'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6112035634047142246/posts/default/7755975779707034615'/><link rel='alternate' type='text/html' href='http://sameproblemmorecode.blogspot.com/2014/03/running-transmission-under-windows-as.html' title='Running Transmission as a Windows service'/><author><name>Luuk</name><uri>http://www.blogger.com/profile/17727572272200996660</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6112035634047142246.post-2079014144688851269</id><published>2013-10-27T14:00:00.001+01:00</published><updated>2014-03-26T21:33:23.141+01:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="attribute"/><category scheme="http://www.blogger.com/atom/ns#" term="binding"/><category scheme="http://www.blogger.com/atom/ns#" term="caliburn micro"/><category scheme="http://www.blogger.com/atom/ns#" term="wpf"/><title type='text'>Bind WPF controls to attributes using Caliburn Micro</title><content type='html'>To bind for example an &lt;a href=&quot;http://wpftoolkit.codeplex.com/wikipage?title=DecimalUpDown&quot;&gt;DecimalUpDown&lt;/a&gt; control to a &lt;a href=&quot;http://msdn.microsoft.com/en-us/library/system.componentmodel.dataannotations.rangeattribute.aspx&quot;&gt;RangeAttribute&lt;/a&gt; specified in a domain model, or a maxlength to a StringLengthAttribute you need to change the automatic binding of &lt;a href=&quot;http://caliburnmicro.codeplex.com/&quot;&gt;Caliburn Micro&lt;/a&gt;.&lt;br /&gt;
&lt;br /&gt;
The example below is for a DecimalUpDown, but you can use it for all kind of fun stuff. In my &lt;a href=&quot;https://github.com/luuksommers/CaliburnAttibuteBinding&quot;&gt;github working example&lt;/a&gt; you can also see a Textbox.&lt;br /&gt;
&lt;br /&gt;
First we need to add an ElementConvention for out DecimalUpDown in the BootStrapper&#39;s Configure method. Override this method and add the following convention (edit 2014-03-26 added attribute check to prevent binding errors):
&lt;br /&gt;
&lt;pre class=&quot;brush:csharp;&quot;&gt;ConventionManager.AddElementConvention&amp;lt;DecimalUpDown&amp;gt;(DecimalUpDown.ValueProperty, &amp;quot;Value&amp;quot;, &amp;quot;ValueChanged&amp;quot;).ApplyBinding =
(viewModelType, path, property, element, convention) =&amp;gt;
{
    if (!ConventionManager.SetBindingWithoutBindingOrValueOverwrite(viewModelType, path, property, element, convention, DecimalUpDown.ValueProperty))
        return false;

    if (property.GetCustomAttributes(typeof (RangeAttribute), true).Any())
    {
        if (!ConventionManager.HasBinding(element, DecimalUpDown.MaximumProperty))
        {
            var binding = new Binding(path) {Mode = BindingMode.OneTime, Converter = RangeMaximumConverter, ConverterParameter = property};
            BindingOperations.SetBinding(element, DecimalUpDown.MaximumProperty, binding);
        }

        if (!ConventionManager.HasBinding(element, DecimalUpDown.MinimumProperty))
        {
            var binding = new Binding(path) {Mode = BindingMode.OneTime, Converter = RangeMinimumConverter, ConverterParameter = property};
            BindingOperations.SetBinding(element, DecimalUpDown.MinimumProperty, binding);
        }
    }

    return true;
};
&lt;/pre&gt;
As you can see the binding uses a RangeMaximumConverter and a RangeMinimumConverter. These are fairly simple with the AttributeConverter baseclass:
&lt;br /&gt;
&lt;pre class=&quot;brush:csharp;&quot;&gt;public sealed class RangeMaximumConverter : AttributeConverter&amp;lt;RangeAttribute&amp;gt;
{
    public override object GetValueFromAttribute(RangeAttribute attribute)
    {
        return attribute.Maximum;
    }
}
&lt;/pre&gt;
And the AttributeConverter base class:
&lt;br /&gt;
&lt;pre class=&quot;brush:csharp;&quot;&gt;public abstract class AttributeConverter&amp;lt;T&amp;gt; : IValueConverter
    where T : Attribute
{
    public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        var property = parameter as PropertyInfo;

        if (property == null)
            return new ArgumentNullException(&quot;parameter&quot;).ToString();

        if (!property.IsDefined(typeof(T), true))
            return new ArgumentOutOfRangeException(&quot;parameter&quot;, parameter,
                &quot;Property \&quot;&quot; + property.Name + &quot;\&quot; has no associated &quot; + typeof(T).Name + &quot; attribute.&quot;).ToString();

        return GetValueFromAttribute((T)property.GetCustomAttributes(typeof(T), true)[0]);
    }

    public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        throw new NotSupportedException();
    }

    public abstract object GetValueFromAttribute(T attribute);
}
&lt;/pre&gt;
You can find a working example in &lt;a href=&quot;https://github.com/luuksommers/CaliburnAttibuteBinding&quot;&gt;GitHub&lt;/a&gt;.&lt;br /&gt;
&lt;br /&gt;
Happy coding,&lt;br /&gt;
Luuk</content><link rel='replies' type='application/atom+xml' href='http://sameproblemmorecode.blogspot.com/feeds/2079014144688851269/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://sameproblemmorecode.blogspot.com/2013/10/bind-wpf-controls-to-attributes-using.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6112035634047142246/posts/default/2079014144688851269'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6112035634047142246/posts/default/2079014144688851269'/><link rel='alternate' type='text/html' href='http://sameproblemmorecode.blogspot.com/2013/10/bind-wpf-controls-to-attributes-using.html' title='Bind WPF controls to attributes using Caliburn Micro'/><author><name>Luuk</name><uri>http://www.blogger.com/profile/17727572272200996660</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6112035634047142246.post-7680466881826211578</id><published>2013-10-17T18:32:00.000+02:00</published><updated>2013-10-17T18:32:24.575+02:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="custom dialog"/><category scheme="http://www.blogger.com/atom/ns#" term="installer"/><category scheme="http://www.blogger.com/atom/ns#" term="msi"/><category scheme="http://www.blogger.com/atom/ns#" term="visual studio"/><category scheme="http://www.blogger.com/atom/ns#" term="windows service"/><category scheme="http://www.blogger.com/atom/ns#" term="wix"/><title type='text'>Using WiX installers the right way</title><content type='html'>Wix is the way to go for creating installers for your visual studio projects. Because Wix is rather complex to start with, I want to give you a working example so you can start building your own installers. You can also skip this short description and go directly to the &lt;a href=&quot;https://github.com/luuksommers/WixInstallerDemo&quot;&gt;source code&lt;/a&gt;.&lt;br /&gt;
&lt;br /&gt;
What we will setup in this post is:&lt;br /&gt;
&lt;ol&gt;
&lt;li&gt;Heat.exe (automatically include your dll files)&lt;/li&gt;
&lt;li&gt;Transformations (automatically edit the file generated by heat.exe)&lt;/li&gt;
&lt;li&gt;Service installers (register your windows service)&lt;/li&gt;
&lt;li&gt;Custom forms (manipulate your config file)&lt;/li&gt;
&lt;/ol&gt;
First off, we need to setup head.exe so it automatically detects when new dll&#39;s are added to your service. To do that, we need to edit the pre-build event:
&lt;br /&gt;
&lt;blockquote&gt;$(WIX)bin\heat.exe&quot; dir &quot;$(SolutionDir)MyWindowsService\$(OutDir).&quot; -srd -sreg -nologo  -scom -srd -sfrag -ag -cg &quot;Binaries&quot; -dr &quot;INSTALLDIR&quot; -t &quot;$(ProjectDir)XslTransform.xslt&quot; -var var.MyWindowsService.TargetDir -o &quot;../../Binaries.wxs&lt;/blockquote&gt;
&lt;br /&gt;
This will generate a &lt;a href=&quot;https://github.com/luuksommers/WixInstallerDemo/blob/master/src/MySetup/Binaries.wxs&quot;&gt;Binaries.wxs&lt;/a&gt; in your installer dir.
&lt;br /&gt;
The next trick is to use transformations to edit the generated file. For example: we want to install a windows service and remove vshost.exe files. This is done with the &lt;a href=&quot;https://github.com/luuksommers/WixInstallerDemo/blob/master/src/MySetup/XslTransform.xslt&quot;&gt;XslTransform.xslt&lt;/a&gt; file.&lt;br /&gt;
&lt;br /&gt;
The following example creates a service:
&lt;pre class=&quot;brush: xml&quot;&gt;&amp;lt;xsl:template match=&amp;quot;wix:Component[wix:File[@Source=&#39;$(var.MyWindowsService.TargetDir)\MyWindowsService.exe&#39;]]&amp;quot;&amp;gt;
 &amp;lt;xsl:copy&amp;gt;
  &amp;lt;xsl:apply-templates select=&amp;quot;node() | @*&amp;quot; /&amp;gt;
  &amp;lt;wix:ServiceInstall Id=&amp;quot;MyServiceInstall&amp;quot; DisplayName=&amp;quot;[SERVICENAME]&amp;quot; Description=&amp;quot;[SERVICENAME]&amp;quot; Name=&amp;quot;[SERVICENAME]&amp;quot; ErrorControl=&amp;quot;ignore&amp;quot; Start=&amp;quot;auto&amp;quot; Type=&amp;quot;ownProcess&amp;quot; Vital=&amp;quot;yes&amp;quot; Interactive=&amp;quot;no&amp;quot; Account=&amp;quot;[SERVICEUSER]&amp;quot; Password=&amp;quot;[SERVICEPSWD]&amp;quot; /&amp;gt;
  &amp;lt;wix:ServiceControl Id=&amp;quot;MyServiceControl&amp;quot; Name=&amp;quot;[SERVICENAME]&amp;quot; Start=&amp;quot;install&amp;quot; Stop=&amp;quot;both&amp;quot; Remove=&amp;quot;uninstall&amp;quot; Wait=&amp;quot;yes&amp;quot;/&amp;gt;
  &amp;lt;util:User Id=&amp;quot;user&amp;quot; CreateUser=&amp;quot;no&amp;quot; Name =&amp;quot;[SERVICEUSER]&amp;quot; Password=&amp;quot;[SERVICEPSWD]&amp;quot; LogonAsService=&amp;quot;yes&amp;quot; /&amp;gt;
 &amp;lt;/xsl:copy&amp;gt;
&amp;lt;/xsl:template&amp;gt;&lt;/pre&gt;After installation, the service is running with the parameters from the product.wxs file.&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjlb2fJYHYUmX_mhTydDQQwKip6xkuJz-qvNYr_GtgIxQD8cvnEMoxQpLMxdVZDh7cOBETHifdv3B2FaBLWDG8bI1f2iO-hNJ0kgOghWq4G4QrWZ2py2zrcueEjPmaLjDqq9RhAenWBvXam/s1600/Services1.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjlb2fJYHYUmX_mhTydDQQwKip6xkuJz-qvNYr_GtgIxQD8cvnEMoxQpLMxdVZDh7cOBETHifdv3B2FaBLWDG8bI1f2iO-hNJ0kgOghWq4G4QrWZ2py2zrcueEjPmaLjDqq9RhAenWBvXam/s320/Services1.png&quot; /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;
The following example manipulates the app.config file:
&lt;pre class=&quot;brush: xml&quot;&gt;&amp;lt;xsl:template match=&amp;quot;wix:Component[wix:File[@Source=&#39;$(var.MyWindowsService.TargetDir)\MyWindowsService.exe.config&#39;]]&amp;quot;&amp;gt;
 &amp;lt;xsl:copy&amp;gt;
  &amp;lt;xsl:apply-templates select=&amp;quot;node() | @*&amp;quot; /&amp;gt;
  &amp;lt;util:XmlFile Id=&amp;quot;AppConfigSetSetting1&amp;quot; File=&amp;quot;[INSTALLDIR]MyWindowsService.exe.config&amp;quot; Action=&amp;quot;setValue&amp;quot; Name=&amp;quot;value&amp;quot; Value=&amp;quot;[SETTING1]&amp;quot; ElementPath=&amp;quot;//configuration/appSettings/add[\[]@key=&#39;setting1&#39;[\]]&amp;quot; Sequence=&amp;quot;1&amp;quot; /&amp;gt;
  &amp;lt;util:XmlFile Id=&amp;quot;AppConfigSetSetting2&amp;quot; File=&amp;quot;[INSTALLDIR]MyWindowsService.exe.config&amp;quot; Action=&amp;quot;setValue&amp;quot; Name=&amp;quot;value&amp;quot; Value=&amp;quot;[SETTING2]&amp;quot; ElementPath=&amp;quot;//configuration/appSettings/add[\[]@key=&#39;setting2&#39;[\]]&amp;quot; Sequence=&amp;quot;1&amp;quot; /&amp;gt;
 &amp;lt;/xsl:copy&amp;gt;
&amp;lt;/xsl:template&amp;gt;&lt;/pre&gt;
Custom forms is a whole different deal. You need to copy code from the original source and add it to your installer. No need to worry, I&#39;ve got a good basic installer flow defined below. It is based on the WixUI_Common template without the license window.
&lt;pre class=&quot;brush: xml&quot;&gt;&amp;lt;Fragment&amp;gt;
 &amp;lt;UI Id=&amp;quot;CustomInstallerUI&amp;quot;&amp;gt;
  &amp;lt;TextStyle Id=&amp;quot;WixUI_Font_Normal&amp;quot; FaceName=&amp;quot;Tahoma&amp;quot; Size=&amp;quot;8&amp;quot; /&amp;gt;
  &amp;lt;TextStyle Id=&amp;quot;WixUI_Font_Bigger&amp;quot; FaceName=&amp;quot;Tahoma&amp;quot; Size=&amp;quot;12&amp;quot; /&amp;gt;
  &amp;lt;TextStyle Id=&amp;quot;WixUI_Font_Title&amp;quot; FaceName=&amp;quot;Tahoma&amp;quot; Size=&amp;quot;9&amp;quot; Bold=&amp;quot;yes&amp;quot; /&amp;gt;

  &amp;lt;Property Id=&amp;quot;DefaultUIFont&amp;quot; Value=&amp;quot;WixUI_Font_Normal&amp;quot; /&amp;gt;
  &amp;lt;Property Id=&amp;quot;WixUI_Mode&amp;quot; Value=&amp;quot;InstallDir&amp;quot; /&amp;gt;

  &amp;lt;DialogRef Id=&amp;quot;SettingsDlg&amp;quot; /&amp;gt;
  &amp;lt;DialogRef Id=&amp;quot;BrowseDlg&amp;quot; /&amp;gt;
  &amp;lt;DialogRef Id=&amp;quot;DiskCostDlg&amp;quot; /&amp;gt;
  &amp;lt;DialogRef Id=&amp;quot;ErrorDlg&amp;quot; /&amp;gt;
  &amp;lt;DialogRef Id=&amp;quot;FatalError&amp;quot; /&amp;gt;
  &amp;lt;DialogRef Id=&amp;quot;FilesInUse&amp;quot; /&amp;gt;
  &amp;lt;DialogRef Id=&amp;quot;MsiRMFilesInUse&amp;quot; /&amp;gt;
  &amp;lt;DialogRef Id=&amp;quot;PrepareDlg&amp;quot; /&amp;gt;
  &amp;lt;DialogRef Id=&amp;quot;ProgressDlg&amp;quot; /&amp;gt;
  &amp;lt;DialogRef Id=&amp;quot;ResumeDlg&amp;quot; /&amp;gt;
  &amp;lt;DialogRef Id=&amp;quot;UserExit&amp;quot; /&amp;gt;

  &amp;lt;Publish Dialog=&amp;quot;BrowseDlg&amp;quot; Control=&amp;quot;OK&amp;quot; Event=&amp;quot;DoAction&amp;quot; Value=&amp;quot;WixUIValidatePath&amp;quot; Order=&amp;quot;3&amp;quot;&amp;gt;1&amp;lt;/Publish&amp;gt;
  &amp;lt;Publish Dialog=&amp;quot;BrowseDlg&amp;quot; Control=&amp;quot;OK&amp;quot; Event=&amp;quot;SpawnDialog&amp;quot; Value=&amp;quot;InvalidDirDlg&amp;quot; Order=&amp;quot;4&amp;quot;&amp;gt;&amp;lt;![CDATA[WIXUI_INSTALLDIR_VALID&amp;lt;&amp;gt;&amp;quot;1&amp;quot;]]&amp;gt;&amp;lt;/Publish&amp;gt;

  &amp;lt;Publish Dialog=&amp;quot;ExitDialog&amp;quot; Control=&amp;quot;Finish&amp;quot; Event=&amp;quot;EndDialog&amp;quot; Value=&amp;quot;Return&amp;quot; Order=&amp;quot;999&amp;quot;&amp;gt;1&amp;lt;/Publish&amp;gt;

  &amp;lt;Publish Dialog=&amp;quot;WelcomeDlg&amp;quot; Control=&amp;quot;Next&amp;quot; Event=&amp;quot;NewDialog&amp;quot; Value=&amp;quot;InstallDirDlg&amp;quot;&amp;gt;NOT Installed&amp;lt;/Publish&amp;gt;
  &amp;lt;Publish Dialog=&amp;quot;WelcomeDlg&amp;quot; Control=&amp;quot;Next&amp;quot; Event=&amp;quot;NewDialog&amp;quot; Value=&amp;quot;VerifyReadyDlg&amp;quot;&amp;gt;Installed AND PATCH&amp;lt;/Publish&amp;gt;

  &amp;lt;Publish Dialog=&amp;quot;InstallDirDlg&amp;quot; Control=&amp;quot;Back&amp;quot; Event=&amp;quot;NewDialog&amp;quot; Value=&amp;quot;WelcomeDlg&amp;quot;&amp;gt;1&amp;lt;/Publish&amp;gt;
  &amp;lt;Publish Dialog=&amp;quot;InstallDirDlg&amp;quot; Control=&amp;quot;Next&amp;quot; Event=&amp;quot;SetTargetPath&amp;quot; Value=&amp;quot;[WIXUI_INSTALLDIR]&amp;quot; Order=&amp;quot;1&amp;quot;&amp;gt;1&amp;lt;/Publish&amp;gt;
  &amp;lt;Publish Dialog=&amp;quot;InstallDirDlg&amp;quot; Control=&amp;quot;Next&amp;quot; Event=&amp;quot;DoAction&amp;quot; Value=&amp;quot;WixUIValidatePath&amp;quot; Order=&amp;quot;2&amp;quot;&amp;gt;NOT WIXUI_DONTVALIDATEPATH&amp;lt;/Publish&amp;gt;
  &amp;lt;Publish Dialog=&amp;quot;InstallDirDlg&amp;quot; Control=&amp;quot;Next&amp;quot; Event=&amp;quot;SpawnDialog&amp;quot; Value=&amp;quot;InvalidDirDlg&amp;quot; Order=&amp;quot;3&amp;quot;&amp;gt;&amp;lt;![CDATA[NOT WIXUI_DONTVALIDATEPATH AND WIXUI_INSTALLDIR_VALID&amp;lt;&amp;gt;&amp;quot;1&amp;quot;]]&amp;gt;&amp;lt;/Publish&amp;gt;
  &amp;lt;Publish Dialog=&amp;quot;InstallDirDlg&amp;quot; Control=&amp;quot;Next&amp;quot; Event=&amp;quot;NewDialog&amp;quot; Value=&amp;quot;SettingsDlg&amp;quot; Order=&amp;quot;4&amp;quot;&amp;gt;WIXUI_DONTVALIDATEPATH OR WIXUI_INSTALLDIR_VALID=&amp;quot;1&amp;quot;&amp;lt;/Publish&amp;gt;
  &amp;lt;Publish Dialog=&amp;quot;InstallDirDlg&amp;quot; Control=&amp;quot;ChangeFolder&amp;quot; Property=&amp;quot;_BrowseProperty&amp;quot; Value=&amp;quot;[WIXUI_INSTALLDIR]&amp;quot; Order=&amp;quot;1&amp;quot;&amp;gt;1&amp;lt;/Publish&amp;gt;
  &amp;lt;Publish Dialog=&amp;quot;InstallDirDlg&amp;quot; Control=&amp;quot;ChangeFolder&amp;quot; Event=&amp;quot;SpawnDialog&amp;quot; Value=&amp;quot;BrowseDlg&amp;quot; Order=&amp;quot;2&amp;quot;&amp;gt;1&amp;lt;/Publish&amp;gt;

  &amp;lt;Publish Dialog=&amp;quot;SettingsDlg&amp;quot; Control=&amp;quot;Back&amp;quot; Event=&amp;quot;NewDialog&amp;quot; Value=&amp;quot;InstallDirDlg&amp;quot;&amp;gt;1&amp;lt;/Publish&amp;gt;
  &amp;lt;Publish Dialog=&amp;quot;SettingsDlg&amp;quot; Control=&amp;quot;Next&amp;quot; Event=&amp;quot;NewDialog&amp;quot; Value=&amp;quot;VerifyReadyDlg&amp;quot;&amp;gt;&amp;lt;/Publish&amp;gt;

  &amp;lt;Publish Dialog=&amp;quot;VerifyReadyDlg&amp;quot; Control=&amp;quot;Back&amp;quot; Event=&amp;quot;NewDialog&amp;quot; Value=&amp;quot;InstallDirDlg&amp;quot; Order=&amp;quot;1&amp;quot;&amp;gt;NOT Installed&amp;lt;/Publish&amp;gt;
  &amp;lt;Publish Dialog=&amp;quot;VerifyReadyDlg&amp;quot; Control=&amp;quot;Back&amp;quot; Event=&amp;quot;NewDialog&amp;quot; Value=&amp;quot;MaintenanceTypeDlg&amp;quot; Order=&amp;quot;2&amp;quot;&amp;gt;Installed AND NOT PATCH&amp;lt;/Publish&amp;gt;
  &amp;lt;Publish Dialog=&amp;quot;VerifyReadyDlg&amp;quot; Control=&amp;quot;Back&amp;quot; Event=&amp;quot;NewDialog&amp;quot; Value=&amp;quot;WelcomeDlg&amp;quot; Order=&amp;quot;2&amp;quot;&amp;gt;Installed AND PATCH&amp;lt;/Publish&amp;gt;

  &amp;lt;Publish Dialog=&amp;quot;MaintenanceWelcomeDlg&amp;quot; Control=&amp;quot;Next&amp;quot; Event=&amp;quot;NewDialog&amp;quot; Value=&amp;quot;MaintenanceTypeDlg&amp;quot;&amp;gt;1&amp;lt;/Publish&amp;gt;

  &amp;lt;Publish Dialog=&amp;quot;MaintenanceTypeDlg&amp;quot; Control=&amp;quot;RepairButton&amp;quot; Event=&amp;quot;NewDialog&amp;quot; Value=&amp;quot;VerifyReadyDlg&amp;quot;&amp;gt;1&amp;lt;/Publish&amp;gt;
  &amp;lt;Publish Dialog=&amp;quot;MaintenanceTypeDlg&amp;quot; Control=&amp;quot;RemoveButton&amp;quot; Event=&amp;quot;NewDialog&amp;quot; Value=&amp;quot;VerifyReadyDlg&amp;quot;&amp;gt;1&amp;lt;/Publish&amp;gt;
  &amp;lt;Publish Dialog=&amp;quot;MaintenanceTypeDlg&amp;quot; Control=&amp;quot;Back&amp;quot; Event=&amp;quot;NewDialog&amp;quot; Value=&amp;quot;MaintenanceWelcomeDlg&amp;quot;&amp;gt;1&amp;lt;/Publish&amp;gt;

  &amp;lt;Property Id=&amp;quot;ARPNOMODIFY&amp;quot; Value=&amp;quot;1&amp;quot; /&amp;gt;
 &amp;lt;/UI&amp;gt;

 &amp;lt;UIRef Id=&amp;quot;WixUI_Common&amp;quot; /&amp;gt;
&amp;lt;/Fragment&amp;gt;&lt;/pre&gt;
The custom &lt;a href=&quot;https://github.com/luuksommers/WixInstallerDemo/blob/master/src/MySetup/SettingsDlg.wxs&quot;&gt;SettingsDlg.wxs&lt;/a&gt; looks like this:&lt;br /&gt;&lt;br /&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEieOTsXM8TWzYCnwnWmWxE9eaAtPRyPtTa3TqvDk35GEo7RaiJ_Rx_vlAKcD7bHOrf8bLLd1u2lkFbGLBNa_SU-gEa78hH0qhKZSqQQVLiHyax9sepoVU0RHqgjx3icK4wTYD_W3EyuNBuT/s1600/Services2.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEieOTsXM8TWzYCnwnWmWxE9eaAtPRyPtTa3TqvDk35GEo7RaiJ_Rx_vlAKcD7bHOrf8bLLd1u2lkFbGLBNa_SU-gEa78hH0qhKZSqQQVLiHyax9sepoVU0RHqgjx3icK4wTYD_W3EyuNBuT/s320/Services2.png&quot; /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;/div&gt;&lt;br /&gt;
Last but not least, to fix &#39;ICE80: This 32BitComponent &#39;&#39; uses 64BitDirectory INSTALLDIR&#39; you can add &#39;-arch x64&#39; to the Compiler parameters in the project properies&#39; Tool Settings.&lt;br /&gt;
The heat.exe searches for all binaries in the output folder. This causes problems with build servers. In TFS2012 you can enable that the build server puts the binaries in seperate folders. I don&#39;t have TFS2012 running so I can&#39;t try this.&lt;br /&gt;
&lt;br /&gt;
Full source is available at GitHub, so you can simply test and edit it yourself: &lt;a href=&quot;https://github.com/luuksommers/WixInstallerDemo&quot;&gt;https://github.com/luuksommers/WixInstallerDemo&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
Sources:&lt;br /&gt;&lt;a href=&quot;http://ahordijk.wordpress.com/2013/03/26/automatically-add-references-and-content-to-the-wix-installer/&quot;&gt;http://ahordijk.wordpress.com/2013/03/26/automatically-add-references-and-content-to-the-wix-installer/&lt;/a&gt;&lt;br /&gt;
&lt;a href=&quot;http://www.chriskonces.com/using-xslt-with-heat-exe-wix-to-create-windows-service-installs/&quot;&gt;http://www.chriskonces.com/using-xslt-with-heat-exe-wix-to-create-windows-service-installs/&lt;/a&gt;&lt;br /&gt;
&lt;a href=&quot;http://kentie.net/article/wixtipstricks/&quot;&gt;http://kentie.net/article/wixtipstricks/&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
Cheers,&lt;br /&gt;
Luuk&lt;br /&gt;
&lt;br /&gt;
PS: Next blog post is also in progress, Caliburn Micro and Attribute binding :) </content><link rel='replies' type='application/atom+xml' href='http://sameproblemmorecode.blogspot.com/feeds/7680466881826211578/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://sameproblemmorecode.blogspot.com/2013/10/using-wix-installers-right-way.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6112035634047142246/posts/default/7680466881826211578'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6112035634047142246/posts/default/7680466881826211578'/><link rel='alternate' type='text/html' href='http://sameproblemmorecode.blogspot.com/2013/10/using-wix-installers-right-way.html' title='Using WiX installers the right way'/><author><name>Luuk</name><uri>http://www.blogger.com/profile/17727572272200996660</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjlb2fJYHYUmX_mhTydDQQwKip6xkuJz-qvNYr_GtgIxQD8cvnEMoxQpLMxdVZDh7cOBETHifdv3B2FaBLWDG8bI1f2iO-hNJ0kgOghWq4G4QrWZ2py2zrcueEjPmaLjDqq9RhAenWBvXam/s72-c/Services1.png" height="72" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6112035634047142246.post-3041896063745554842</id><published>2013-07-14T15:06:00.000+02:00</published><updated>2013-07-14T15:06:09.540+02:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="mapping"/><category scheme="http://www.blogger.com/atom/ns#" term="petapoco"/><category scheme="http://www.blogger.com/atom/ns#" term="repository"/><title type='text'>PetaPoco as it&#39;s meant to be; with repository and fluent mappings</title><content type='html'>When your domain objects get decorated with DataLayer column mappings, you create an unwanted dependency with your DayaLayer. To prevent this, you can create a mapping. This blog describes how I&#39;ve done it. Comments are always welcome in the comment section below. &lt;br /&gt;
&lt;br /&gt;
In the recently updated &lt;a href=&quot;https://github.com/luuksommers/PetaPoco/tree/v5-Informix&quot;&gt;PetaPoco for Informix&lt;/a&gt;, I&#39;ve created a &lt;a href=&quot;https://github.com/luuksommers/PetaPoco/blob/v5-Informix/PetaPoco/Core/FluentMapper.cs&quot;&gt;FluentMapper&lt;/a&gt;. With this you can create a mapping of your domain object, without decorating them.&lt;br /&gt;
&lt;br /&gt;
Here&#39;s how you can also benefit from this seperation. First create the domain object (DO):&lt;br&gt;
&lt;pre class=&quot;brush:c#;&quot;&gt;
public class Customer
{
    public int Id { get; set; }
    public string Name { get; set; }
    public double Revenue { get;set; }
}
&lt;/pre&gt;
Followed by the mapper of the DO
&lt;pre class=&quot;brush:c#;&quot;&gt;
public class CustomerMapper : FluentMapper&amp;lt;Customer&amp;gt;
{
    public CustomerMapper() : base(&amp;quot;tblCustomer&amp;quot;, &amp;quot;CustomerId&amp;quot;)
    {
        this.Property(a=&amp;gt;a.Id, &amp;quot;CustomerId&amp;quot;)
            .Property(a=&amp;gt;a.Name, &amp;quot;CustomerName&amp;quot;)
            .Property(a=&amp;gt;a.Revenue, &amp;quot;Revenue&amp;quot;, fromDbValue=&amp;gt;(int)fromDbValue / 10d, toDbValue =&amp;gt; (int)((double)toDbValue * 10));
    }
}
&lt;/pre&gt;
Once the mapper is in place, we want to make sure we hook it up every time. This is why I make a DataContext class (which is used in the repository):
&lt;pre class=&quot;brush:c#;&quot;&gt;
public class MyDataContext : Database
{
    //Because the PetaPoco.Mappers is static, we also hook up our mappers static
    static MyDataContext()
    {
        PetaPoco.Mappers.Register(typeof(Customer), new CustomerMapper());
    }
    public MyDataContext()
        : base(ConfigurationManager.ConnectionStrings[&amp;quot;MyConnectionString&amp;quot;].ConnectionString))
    {
        
    }
}
&lt;/pre&gt;
Now we can create the repository for the customer related DataLayer functions (CRUD operations):
&lt;pre class=&quot;brush:c#;&quot;&gt;
public class CustomerRepository
{
    private MyDataContext _dataContext
    public CustomerRepository(MyDataContext dataConext)
    {
        _dataContext = dataConext;
    }

    public Customer GetById(int customerId)
    {
        _dataContext.Get&amp;lt;Customer&amp;gt;(customerId);
    }

    public void Update(Customer customer)
    {
        _dataContext.Update(customer);
    }

    // etc
}
&lt;/pre&gt;
We can use it all together in the following way:
&lt;pre class=&quot;brush:c#;&quot;&gt;
using(var dataContext = new MyDataContext())
{
    var customerRepository = new CustomerRepository(dataContext);
    var customer = customerRepository.GetById(1234);
}
&lt;/pre&gt;
As you can see the usage of the repository is super clean. Nobody knows where the data comes from, and nobody cares.&lt;br /&gt;
&lt;br /&gt;
Let me know what you think of this solution!&lt;br /&gt;
&lt;br /&gt;
Cheers,&lt;br /&gt;
Luuk</content><link rel='replies' type='application/atom+xml' href='http://sameproblemmorecode.blogspot.com/feeds/3041896063745554842/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://sameproblemmorecode.blogspot.com/2013/07/petapoco-as-its-meant-to-be-with.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6112035634047142246/posts/default/3041896063745554842'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6112035634047142246/posts/default/3041896063745554842'/><link rel='alternate' type='text/html' href='http://sameproblemmorecode.blogspot.com/2013/07/petapoco-as-its-meant-to-be-with.html' title='PetaPoco as it&#39;s meant to be; with repository and fluent mappings'/><author><name>Luuk</name><uri>http://www.blogger.com/profile/17727572272200996660</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6112035634047142246.post-4016037685334841058</id><published>2013-07-12T11:59:00.000+02:00</published><updated>2013-07-12T11:59:10.898+02:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="informix"/><category scheme="http://www.blogger.com/atom/ns#" term="named parameters"/><category scheme="http://www.blogger.com/atom/ns#" term="orm"/><category scheme="http://www.blogger.com/atom/ns#" term="petapoco"/><title type='text'>Introducing PetaPoco for Informix</title><content type='html'>I&#39;ve created a fork of &lt;a href=&quot;https://github.com/toptensoftware/PetaPoco&quot;&gt;PetaPoco&lt;/a&gt;, with support for Informix and named parameters. I&#39;ve also added multiple key support.&lt;br /&gt;
&lt;br /&gt;
The code is available on &lt;a href=&quot;https://github.com/luuksommers/PetaPoco/tree/v5-Informix&quot;&gt;GitHub&lt;/a&gt;.&lt;br /&gt;
&lt;br /&gt;
An example:
&lt;br /&gt;
&lt;pre class=&quot;brush:c#;&quot;&gt;[TableName(&quot;ship&quot;)]
public class Ship
{
    [PrimaryKey]
    [Column(&quot;shipid&quot;)]
    public int Id { get; set; }

    [Column(&quot;name&quot;)]
    public string Name { get; set; }
}

[TableName(&quot;positionlog&quot;)]
public class PositionLog
{
    [PrimaryKey]
    [Column(&quot;shipid&quot;)]
    public int ShipId { get; set; }

    [PrimaryKey]
    [Column(&quot;epochdate&quot;)]
    public int EpochDate { get; set; }

    [Column(&quot;lat&quot;)]
    public int Latitude {get;set;}

    [Column(&quot;lon&quot;)]
    public int Longitude {get;set;}
}

var db = new Database(new IfxConnection(&quot;&amp;lt;ConnectionString&amp;gt;&quot;);
int shipId = 1234;
var ship = db.Query&amp;lt;Ship&amp;gt;(&quot;select first 1 * from ship where shipid = @id&quot;, new { id = shipId }).FirstOrDefault();

ship.Name = &quot;Submarine&quot;;

db.Update(ship);
&lt;/pre&gt;
&lt;br /&gt;
The code will be updated with support of more features as we move along with our project (which uses Informix).&lt;br /&gt;
&lt;br /&gt;
Cheers,&lt;br /&gt;
Luuk</content><link rel='replies' type='application/atom+xml' href='http://sameproblemmorecode.blogspot.com/feeds/4016037685334841058/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://sameproblemmorecode.blogspot.com/2013/07/introducing-petapoco-for-informix.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6112035634047142246/posts/default/4016037685334841058'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6112035634047142246/posts/default/4016037685334841058'/><link rel='alternate' type='text/html' href='http://sameproblemmorecode.blogspot.com/2013/07/introducing-petapoco-for-informix.html' title='Introducing PetaPoco for Informix'/><author><name>Luuk</name><uri>http://www.blogger.com/profile/17727572272200996660</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6112035634047142246.post-444221153300947307</id><published>2013-07-01T21:11:00.001+02:00</published><updated>2013-07-03T12:32:37.237+02:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="e-mail"/><category scheme="http://www.blogger.com/atom/ns#" term="interop"/><category scheme="http://www.blogger.com/atom/ns#" term="outlook"/><title type='text'>Looping through your e-mails with outlook interop with c#</title><content type='html'>Last week we needed a small tool that checked the body of an e-mail. I found out that it only takes a couple of lines using Outlook Interop to do so. Super fast, super easy:&lt;br /&gt;
&lt;pre class=&quot;brush:csharp;&quot;&gt;using System;
using Microsoft.Office.Interop.Outlook;

namespace OutlookReader
{
    class Program
    {
        static void Main(string[] args)
        {
            Microsoft.Office.Interop.Outlook.Application app = null;
            Microsoft.Office.Interop.Outlook._NameSpace ns = null;
            Microsoft.Office.Interop.Outlook.MailItem item = null;
            Microsoft.Office.Interop.Outlook.MAPIFolder inboxFolder = null;
            Microsoft.Office.Interop.Outlook.MAPIFolder subFolder = null;

            try
            {
                app = new Application();
                ns = app.GetNamespace(&quot;MAPI&quot;);
                ns.Logon(null, null, false, false);

                inboxFolder = ns.GetDefaultFolder(Microsoft.Office.Interop.Outlook.OlDefaultFolders.olFolderInbox);
                subFolder = inboxFolder; // or use folder.Folders[&quot;Folder Name&quot;];

                Console.WriteLine(&quot;Folder Name: {0}, EntryId: {1}&quot;, subFolder.Name, subFolder.EntryID);
                Console.WriteLine(&quot;Num Items: {0}&quot;, subFolder.Items.Count.ToString());

                for (int i = 1; i &amp;lt;= subFolder.Items.Count; i++)
                {
                    item = (MailItem)subFolder.Items[i];
                    Console.WriteLine(&quot;Subject: {0}&quot;, item.Subject);
                }
            }
            catch (System.Runtime.InteropServices.COMException ex)
            {
                Console.WriteLine(ex.ToString());
            }
            finally
            {
                ns = null;
                app = null;
                inboxFolder = null;
            }
        }
    }
}
&lt;/pre&gt;
This only works with outlook installed, so if you want to use it on your server, you&#39;ll have to install outlook. Does anybody know any other good way to access mail without the native MAPI32?&lt;br /&gt;
&lt;br /&gt;
Cheers,&lt;br /&gt;
Luuk</content><link rel='replies' type='application/atom+xml' href='http://sameproblemmorecode.blogspot.com/feeds/444221153300947307/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://sameproblemmorecode.blogspot.com/2013/07/looping-through-your-e-mails-with.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6112035634047142246/posts/default/444221153300947307'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6112035634047142246/posts/default/444221153300947307'/><link rel='alternate' type='text/html' href='http://sameproblemmorecode.blogspot.com/2013/07/looping-through-your-e-mails-with.html' title='Looping through your e-mails with outlook interop with c#'/><author><name>Luuk</name><uri>http://www.blogger.com/profile/17727572272200996660</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6112035634047142246.post-2829346589339050006</id><published>2013-06-04T14:38:00.003+02:00</published><updated>2013-06-04T14:38:46.270+02:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="beyond compare"/><category scheme="http://www.blogger.com/atom/ns#" term="source control"/><category scheme="http://www.blogger.com/atom/ns#" term="TFS"/><title type='text'>Beyond Compare is Beyond Awesome with Source Control Integration</title><content type='html'>Just found out the Source Control Integration with Beyond Compare Pro, this is awesome! First install the &lt;a href=&quot;http://www.scootersoftware.com/support.php?zz=kb_scc_tfs&quot;&gt;TFS &amp;nbsp;SCC provider&lt;/a&gt;&amp;nbsp;and click on Tools -&amp;gt; Source Controls Integration.&lt;br /&gt;
&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgztlkWYA5_1uCTF3C15zZ6VEKsl5LcY4JJ1_ApjMrDZMQLQtFYDQOPL-pYEXN6WGL4m6YmCttY2owfj-fBrrCSV38tplXf3huBKsbwEK39K0P4ARep7oQXBS1t-Hgn-PLgLkCNDxGKnHkU/s1600/Source+Control+Integration.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;250&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgztlkWYA5_1uCTF3C15zZ6VEKsl5LcY4JJ1_ApjMrDZMQLQtFYDQOPL-pYEXN6WGL4m6YmCttY2owfj-fBrrCSV38tplXf3huBKsbwEK39K0P4ARep7oQXBS1t-Hgn-PLgLkCNDxGKnHkU/s320/Source+Control+Integration.png&quot; width=&quot;320&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
Now see a window where you can add the same folders as your mapped TFS workspaces. But when you now start to compare, merge or edit a file which is checked in, you get the following popup:&lt;br /&gt;
&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgTq8WdW6D7RQv9aaKbQjFGkU1LmRW9I5jxUurn78Rt_TSUhGIZ0ZmXTH4cXgmQEKo8rQo0RnJjuW4ruZcDynnoRyHJuvhU2mM-M3BsB1uRlpnm4vzNud0T5_O0FuQuyabNIp1-9vT3oVzp/s1600/Source+Control+Integration+Confirm.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;50&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgTq8WdW6D7RQv9aaKbQjFGkU1LmRW9I5jxUurn78Rt_TSUhGIZ0ZmXTH4cXgmQEKo8rQo0RnJjuW4ruZcDynnoRyHJuvhU2mM-M3BsB1uRlpnm4vzNud0T5_O0FuQuyabNIp1-9vT3oVzp/s320/Source+Control+Integration+Confirm.png&quot; width=&quot;320&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
Nice, isn&#39;t it? So now you don&#39;t have to go to VS to checkout the item manually and this works a lot faster!&lt;br /&gt;
&lt;br /&gt;
Cheers,&lt;br /&gt;
Luuk</content><link rel='replies' type='application/atom+xml' href='http://sameproblemmorecode.blogspot.com/feeds/2829346589339050006/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://sameproblemmorecode.blogspot.com/2013/06/beyond-compare-is-beyond-awesome-with.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6112035634047142246/posts/default/2829346589339050006'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6112035634047142246/posts/default/2829346589339050006'/><link rel='alternate' type='text/html' href='http://sameproblemmorecode.blogspot.com/2013/06/beyond-compare-is-beyond-awesome-with.html' title='Beyond Compare is Beyond Awesome with Source Control Integration'/><author><name>Luuk</name><uri>http://www.blogger.com/profile/17727572272200996660</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgztlkWYA5_1uCTF3C15zZ6VEKsl5LcY4JJ1_ApjMrDZMQLQtFYDQOPL-pYEXN6WGL4m6YmCttY2owfj-fBrrCSV38tplXf3huBKsbwEK39K0P4ARep7oQXBS1t-Hgn-PLgLkCNDxGKnHkU/s72-c/Source+Control+Integration.png" height="72" width="72"/><thr:total>0</thr:total></entry></feed>