<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
  <title>mozzy.dev</title>
	<subtitle></subtitle>
	<link href="https://mozzy.dev/feed.xml" rel="self"/>
	<link href="https://mozzy.dev/"/>
	<updated>2012-02-06T00:00:00+00:00</updated>
	<id>https://mozzy.dev</id>
	<author>
  <name>Thomas Morris</name>
  <email>hello@tcmorris.net</email>
	</author>
	
  
  <entry>
    <title>Umbraco Codegarden 2023</title>
    <link href="https://mozzy.dev/posts/umbraco-codegarden-2023/"/>
    <updated>2023-08-01T00:00:00+00:00</updated>
    <id>https://mozzy.dev/posts/umbraco-codegarden-2023/</id>
    <content type="html"><![CDATA[
      <p>I wrote an article for <a href="https://www.tpximpact.com/">TPXimpact</a> about my experience at Umbraco Codegarden 2023.</p>
<blockquote>
<p>Recently, a couple of our team had the opportunity to attend the annual Umbraco conference known as <a href="https://codegarden.umbraco.com/">Codegarden</a>. Hosted in Odense, Denmark it pulls together 800+ in person to the event, but also a number of people were able to attend online as a hybrid experience.</p>
</blockquote>
<p>Read in full here: <a href="https://www.tpximpact.com/knowledge-hub/blogs/tech/umbraco-codegarden-2023/">Umbraco Codegarden 2023</a></p>

    ]]></content>
  </entry>
	
  
  <entry>
    <title>Unboxing Umbraco 11</title>
    <link href="https://mozzy.dev/posts/umbraco-11/"/>
    <updated>2023-02-07T00:00:00+00:00</updated>
    <id>https://mozzy.dev/posts/umbraco-11/</id>
    <content type="html"><![CDATA[
      <p>I wrote an article for <a href="https://www.tpximpact.com/">TPXimpact</a> about Umbraco 11.</p>
<blockquote>
<p>Not too long ago we reviewed Umbraco 9, calling it a significant milestone and a major step up from prior versions of Umbraco. In this article we’d like to share our thoughts on Umbraco 11 and see if it’s worth the upgrade.</p>
</blockquote>
<p>Read in full here: <a href="https://www.tpximpact.com/knowledge-hub/blogs/tech/umbraco-11-features/">Umbraco 11</a></p>

    ]]></content>
  </entry>
	
  
  <entry>
    <title>Looking back at 2022</title>
    <link href="https://mozzy.dev/posts/looking-back-at-2022/"/>
    <updated>2023-01-03T00:00:00+00:00</updated>
    <id>https://mozzy.dev/posts/looking-back-at-2022/</id>
    <content type="html"><![CDATA[
      <p>As I start 2023, in typical fashion you start to think about the year ahead, what kind of things to get excited for and to perhaps introduce. I've even written about this in the past. However, this year I'm thinking it'd be useful to look back and see what I have achieved in the hope that it provides me the bliss from constantly searching to what's next.</p>
<p>From a work perspective, there's been a few highlights.</p>
<ul>
<li>Got promoted to Technical Lead</li>
<li>Launched various new Umbraco websites</li>
<li>Taken on hosting for our internal tech talks</li>
<li>Rekindled umBristol and getting involved with the community</li>
</ul>
<p>From a personal point of view, there's been some big changes.</p>
<ul>
<li>Started some renovation of our 1930s house</li>
<li>Elliot joined our world</li>
<li>Proposed to Hayley, my wonderful partner (she said yes)</li>
</ul>
<p>And that's good enough for me. Dream big, but let's cherish and celebrate too.</p>

    ]]></content>
  </entry>
	
  
  <entry>
    <title>Umbraco 9 - The latest major version from Umbraco</title>
    <link href="https://mozzy.dev/posts/umbraco-9-latest-major/"/>
    <updated>2021-12-02T00:00:00+00:00</updated>
    <id>https://mozzy.dev/posts/umbraco-9-latest-major/</id>
    <content type="html"><![CDATA[
      <p>I wrote an article for <a href="https://www.tpximpact.com/">TPXimpact</a> about Umbraco 9.</p>
<blockquote>
<p>As of Sept 2021, Umbraco is now a fully-fledged .NET 5 (ASP.NET Core) CMS. A significant milestone, which brings a multitude of new features and benefits.</p>
</blockquote>
<p>Read in full here: <a href="https://www.tpximpact.com/knowledge-hub/insights/umbraco-9/">Umbraco 9: The latest major version from Umbraco</a></p>

    ]]></content>
  </entry>
	
  
  <entry>
    <title>Breaking down Umbraco</title>
    <link href="https://mozzy.dev/posts/breaking-down-umbraco/"/>
    <updated>2021-03-16T00:00:00+00:00</updated>
    <id>https://mozzy.dev/posts/breaking-down-umbraco/</id>
    <content type="html"><![CDATA[
      <p>I wrote an article for <a href="https://www.tpximpact.com/">TPXimpact</a> about why you might choose Umbraco for a project.</p>
<blockquote>
<p>Umbraco’s benefits are many. Using technologies we’re already familiar with, the CMS allows our solutions to achieve a breadth of functionality and remain malleable post production.</p>
</blockquote>
<p>Read in full here: <a href="https://www.tpximpact.com/knowledge-hub/insights/breaking-down-umbraco/">Breaking down Umbraco</a></p>

    ]]></content>
  </entry>
	
  
  <entry>
    <title>GitHub Actions</title>
    <link href="https://mozzy.dev/posts/github-actions/"/>
    <updated>2020-08-19T00:00:00+00:00</updated>
    <id>https://mozzy.dev/posts/github-actions/</id>
    <content type="html"><![CDATA[
      <p>There are quite a few build and deploy options available to developers these days. Previously, I have wrote about using a combination of <a href="http://mozzy.dev/posts/continuous-delivery-for-dotnet-revisited/">Team City and Octopus Deploy</a>. These are still good tools, but will likely require a bit of setup and probably require a VM.</p>
<p>A more recent trend is to have your actions linked to your repository, where you can have it all self contained and in one place. There are pros and cons to both, but I'm gonna show you how you might do that with GitHub Actions.</p>
<h2>dotnet</h2>
<p>I work mostly with .NET, so lets take a look at the workflow for that. With .NET Core you can now use Linux (and macOS) as your build target. Here we're using <code>ubuntu-latest</code>.</p>
<p>We're also setting the relevant <code>DOTNET_VERSION</code> and running our commands, <code>dotnet build</code> and <code>dotnet publish</code>. Problems with the build will be visible within GitHub and you can follow along with the progress.</p>
<p>Finally, we're pushing our published version of the app to Azure Web Apps using a publish profile. You could also choose to generate a NuGet package and push to a feed for distribution.</p>
<script src="https://gist.github.com/tcmorris/dada56a630316670a064882a2753f04f.js"></script>
<p>Note, you can also build <a href="https://github.com/Azure-Samples/dotnet-sample/blob/master/.github/workflows/aspnet.yml">.NET Framework apps</a>, that will look a little different but the concept is the same. You'll target <code>windows-latest</code> as that is a prerequisite for .NET Framework, and the commands will be <code>msbuild</code>.</p>
<h2>node.js</h2>
<p>If you've got a FE repo, then you'll likely want to use npm to compile some assets and package them up. Here's how you can do that.</p>
<p>We've set up our <code>NODE_VERSION</code> and then run the commands, <code>npm install</code> and <code>npm build</code>. At that point, we might want to package up the assets or deploy as an application.</p>
<script src="https://gist.github.com/tcmorris/a779e0c62f9db194b7a15bdef0ec696e.js"></script>
<h2>other</h2>
<p>There are lots of other options available to you, without going into all of them here, I encourage you to take a look through the <a href="https://docs.github.com/en/actions/language-and-framework-guides">docs</a> and see what you might want for your needs.</p>
<p>If you're interested in what's installed on the runners, then take a look at <a href="https://github.com/actions/virtual-environments">this repo</a> which contains the full list of software and spec for each.</p>
<p>The approach here can also be used for similar tools such as <a href="https://bitbucket.org/product/features/pipelines">Bitbucket Pipelines</a> or <a href="https://azure.microsoft.com/en-us/services/devops/pipelines/">Azure Pipelines</a>. Choose what fits the bill for you.</p>
<p>Have fun!</p>

    ]]></content>
  </entry>
	
  
  <entry>
    <title>Building a bottle shop</title>
    <link href="https://mozzy.dev/posts/custom-store-in-umbraco/"/>
    <updated>2020-08-10T00:00:00+00:00</updated>
    <id>https://mozzy.dev/posts/custom-store-in-umbraco/</id>
    <content type="html"><![CDATA[
      <p>One of the things that is important to an ecommerce experience is the speed at which you can make informed decisions and place items in your cart. From there, the next phase will be to checkout and proceed with the order. Typically, this is classed as a conversion and you want as many as possible. You might do various tests to achieve that end goal and nudge the customer along that path.</p>
<p>What if you were open to the idea of not pushing the customer to checkout immediately and provide them time to make their choices, even over a few weeks. This was a concept that we played with at <a href="https://beerbods.co.uk/">BeerBods</a>, centred around a reservation of beer, to build a case of beers you pick in your own time. The experience itself is more about exploration and finding the beer you want.</p>
<p>Not only does that shift the UX in a slightly different direction, it also has some technical challenges. Namely, how do you reserve a beer, how is this stock controlled and how do I come back to my continue with my purchase.</p>
<img src="/images/buildacase-concept.jpg" title="Build a Case - concept" />
<h2>Introducing Umbraco</h2>
<p><a href="https://umbraco.com/">Umbraco</a> as a CMS allows for a lot of variation in terms of document types and property editors. Essentially, you can build a custom editing interface relatively easily to manage your content. In my case, I wanted to add products to Umbraco and have these editable by anyone in the team. There was no data warehouse, so adding directly into Umbraco was ok in this scenario. I was able to define the required information and set up some basic stock control with SKUs and pricing. Since we were already using Umbraco, it was comfortable to use on this front.</p>
<p>The product pages themselves can be rendered using traditional patterns and templates. The more interesting part came when adding the functionality to add a beer to your case.</p>
<h2>Enter VueJS and Algolia</h2>
<p><a href="https://vuejs.org/">VueJS</a> is a javascript framework that allows for building SPA (single page applications) like functionality, introducing more dynamic and responsive user interfaces. It can be added with relative ease to an existing website, which made it a good option for building our 'shop' front. VueJS would be responsible for rendering components, handling FE state and making calls to our API.</p>
<p><a href="https://www.algolia.com/">Algolia</a> is a search platform that has a number of pre-built components to integrate with it's service. There was one of particular interest that near enough provided the basis for our <a href="https://www.algolia.com/doc/guides/building-search-ui/widgets/showcase/vue/">'shop'</a> and the required functionality. This included a list of results, options to filter, sort and search. The idea of adding this kind of service had a number of benefits, it was quick to get started and by having an external service handling search powered by a CDN, it was very responsive to customers. We could push data to the service (whenever a product was updated) and query the results wherever we needed.</p>
<p>Combined, we were able to build a UI that was quick to load, easy to filter and visually interesting with a lot of customisation options. All of the API calls would be triggered from the FE and the state would update our UI to present back to the user.</p>
<h2>Adding Fluidity</h2>
<p>So, we've got our products and our UI for the front end. We now need to persist changes and provide a stateful system for the current user. This was done by implementing custom database tables and an API to enable adding items, removing items and saving these items for a later date.</p>
<p>These custom database tables can be exposed in our Umbraco instance by using a package called <a href="https://github.com/mattbrailsford/umbraco-fluidity/">Fluidity</a>. It provides a CRUD like experience for the editors so that we can see what's being added and when, as well as allowing us to add beers on the behalf of a customer.</p>
<p>It's important to note that the idea of persistance is 2-fold, once when we are on the FE and we need to ensure state between sessions and also on the BE, where we need to actually store the data and reserve the beer. This distinction means that we don't get people adding multiple beers filling up stock until they commit to saving that data. At which point we've got their details and can follow up if necessary.</p>
<p>When it comes to purchase or if the customer comes back to their choices, we can load these from the API and allow the customer to proceed. The items can be locked in and an order can be made just like any other checkout, allowing the next stage of fulfilment in the warehouse.</p>
<p>If the customer didn't come back (which did happen), then we'd prompt them to finish their case via email. If after the 30 days they hadn't made a purchase, then we would need to remove their reservation and put the beers back into the shop for other customers. This was done by using <a href="https://www.hangfire.io/">Hangfire</a>, a tool for running background tasks at desired times.</p>
<h2>The result</h2>
<p>What we were looking for was a responsive, easy to use 'shop' front for customers to pick beer and save until they were ready to make a purchase. We needed the ability to add beers to our shop and view details about what was in progress or had been ordered. By using a combination of Umbraco on the back end, and VueJS / Algolia on the front end, the result turned out how we wanted it to and we saw great customer interaction.</p>
<p><em>Note: This functionality is no longer live on the website but you can view the <a href="https://beerbods.co.uk/blog/introducing-buildacase/">introductory blog post</a>.</em></p>

    ]]></content>
  </entry>
	
  
  <entry>
    <title>Remote working</title>
    <link href="https://mozzy.dev/posts/remote-working/"/>
    <updated>2020-03-09T00:00:00+00:00</updated>
    <id>https://mozzy.dev/posts/remote-working/</id>
    <content type="html"><![CDATA[
      <p>For the past couple of years I've been working in a mostly remote position. There are a lot of positives, but it's important to know that it's not for everyone and it does come with it's own challenges that you'll need to think about.</p>
<p>Here's a few things that I've noticed can help. Your experiences may/will be different.</p>
<h2>Tips on remote working</h2>
<p>Keep in <strong>regular contact</strong> with your fellow workers. Provide updates to the team about your progress. Discuss using online tools for greater visibility of decisions made. It helps provide context and allows for further input as necessary. This works both ways.</p>
<p>Use face to face meetings via video. If there are multiple people joining at the other end, use a proper meeting room with <strong>good a/v equipment</strong>. Holding a laptop with others joining is not a positive experience and leaves people feeling less involved. Not everything needs a call. Embrace async communication.</p>
<p>You will at times feel isolated and need human interaction. Go to places that encourage this and create a <strong>different environment</strong>. This can be a shared office, coworking space or local coffee shop. When you know you need to focus, you'll welcome the solitude.</p>
<p>Try and work to <strong>your own schedule</strong>. Take a longer lunch if it helps you be more effective at what you do. If you need to go and do something, then do it and work around it. Define check in times and availability to your coworkers. This is not about being unavailable, it's about managing your time better.</p>
<p>Replace your commute with something for yourself. Go for a walk with the dog, cycle round the block, or grab a coffee from your local. It will help kickstart the day and allow your mind to <strong>seperate home from work</strong>. Likewise, wearing your pjs all day whilst comfortable is an easy way to laze about.</p>
<p><strong>Invest in your space</strong>. Ideally you'll have somewhere that is a place for you, with a decent set of equipment and lighting. Working in a common room within your house/flat will likely make it harder to concentrate and may lead to distractions.</p>
<p>If your company has to emphasize the fact you need to <em>work</em> whilst you are at home, then they probably don't trust you to do any work or are at least unfamiliar with the concept. <strong>Don't overcompensate</strong> by doing more work, just alleviate concern with what you are doing.</p>
<p>If you want to do more work because you're in the zone or whatever, by all means do so, just remember to take some <strong>time out and recharge</strong>.</p>
<p>Take notes and provide a plan of what you'll be working on. This can be as simple as you like. Working to a few <strong>bullet points and targets</strong> will add extra focus and satisfaction when complete.</p>
<p>Spend time with your <strong>family, friends and significant others</strong>. It can be really easy to slip into constantly thinking about work and failing to relax with the people around you. Enjoy life outside of work.</p>
<p><strong>Hopefully these tips will put you on the right path to remote working bliss.</strong></p>

    ]]></content>
  </entry>
	
  
  <entry>
    <title>Mediatr and CQRS</title>
    <link href="https://mozzy.dev/posts/mediatr-and-cqrs/"/>
    <updated>2020-01-30T00:00:00+00:00</updated>
    <id>https://mozzy.dev/posts/mediatr-and-cqrs/</id>
    <content type="html"><![CDATA[
      <h2>Introducing new changes</h2>
<p>To begin, I think it would be useful to go over a scenario that I'm sure many people have come across before and why perhaps it would be useful to look into an alternative.</p>
<p>Let's say we've got a bunch of beers and we've allowed our users to see them along with their basic details and an option to buy. When someone is interested in that beer, they might want to know whether or not this beer is any good. It'd be great if we could allow our users to review a beer.</p>
<p>When using the repository pattern we would have created a new repository, passed that into a service and called that service from within our controller to return the reviews and allow our users to review a beer. We will have likely used the same model for our read and write. This works and you carry on as normal happy that users can now add some extra context to beers.</p>
<pre class="language-csharp"><code class="language-csharp"><span class="highlight-line"><span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">BeerReviewService</span></span><br><span class="highlight-line"><span class="token punctuation">{</span></span><br><span class="highlight-line">    <span class="token keyword">private</span> <span class="token keyword">readonly</span> <span class="token return-type class-name">Database</span> _db <span class="token operator">=></span> ApplicationContext<span class="token punctuation">.</span>Current<span class="token punctuation">.</span>DatabaseContext<span class="token punctuation">.</span>Database<span class="token punctuation">;</span></span><br><span class="highlight-line"></span><br><span class="highlight-line">    <span class="token keyword">public</span> <span class="token return-type class-name"><span class="token keyword">void</span></span> <span class="token function">Create</span><span class="token punctuation">(</span><span class="token class-name">BeerReview</span> beerReview<span class="token punctuation">)</span></span><br><span class="highlight-line">    <span class="token punctuation">{</span></span><br><span class="highlight-line">        _db<span class="token punctuation">.</span><span class="token function">Insert</span><span class="token punctuation">(</span>beerReview<span class="token punctuation">)</span><span class="token punctuation">;</span></span><br><span class="highlight-line">    <span class="token punctuation">}</span></span><br><span class="highlight-line"></span><br><span class="highlight-line">    <span class="token keyword">public</span> <span class="token return-type class-name">IList<span class="token punctuation">&lt;</span>BeerReview<span class="token punctuation">></span></span> <span class="token function">GetAllReviews</span><span class="token punctuation">(</span><span class="token punctuation">)</span></span><br><span class="highlight-line">    <span class="token punctuation">{</span></span><br><span class="highlight-line">        <span class="token keyword">return</span> _db<span class="token punctuation">.</span><span class="token generic-method"><span class="token function">Fetch</span><span class="token generic class-name"><span class="token punctuation">&lt;</span>BeerReview<span class="token punctuation">></span></span></span><span class="token punctuation">(</span><span class="token string">"SELECT * FROM BeerReviews"</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span><br><span class="highlight-line">    <span class="token punctuation">}</span></span><br><span class="highlight-line"></span><br><span class="highlight-line">    <span class="token keyword">public</span> <span class="token return-type class-name">IList<span class="token punctuation">&lt;</span>BeerReview<span class="token punctuation">></span></span> <span class="token function">GetReviewsByBeerId</span><span class="token punctuation">(</span><span class="token class-name"><span class="token keyword">int</span></span> beerId<span class="token punctuation">)</span></span><br><span class="highlight-line">    <span class="token punctuation">{</span></span><br><span class="highlight-line">        <span class="token keyword">return</span> _db<span class="token punctuation">.</span><span class="token generic-method"><span class="token function">Fetch</span><span class="token generic class-name"><span class="token punctuation">&lt;</span>BeerReview<span class="token punctuation">></span></span></span><span class="token punctuation">(</span><span class="token string">"SELECT * FROM BeerReviews WHERE BeerId = @0"</span><span class="token punctuation">,</span> beerId<span class="token punctuation">)</span><span class="token punctuation">;</span></span><br><span class="highlight-line">    <span class="token punctuation">}</span></span><br><span class="highlight-line"><span class="token punctuation">}</span></span></code></pre>
<p>A couple weeks later, someone has started taking advantage of this rating option and posted a bunch of fake reviews. You need to delete them. Something that when you first built your service, the functionality wasn't required and for good reason didn't add it in just for the hell of it. Except that now, you need to make a change to your rating service by adding some more code. A couple more weeks, and people are asking to edit those reviews as they've added some typos. You need to introduce edit functionality and the rating service grows some more. Whilst we've now got some honest reviews, not everyone agrees with them and we'd like to allow people to upvote a review to show appreciation for how good a review is. Again, we need to go back to our rating service. This can go on and on and soon enough the original code that you wrote bares little resemblance to the intentions of what was supposedly a simple implementation. The contract itself has completely shifted.</p>
<pre class="language-csharp"><code class="language-csharp"><span class="highlight-line"><span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">BeerReviewService</span></span><br><span class="highlight-line"><span class="token punctuation">{</span></span><br><span class="highlight-line">    <span class="token keyword">private</span> <span class="token keyword">readonly</span> <span class="token return-type class-name">Database</span> _db <span class="token operator">=></span> ApplicationContext<span class="token punctuation">.</span>Current<span class="token punctuation">.</span>DatabaseContext<span class="token punctuation">.</span>Database<span class="token punctuation">;</span></span><br><span class="highlight-line"></span><br><span class="highlight-line">    <span class="token keyword">public</span> <span class="token return-type class-name"><span class="token keyword">void</span></span> <span class="token function">Create</span><span class="token punctuation">(</span><span class="token class-name">BeerReview</span> beerReview<span class="token punctuation">)</span></span><br><span class="highlight-line">    <span class="token punctuation">{</span></span><br><span class="highlight-line">        _db<span class="token punctuation">.</span><span class="token function">Insert</span><span class="token punctuation">(</span>beerReview<span class="token punctuation">)</span><span class="token punctuation">;</span></span><br><span class="highlight-line">    <span class="token punctuation">}</span></span><br><span class="highlight-line"></span><br><span class="highlight-line">    <span class="token keyword">public</span> <span class="token return-type class-name"><span class="token keyword">void</span></span> <span class="token function">Edit</span><span class="token punctuation">(</span><span class="token class-name">BeerReview</span> beerReview<span class="token punctuation">)</span></span><br><span class="highlight-line">    <span class="token punctuation">{</span></span><br><span class="highlight-line">        _db<span class="token punctuation">.</span><span class="token function">Save</span><span class="token punctuation">(</span>beerReview<span class="token punctuation">)</span><span class="token punctuation">;</span></span><br><span class="highlight-line">    <span class="token punctuation">}</span></span><br><span class="highlight-line"></span><br><span class="highlight-line">    <span class="token keyword">public</span> <span class="token return-type class-name"><span class="token keyword">void</span></span> <span class="token function">Upvote</span><span class="token punctuation">(</span><span class="token class-name"><span class="token keyword">int</span></span> reviewId<span class="token punctuation">)</span></span><br><span class="highlight-line">    <span class="token punctuation">{</span></span><br><span class="highlight-line">        <span class="token class-name"><span class="token keyword">var</span></span> beerReview <span class="token operator">=</span> <span class="token function">GetReviewById</span><span class="token punctuation">(</span>reviewId<span class="token punctuation">)</span><span class="token punctuation">;</span></span><br><span class="highlight-line">        <span class="token keyword">if</span> <span class="token punctuation">(</span>beerReview <span class="token operator">==</span> <span class="token keyword">null</span><span class="token punctuation">)</span></span><br><span class="highlight-line">        <span class="token punctuation">{</span></span><br><span class="highlight-line">            <span class="token keyword">return</span><span class="token punctuation">;</span></span><br><span class="highlight-line">        <span class="token punctuation">}</span></span><br><span class="highlight-line"></span><br><span class="highlight-line">        beerReview<span class="token punctuation">.</span>UpVotes <span class="token operator">+=</span> <span class="token number">1</span><span class="token punctuation">;</span></span><br><span class="highlight-line">        _db<span class="token punctuation">.</span><span class="token function">Save</span><span class="token punctuation">(</span>beerReview<span class="token punctuation">)</span><span class="token punctuation">;</span></span><br><span class="highlight-line">    <span class="token punctuation">}</span></span><br><span class="highlight-line"></span><br><span class="highlight-line">    <span class="token keyword">public</span> <span class="token return-type class-name"><span class="token keyword">void</span></span> <span class="token function">Delete</span><span class="token punctuation">(</span><span class="token class-name">BeerReview</span> beerReview<span class="token punctuation">)</span></span><br><span class="highlight-line">    <span class="token punctuation">{</span></span><br><span class="highlight-line">        <span class="token keyword">if</span> <span class="token punctuation">(</span>beerReview <span class="token operator">==</span> <span class="token keyword">null</span><span class="token punctuation">)</span></span><br><span class="highlight-line">        <span class="token punctuation">{</span></span><br><span class="highlight-line">            <span class="token keyword">return</span><span class="token punctuation">;</span></span><br><span class="highlight-line">        <span class="token punctuation">}</span></span><br><span class="highlight-line">        _db<span class="token punctuation">.</span><span class="token function">Delete</span><span class="token punctuation">(</span>beerReview<span class="token punctuation">)</span><span class="token punctuation">;</span></span><br><span class="highlight-line">    <span class="token punctuation">}</span></span><br><span class="highlight-line"></span><br><span class="highlight-line">    <span class="token keyword">public</span> <span class="token return-type class-name">IList<span class="token punctuation">&lt;</span>BeerReview<span class="token punctuation">></span></span> <span class="token function">GetAllReviews</span><span class="token punctuation">(</span><span class="token punctuation">)</span></span><br><span class="highlight-line">    <span class="token punctuation">{</span></span><br><span class="highlight-line">        <span class="token keyword">return</span> _db<span class="token punctuation">.</span><span class="token generic-method"><span class="token function">Fetch</span><span class="token generic class-name"><span class="token punctuation">&lt;</span>BeerReview<span class="token punctuation">></span></span></span><span class="token punctuation">(</span><span class="token string">"SELECT * FROM BeerReviews"</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span><br><span class="highlight-line">    <span class="token punctuation">}</span></span><br><span class="highlight-line"></span><br><span class="highlight-line">    <span class="token keyword">public</span> <span class="token return-type class-name">IList<span class="token punctuation">&lt;</span>BeerReview<span class="token punctuation">></span></span> <span class="token function">GetReviewsByBeerId</span><span class="token punctuation">(</span><span class="token class-name"><span class="token keyword">int</span></span> beerId<span class="token punctuation">)</span></span><br><span class="highlight-line">    <span class="token punctuation">{</span></span><br><span class="highlight-line">        <span class="token keyword">return</span> _db<span class="token punctuation">.</span><span class="token generic-method"><span class="token function">Fetch</span><span class="token generic class-name"><span class="token punctuation">&lt;</span>BeerReview<span class="token punctuation">></span></span></span><span class="token punctuation">(</span><span class="token string">"SELECT * FROM BeerReviews WHERE BeerId = @0"</span><span class="token punctuation">,</span> beerId<span class="token punctuation">)</span><span class="token punctuation">;</span></span><br><span class="highlight-line">    <span class="token punctuation">}</span></span><br><span class="highlight-line"></span><br><span class="highlight-line">    <span class="token keyword">public</span> <span class="token return-type class-name">IList<span class="token punctuation">&lt;</span>BeerReview<span class="token punctuation">></span></span> <span class="token function">GetReviewsByUserId</span><span class="token punctuation">(</span><span class="token class-name"><span class="token keyword">int</span></span> userId<span class="token punctuation">)</span></span><br><span class="highlight-line">    <span class="token punctuation">{</span></span><br><span class="highlight-line">        <span class="token keyword">return</span> _db<span class="token punctuation">.</span><span class="token generic-method"><span class="token function">Fetch</span><span class="token generic class-name"><span class="token punctuation">&lt;</span>BeerReview<span class="token punctuation">></span></span></span><span class="token punctuation">(</span><span class="token string">"SELECT * FROM BeerReviews WHERE UserId = @0"</span><span class="token punctuation">,</span> userId<span class="token punctuation">)</span><span class="token punctuation">;</span></span><br><span class="highlight-line">    <span class="token punctuation">}</span></span><br><span class="highlight-line"></span><br><span class="highlight-line">    <span class="token keyword">public</span> <span class="token return-type class-name">BeerReview</span> <span class="token function">GetReviewById</span><span class="token punctuation">(</span><span class="token class-name"><span class="token keyword">int</span></span> reviewId<span class="token punctuation">)</span></span><br><span class="highlight-line">    <span class="token punctuation">{</span></span><br><span class="highlight-line">        <span class="token keyword">return</span> _db<span class="token punctuation">.</span><span class="token generic-method"><span class="token function">FirstOrDefault</span><span class="token generic class-name"><span class="token punctuation">&lt;</span>BeerReview<span class="token punctuation">></span></span></span><span class="token punctuation">(</span><span class="token string">"SELECT * FROM BeerReviews WHERE ReviewId = @0"</span><span class="token punctuation">,</span> reviewId<span class="token punctuation">)</span><span class="token punctuation">;</span></span><br><span class="highlight-line">    <span class="token punctuation">}</span></span><br><span class="highlight-line"><span class="token punctuation">}</span></span></code></pre>
<h2>How about CQRS?</h2>
<p>Taking a look at our reviews example, there were a few things we ended up wanting to do, but essentially we can split those into something that modifies something, or something that retrieves something.</p>
<p><a href="https://docs.microsoft.com/en-us/azure/architecture/patterns/cqrs">CQRS</a> or Command Query Responsibility Segregation in it's full name, is a pattern that separates command logic from query logic. If you need to make an update or create an entity, you would use a command. If you need to query for some data, you would create a query. By following this pattern, it can help with the Single Responsibility Principle. No longer are you likely to have a service or such like that combines both update and retrieval, providing a better separation of concerns. GraphQL has a <a href="https://graphql.org/learn/queries/">similar concept</a>, you can either <code>query</code> data or you can apply a <code>mutation</code> to change data.</p>
<p>One of the benefits of this is that the code itself should be self documentating. The name itself should provide all you need to know. For example, <code>CreateBeerReviewCommand</code> will as one might assume, create a review for a beer.</p>
<pre class="language-csharp"><code class="language-csharp"><span class="highlight-line"><span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">CreateBeerReviewCommand</span> <span class="token punctuation">:</span> <span class="token type-list"><span class="token class-name">IRequest<span class="token punctuation">&lt;</span><span class="token keyword">int</span><span class="token punctuation">></span></span></span></span><br><span class="highlight-line"><span class="token punctuation">{</span></span><br><span class="highlight-line">    <span class="token keyword">public</span> <span class="token return-type class-name"><span class="token keyword">int</span></span> BeerId <span class="token punctuation">{</span> <span class="token keyword">get</span><span class="token punctuation">;</span> <span class="token keyword">set</span><span class="token punctuation">;</span> <span class="token punctuation">}</span></span><br><span class="highlight-line">    <span class="token keyword">public</span> <span class="token return-type class-name"><span class="token keyword">int</span></span> UserId <span class="token punctuation">{</span> <span class="token keyword">get</span><span class="token punctuation">;</span> <span class="token keyword">set</span><span class="token punctuation">;</span> <span class="token punctuation">}</span></span><br><span class="highlight-line">    <span class="token keyword">public</span> <span class="token return-type class-name"><span class="token keyword">string</span></span> Review <span class="token punctuation">{</span> <span class="token keyword">get</span><span class="token punctuation">;</span> <span class="token keyword">set</span><span class="token punctuation">;</span> <span class="token punctuation">}</span></span><br><span class="highlight-line"><span class="token punctuation">}</span></span></code></pre>
<p>As for a query, likewise the naming convention should be self explanatory. <code>GetBeerReviewsQuery</code> in order to fetch a collection of reviews for a beer. Things have suddenly become a lot more descriptive and relate better to their function.</p>
<pre class="language-csharp"><code class="language-csharp"><span class="highlight-line"><span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">GetBeerReviewsQuery</span> <span class="token punctuation">:</span> <span class="token type-list"><span class="token class-name">IRequest<span class="token punctuation">&lt;</span>BeerReviewsModel<span class="token punctuation">></span></span></span></span><br><span class="highlight-line"><span class="token punctuation">{</span></span><br><span class="highlight-line">    <span class="token keyword">public</span> <span class="token return-type class-name"><span class="token keyword">int</span></span> BeerId <span class="token punctuation">{</span> <span class="token keyword">get</span><span class="token punctuation">;</span> <span class="token keyword">set</span><span class="token punctuation">;</span> <span class="token punctuation">}</span></span><br><span class="highlight-line"><span class="token punctuation">}</span></span></code></pre>
<p>Once you've got a command or a query, you need to handle that request. One way to do that, is to create a new handler which mimics the naming convention of your command (or query). So, you will have a <code>CreateBeerReviewCommand</code> and a <code>CreateBeerReviewHandler</code> which will perform any necessary logic (i.e. create a beer review) and return a response. You define the expected response, so in the <code>CreateBeerReviewHandler</code> we will return the id of the newly created review for example.</p>
<pre class="language-csharp"><code class="language-csharp"><span class="highlight-line"><span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">CreateBeerReviewHandler</span> <span class="token punctuation">:</span> <span class="token type-list"><span class="token class-name">IRequestHandler<span class="token punctuation">&lt;</span>CreateBeerReviewCommand<span class="token punctuation">,</span> <span class="token keyword">int</span><span class="token punctuation">></span></span></span></span><br><span class="highlight-line"><span class="token punctuation">{</span></span><br><span class="highlight-line">    <span class="token keyword">private</span> <span class="token keyword">readonly</span> <span class="token return-type class-name">Database</span> _db <span class="token operator">=></span> ApplicationContext<span class="token punctuation">.</span>Current<span class="token punctuation">.</span>DatabaseContext<span class="token punctuation">.</span>Database<span class="token punctuation">;</span></span><br><span class="highlight-line"></span><br><span class="highlight-line">    <span class="token keyword">public</span> <span class="token return-type class-name"><span class="token keyword">int</span></span> <span class="token function">Handle</span><span class="token punctuation">(</span><span class="token class-name">CreateBeerReviewCommand</span> request<span class="token punctuation">)</span></span><br><span class="highlight-line">    <span class="token punctuation">{</span></span><br><span class="highlight-line">        <span class="token class-name"><span class="token keyword">var</span></span> beerReview <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token constructor-invocation class-name">BeerReview</span><span class="token punctuation">(</span><span class="token punctuation">)</span></span><br><span class="highlight-line">        <span class="token punctuation">{</span></span><br><span class="highlight-line">            BeerId <span class="token operator">=</span> request<span class="token punctuation">.</span>BeerId<span class="token punctuation">,</span></span><br><span class="highlight-line">            UserId <span class="token operator">=</span> request<span class="token punctuation">.</span>UserId<span class="token punctuation">,</span></span><br><span class="highlight-line">            Review <span class="token operator">=</span> request<span class="token punctuation">.</span>Review<span class="token punctuation">,</span></span><br><span class="highlight-line">            LastUpdated <span class="token operator">=</span> DateTime<span class="token punctuation">.</span>Now</span><br><span class="highlight-line">        <span class="token punctuation">}</span><span class="token punctuation">;</span></span><br><span class="highlight-line">        _db<span class="token punctuation">.</span><span class="token function">Save</span><span class="token punctuation">(</span>beerReview<span class="token punctuation">)</span><span class="token punctuation">;</span></span><br><span class="highlight-line"></span><br><span class="highlight-line">        <span class="token keyword">return</span> beerReview<span class="token punctuation">.</span>ReviewId<span class="token punctuation">;</span></span><br><span class="highlight-line">    <span class="token punctuation">}</span></span><br><span class="highlight-line"><span class="token punctuation">}</span></span></code></pre>
<h2>An example</h2>
<p>If we go back to our earlier example, when asked to allow users to edit their reviews, we can implement a new <code>EditBeerReviewCommand</code> with it's own handler and it's own logic.</p>
<pre class="language-csharp"><code class="language-csharp"><span class="highlight-line"><span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">EditBeerReviewCommand</span> <span class="token punctuation">:</span> <span class="token type-list"><span class="token class-name">IRequest</span></span></span><br><span class="highlight-line"><span class="token punctuation">{</span></span><br><span class="highlight-line">    <span class="token keyword">public</span> <span class="token return-type class-name"><span class="token keyword">int</span></span> ReviewId <span class="token punctuation">{</span> <span class="token keyword">get</span><span class="token punctuation">;</span> <span class="token keyword">set</span><span class="token punctuation">;</span> <span class="token punctuation">}</span></span><br><span class="highlight-line">    <span class="token keyword">public</span> <span class="token return-type class-name"><span class="token keyword">string</span></span> Review <span class="token punctuation">{</span> <span class="token keyword">get</span><span class="token punctuation">;</span> <span class="token keyword">set</span><span class="token punctuation">;</span> <span class="token punctuation">}</span></span><br><span class="highlight-line"><span class="token punctuation">}</span></span><br><span class="highlight-line"></span><br><span class="highlight-line"><span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">EditBeerReviewHandler</span> <span class="token punctuation">:</span> <span class="token type-list"><span class="token class-name">IRequestHandler<span class="token punctuation">&lt;</span>EditBeerReviewCommand<span class="token punctuation">></span></span></span></span><br><span class="highlight-line"><span class="token punctuation">{</span></span><br><span class="highlight-line">    <span class="token keyword">private</span> <span class="token keyword">readonly</span> <span class="token return-type class-name">Database</span> _db <span class="token operator">=></span> ApplicationContext<span class="token punctuation">.</span>Current<span class="token punctuation">.</span>DatabaseContext<span class="token punctuation">.</span>Database<span class="token punctuation">;</span></span><br><span class="highlight-line"></span><br><span class="highlight-line">    <span class="token keyword">public</span> <span class="token return-type class-name"><span class="token keyword">void</span></span> <span class="token function">Handle</span><span class="token punctuation">(</span><span class="token class-name">EditBeerReviewCommand</span> request<span class="token punctuation">)</span></span><br><span class="highlight-line">    <span class="token punctuation">{</span></span><br><span class="highlight-line">        <span class="token class-name"><span class="token keyword">var</span></span> beerReview <span class="token operator">=</span> _db<span class="token punctuation">.</span><span class="token function">GetById</span><span class="token punctuation">(</span>request<span class="token punctuation">.</span>ReviewId<span class="token punctuation">)</span><span class="token punctuation">;</span></span><br><span class="highlight-line">        <span class="token keyword">if</span> <span class="token punctuation">(</span>beerReview <span class="token operator">!=</span> <span class="token keyword">null</span><span class="token punctuation">)</span></span><br><span class="highlight-line">        <span class="token punctuation">{</span></span><br><span class="highlight-line">            beerReview<span class="token punctuation">.</span>Review <span class="token operator">=</span> request<span class="token punctuation">.</span>Review<span class="token punctuation">;</span></span><br><span class="highlight-line">            beerReview<span class="token punctuation">.</span>LastUpdated <span class="token operator">=</span> DateTime<span class="token punctuation">.</span>Now<span class="token punctuation">;</span></span><br><span class="highlight-line">            _db<span class="token punctuation">.</span><span class="token function">Save</span><span class="token punctuation">(</span>beerReview<span class="token punctuation">)</span><span class="token punctuation">;</span></span><br><span class="highlight-line">        <span class="token punctuation">}</span></span><br><span class="highlight-line">    <span class="token punctuation">}</span></span><br><span class="highlight-line"><span class="token punctuation">}</span></span></code></pre>
<p>You'll notice that the code being used to edit a beer review only needs to reference the review id and provide the newly updated review itself. The models in this sense are a lot smaller than passing around a DB model, and they are created to perform a particular task. You do end up with more, but hopefully you can see the benefit in doing so.</p>
<p>Now, you might be thinking we've got a ton of classes going on here and I'm going to have a lot of dependencies in my controller to achieve all of this. You need to ensure the right commands/queries are going to the right handlers, it would be good to have something that could help mediate these dependencies. Luckily there is a Nuget package out there that makes things a bit simpler. Enter <strong>Mediatr</strong> by Jimmy Bogard (of AutoMapper fame).</p>
<p><a href="https://github.com/jbogard/MediatR">Mediatr</a> is a package that helps link up the relevant commands/queries to the correct handlers. This means that we can simplify our controllers to use an instance of <code>IMediatr</code>, which we'll then use to send our request to get the relevant response. In the example below, we've got a beer page and we're getting the reviews for that beer by creating a new <code>GetBeerReviewsQuery</code>.</p>
<pre class="language-csharp"><code class="language-csharp"><span class="highlight-line"><span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">BeerController</span> <span class="token punctuation">:</span> <span class="token type-list"><span class="token class-name">Controller</span></span></span><br><span class="highlight-line"><span class="token punctuation">{</span></span><br><span class="highlight-line">    <span class="token keyword">private</span> <span class="token keyword">readonly</span> <span class="token class-name">IMediator</span> _mediatr<span class="token punctuation">;</span></span><br><span class="highlight-line"></span><br><span class="highlight-line">    <span class="token keyword">public</span> <span class="token function">BeerController</span><span class="token punctuation">(</span><span class="token class-name">IMediator</span> mediatr<span class="token punctuation">)</span></span><br><span class="highlight-line">    <span class="token punctuation">{</span></span><br><span class="highlight-line">        _mediatr <span class="token operator">=</span> mediatr<span class="token punctuation">;</span></span><br><span class="highlight-line">    <span class="token punctuation">}</span></span><br><span class="highlight-line"></span><br><span class="highlight-line">    <span class="token keyword">public</span> <span class="token return-type class-name">IActionResult</span> <span class="token function">Index</span><span class="token punctuation">(</span><span class="token punctuation">)</span></span><br><span class="highlight-line">    <span class="token punctuation">{</span></span><br><span class="highlight-line">        <span class="token class-name"><span class="token keyword">var</span></span> beerId <span class="token operator">=</span> <span class="token number">1234</span><span class="token punctuation">;</span></span><br><span class="highlight-line">        <span class="token class-name"><span class="token keyword">var</span></span> model <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token constructor-invocation class-name">BeerViewModel</span></span><br><span class="highlight-line">        <span class="token punctuation">{</span></span><br><span class="highlight-line">            BeerId <span class="token operator">=</span> beerId<span class="token punctuation">,</span></span><br><span class="highlight-line">            Name <span class="token operator">=</span> <span class="token string">"My beer"</span><span class="token punctuation">,</span></span><br><span class="highlight-line">            Description <span class="token operator">=</span> <span class="token string">"My awesome pale ale"</span><span class="token punctuation">,</span></span><br><span class="highlight-line">            Price <span class="token operator">=</span> <span class="token number">2.99m</span><span class="token punctuation">,</span></span><br><span class="highlight-line">            Reviews <span class="token operator">=</span> _mediatr<span class="token punctuation">.</span><span class="token function">Send</span><span class="token punctuation">(</span><span class="token keyword">new</span> <span class="token constructor-invocation class-name">GetBeerReviewsQuery</span> <span class="token punctuation">{</span> BeerId <span class="token operator">=</span> beerId <span class="token punctuation">}</span><span class="token punctuation">)</span></span><br><span class="highlight-line">        <span class="token punctuation">}</span><span class="token punctuation">;</span></span><br><span class="highlight-line"></span><br><span class="highlight-line">        <span class="token keyword">return</span> <span class="token function">View</span><span class="token punctuation">(</span>model<span class="token punctuation">)</span><span class="token punctuation">;</span></span><br><span class="highlight-line">    <span class="token punctuation">}</span></span><br><span class="highlight-line"><span class="token punctuation">}</span></span></code></pre>
<p>In this scenario we've isolated the code to get reviews relating to a beer and we're loading them our handler for <code>GetBeerReviewsQuery</code>. It'll look something like this.</p>
<pre class="language-csharp"><code class="language-csharp"><span class="highlight-line"><span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">GetBeerReviewsHandler</span> <span class="token punctuation">:</span> <span class="token type-list"><span class="token class-name">IRequestHandler<span class="token punctuation">&lt;</span>GetBeerReviewsQuery<span class="token punctuation">,</span> BeerReviewsModel<span class="token punctuation">></span></span></span></span><br><span class="highlight-line"><span class="token punctuation">{</span></span><br><span class="highlight-line">    <span class="token keyword">private</span> <span class="token keyword">readonly</span> <span class="token return-type class-name">Database</span> _db <span class="token operator">=></span> ApplicationContext<span class="token punctuation">.</span>Current<span class="token punctuation">.</span>DatabaseContext<span class="token punctuation">.</span>Database<span class="token punctuation">;</span></span><br><span class="highlight-line"></span><br><span class="highlight-line">    <span class="token keyword">public</span> <span class="token return-type class-name">BeerReviewsModel</span> <span class="token function">Handle</span><span class="token punctuation">(</span><span class="token class-name">GetBeerReviewsQuery</span> request<span class="token punctuation">)</span></span><br><span class="highlight-line">    <span class="token punctuation">{</span></span><br><span class="highlight-line">        <span class="token class-name"><span class="token keyword">var</span></span> reviews <span class="token operator">=</span> _db<span class="token punctuation">.</span><span class="token generic-method"><span class="token function">Fetch</span><span class="token generic class-name"><span class="token punctuation">&lt;</span>BeerReview<span class="token punctuation">></span></span></span><span class="token punctuation">(</span><span class="token string">"SELECT * FROM BeerReviews WHERE BeerId = @0"</span><span class="token punctuation">,</span> request<span class="token punctuation">.</span>BeerId<span class="token punctuation">)</span><span class="token punctuation">;</span></span><br><span class="highlight-line">        <span class="token class-name"><span class="token keyword">var</span></span> response <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token constructor-invocation class-name">BeerReviewsModel</span><span class="token punctuation">(</span><span class="token punctuation">)</span></span><br><span class="highlight-line">        <span class="token punctuation">{</span></span><br><span class="highlight-line">            Reviews <span class="token operator">=</span> reviews<span class="token punctuation">,</span></span><br><span class="highlight-line">            Count <span class="token operator">=</span> reviews<span class="token punctuation">.</span>Count<span class="token punctuation">,</span></span><br><span class="highlight-line">            LastUpdated <span class="token operator">=</span> DateTime<span class="token punctuation">.</span>Now</span><br><span class="highlight-line">        <span class="token punctuation">}</span><span class="token punctuation">;</span>        </span><br><span class="highlight-line"></span><br><span class="highlight-line">        <span class="token keyword">return</span> response<span class="token punctuation">;</span></span><br><span class="highlight-line">    <span class="token punctuation">}</span></span><br><span class="highlight-line"><span class="token punctuation">}</span></span></code></pre>
<h2>Vertical Slices</h2>
<p>Now that we've split our application more closely into commands and queries relating to specific tasks, it might be a good idea to group those tasks together somehow. This technique involves organising your project into vertical slices rather than by type. i.e. we can define features and split them into verticals. You can keep code relating to beer reviews as one slice of your application, rather than simply having controllers, services, models and so on with a combination of multiple domains. When you need to modify the beer reviews code, you know where to find it and the relating code is positioned together as one piece. You may wish to use different projects or release as different features in a microservices architecture, in which case this idea would help with providing updates in isolation. From a testing point of view, the easier to read and smaller classes should help resulting in code that should be more maintainable as the project grows.</p>
<h2>Going further</h2>
<p>The examples provided here are relatively basic to show the concepts and how you might work with this pattern, however in a typical world you'll also need to think and caching, validation, logging and various other steps in the pipeline. Thankfully, Mediatr has the concept of pipelines and adding behaviours, so you can run code before or after handlers. I'll leave that for another time.</p>
<h3>References</h3>
<ul>
<li><a href="https://codeopinion.com/fat-controller-cqrs-diet/">https://codeopinion.com/fat-controller-cqrs-diet/</a></li>
<li><a href="https://medium.com/@dbottiau/a-naive-introduction-to-cqrs-in-c-9d0d99cd2d54">https://medium.com/@dbottiau/a-naive-introduction-to-cqrs-in-c-9d0d99cd2d54</a></li>
<li><a href="https://www.stevejgordon.co.uk/cqrs-using-mediatr-asp-net-core">https://www.stevejgordon.co.uk/cqrs-using-mediatr-asp-net-core</a></li>
</ul>

    ]]></content>
  </entry>
	
  
  <entry>
    <title>Enabling features in production</title>
    <link href="https://mozzy.dev/posts/enabling-features-in-production/"/>
    <updated>2019-12-18T00:00:00+00:00</updated>
    <id>https://mozzy.dev/posts/enabling-features-in-production/</id>
    <content type="html"><![CDATA[
      <p><strong>Note: this article was written for 24days in Umbraco and the original can be found here: <a href="https://24days.in/umbraco-cms/2019/features-in-production/">https://24days.in/umbraco-cms/2019/features-in-production/</a></strong></p>
<p>When deploying features or new changes to our websites, we might not want them to be available to all users at once. It would be nice if we could slowly introduce new features to our users. We might even want to completely disable them and have them there in secret. In this article, I'm going to present a few different ways in which you can release features into production, even when they might not be fully complete.</p>
<h2>Background</h2>
<p>Before we look into the ways in which we can get our features into production, it's useful to think about how we might have typically developed new changes in our website before a release.</p>
<p>One of the most common ways is to use feature branches in a <a href="https://www.atlassian.com/git/tutorials/comparing-workflows/gitflow-workflow">gitflow scenario</a>, where you would build your new feature, deploy to a test environment and then try and merge those changes with anything else that has changed in the meantime. You'll probably bundle a number of changes together and then release those to production.</p>
<p>Some of the issues at this stage might be that you've got a tricky merge, you've tested something in isolation and when you bring it all together other issues might arise. You also haven't really trialled those changes with actual users, so those changes may not be desired or there could be problems with how it all works.</p>
<h2>Benefits and options</h2>
<p>Therefore, it's probably a good idea to highlight some of the benefits as to why you might want to integrate your new changes sooner rather than later.</p>
<ul>
<li>your features get into production quicker</li>
<li>you can get feedback earlier</li>
<li>you can test things in reduced quantities</li>
<li>you should end up with a better product</li>
<li>your client will be happy</li>
</ul>
<p>You might have seen reasons like this elsewhere, and that's because they actually run true for agile development and the scrum process, which in turn is a good fit for <a href="https://continuousdelivery.com/">continuous delivery</a>. A notion that your app is always in a deliverable state, since any new changes have been safely integrated somehow.</p>
<p>On to the ways in which we can enable our changes...</p>
<h3>App settings</h3>
<p>One of the easiest ways is to define in your web.config, application settings somewhere, or provide settings in your Umbraco solution to features on and off. You'll need to check this setting within your code before including the new changes for your users.</p>
<p>This can be done with a feature helper, which you can query the app setting and then return a true or false as to whether the new changes should be included or not.</p>
<pre class="language-csharp"><code class="language-csharp"><span class="highlight-line"><span class="token keyword">public</span> <span class="token keyword">static</span> <span class="token keyword">class</span> <span class="token class-name">FeatureHelper</span></span><br><span class="highlight-line"><span class="token punctuation">{</span></span><br><span class="highlight-line">    <span class="token keyword">public</span> <span class="token keyword">static</span> <span class="token return-type class-name"><span class="token keyword">bool</span></span> <span class="token function">IsFeatureEnabled</span><span class="token punctuation">(</span><span class="token class-name"><span class="token keyword">string</span></span> featureFlag<span class="token punctuation">)</span></span><br><span class="highlight-line">    <span class="token punctuation">{</span></span><br><span class="highlight-line">        <span class="token comment">// check if we have enabled functionality via web.config</span></span><br><span class="highlight-line">        <span class="token keyword">bool</span><span class="token punctuation">.</span><span class="token function">TryParse</span><span class="token punctuation">(</span>ConfigurationManager<span class="token punctuation">.</span>AppSettings<span class="token punctuation">.</span><span class="token function">Get</span><span class="token punctuation">(</span>featureFlag<span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token keyword">out</span> <span class="token class-name"><span class="token keyword">var</span></span> setting<span class="token punctuation">)</span><span class="token punctuation">;</span></span><br><span class="highlight-line">        <span class="token keyword">return</span> setting<span class="token punctuation">;</span></span><br><span class="highlight-line">    <span class="token punctuation">}</span></span><br><span class="highlight-line"><span class="token punctuation">}</span></span></code></pre>
<p>If you'd like to turn off entire controllers or action methods, one of the ways in which you can do that is via the use of <a href="https://docs.microsoft.com/en-us/aspnet/mvc/overview/older-versions-1/controllers-and-routing/understanding-action-filters-cs">attributes</a>. These will decorate your actions and apply the filter before any of the other code is run. In the attribute logic, it will call our feature helper to determine whether or not a feature should be applied.</p>
<pre class="language-csharp"><code class="language-csharp"><span class="highlight-line"><span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">FeatureAttribute</span> <span class="token punctuation">:</span> <span class="token type-list"><span class="token class-name">ActionFilterAttribute</span></span></span><br><span class="highlight-line"><span class="token punctuation">{</span></span><br><span class="highlight-line">    <span class="token keyword">public</span> <span class="token return-type class-name"><span class="token keyword">string</span></span> ConfigVariable <span class="token punctuation">{</span> <span class="token keyword">get</span><span class="token punctuation">;</span> <span class="token keyword">set</span><span class="token punctuation">;</span> <span class="token punctuation">}</span>        </span><br><span class="highlight-line">    </span><br><span class="highlight-line">    <span class="token keyword">public</span> <span class="token function">FeatureAttribute</span><span class="token punctuation">(</span><span class="token class-name"><span class="token keyword">string</span></span> configVariable<span class="token punctuation">)</span></span><br><span class="highlight-line">    <span class="token punctuation">{</span></span><br><span class="highlight-line">        ConfigVariable <span class="token operator">=</span> configVariable<span class="token punctuation">;</span>        </span><br><span class="highlight-line">    <span class="token punctuation">}</span></span><br><span class="highlight-line"></span><br><span class="highlight-line">    <span class="token keyword">public</span> <span class="token keyword">override</span> <span class="token return-type class-name"><span class="token keyword">void</span></span> <span class="token function">OnActionExecuting</span><span class="token punctuation">(</span><span class="token class-name">ActionExecutingContext</span> filterContext<span class="token punctuation">)</span></span><br><span class="highlight-line">    <span class="token punctuation">{</span></span><br><span class="highlight-line">        <span class="token comment">// if the feature is not enabled, then redirect to 404</span></span><br><span class="highlight-line">        <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token operator">!</span>FeatureHelper<span class="token punctuation">.</span><span class="token function">IsFeatureEnabled</span><span class="token punctuation">(</span>ConfigVariable<span class="token punctuation">)</span><span class="token punctuation">)</span></span><br><span class="highlight-line">        <span class="token punctuation">{</span></span><br><span class="highlight-line">            filterContext<span class="token punctuation">.</span>HttpContext<span class="token punctuation">.</span>Response<span class="token punctuation">.</span><span class="token function">Redirect</span><span class="token punctuation">(</span><span class="token string">"/404/"</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span><br><span class="highlight-line">        <span class="token punctuation">}</span></span><br><span class="highlight-line">        <span class="token keyword">else</span></span><br><span class="highlight-line">        <span class="token punctuation">{</span></span><br><span class="highlight-line">            <span class="token keyword">base</span><span class="token punctuation">.</span><span class="token function">OnActionExecuting</span><span class="token punctuation">(</span>filterContext<span class="token punctuation">)</span><span class="token punctuation">;</span></span><br><span class="highlight-line">        <span class="token punctuation">}</span></span><br><span class="highlight-line">    <span class="token punctuation">}</span></span><br><span class="highlight-line"><span class="token punctuation">}</span></span></code></pre>
<p>This allows for features to be controlled relatively easy in terms of when it is available, but it's an all or nothing solution which might not be desired when you want to tentatively introduce customers to your new feature.</p>
<h3>Session</h3>
<p>We can apply changes based on a user's session data, which could be enabled via a campaign to help with testing. Ask for people to click a link and become part of the session. You can then trigger an update that will kill off any session data if there are issues. The code above that we used for checking app setting can be amended to apply with session data.</p>
<pre class="language-csharp"><code class="language-csharp"><span class="highlight-line"><span class="token keyword">public</span> <span class="token keyword">static</span> <span class="token keyword">class</span> <span class="token class-name">FeatureHelper</span></span><br><span class="highlight-line"><span class="token punctuation">{</span></span><br><span class="highlight-line">    <span class="token keyword">public</span> <span class="token keyword">static</span> <span class="token return-type class-name"><span class="token keyword">bool</span></span> <span class="token function">IsFeatureEnabled</span><span class="token punctuation">(</span><span class="token class-name"><span class="token keyword">string</span></span> sessionFlag<span class="token punctuation">)</span></span><br><span class="highlight-line">    <span class="token punctuation">{</span></span><br><span class="highlight-line">        <span class="token comment">// check if we have a valid session to enable functionality</span></span><br><span class="highlight-line">        <span class="token class-name"><span class="token keyword">var</span></span> sessionVar <span class="token operator">=</span> HttpContext<span class="token punctuation">.</span>Current<span class="token punctuation">?.</span>Session<span class="token punctuation">[</span>sessionFlag<span class="token punctuation">]</span><span class="token punctuation">;</span></span><br><span class="highlight-line">        <span class="token keyword">if</span> <span class="token punctuation">(</span>sessionVar <span class="token operator">==</span> <span class="token keyword">null</span><span class="token punctuation">)</span></span><br><span class="highlight-line">        <span class="token punctuation">{</span></span><br><span class="highlight-line">            <span class="token keyword">return</span> <span class="token boolean">false</span><span class="token punctuation">;</span></span><br><span class="highlight-line">        <span class="token punctuation">}</span></span><br><span class="highlight-line"></span><br><span class="highlight-line">        <span class="token keyword">return</span> <span class="token keyword">bool</span><span class="token punctuation">.</span><span class="token function">Parse</span><span class="token punctuation">(</span>sessionVar<span class="token punctuation">.</span><span class="token function">ToString</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span><br><span class="highlight-line">    <span class="token punctuation">}</span></span><br><span class="highlight-line"><span class="token punctuation">}</span></span></code></pre>
<p>This is great for ad hoc testing, as everything can return to normal after the session. This is ideal if you don't have an account system set up, but it is helpful if you can target or segment your users if you have a hypothesis you want to test.</p>
<p>A/B testing would be a good scenario here. One set of users could get the feature enabled and the other set could continue as normal to see if anything is improved if your feature relates to performance or conversions. It's important that you can define what improvement looks like or can at least get some feedback from your users.</p>
<h3>User preference</h3>
<p>If you do have an account section, you could provide the user the choice as to whether they want to opt in to a newly released feature that you might want to test further before enabling for all. You would need to check against the current logged in user as to whether or not they would like to see those changes.</p>
<p>In Umbraco, you could define this as a member property or <a href="https://our.umbraco.com/Documentation/Getting-Started/Data/Members/#creating-member-groups">membership group</a> so you can see within the backoffice which users have enabled your feature and segment your users that way. If your changes are more granular, then using properties is probably preferred.</p>
<p><em>Just to note, for members in Umbraco there is the concept of role based access, which is tied with membership groups, so could be an option if you wanted to hook in that way instead. This uses .NET authorisation under the hood.</em></p>
<p><img src="/images/umbraco-membership-features.png" alt="Umbraco member properties" title="Image with list of features that can be enabled for an Umbraco member"></p>
<p>This puts the control on to your users, and they are more likely to be actively engaged with a feature and also understand that there may be issues. If they're not happy with how it works, then they can easily opt back out and carry on as normal. Within your website, you can provide an option for feedback based on whether a new feature has been turned on. They can submit reports and you can gain some quality insight as to how your users are actually using your changes.</p>
<h3>Deployment slots</h3>
<p>If you're doing your deployments via Azure App Services, then another option at your dispense, is to use <a href="https://docs.microsoft.com/en-us/azure/app-service/deploy-staging-slots#route-traffic">deployment slots</a>. The main use case for this is to run a staging slot alongside your live slot, and to swap them when doing a deployment to ensure that you've tested your changes, warmed up your site beforehand and traffic is switched over without downtime.</p>
<p>There is another benefit to it though, in that it can allow you to drive traffic to either slot based on a percentage. That way you can test with 20% of users before rolling out to the other 80% and this is managed through deployment. You can do similar with traffic manager or other load balancing rules.</p>
<p><img src="/images/deploymentslots-routetraffic.png" alt="Azure deployment slots" title="Image showing the options for routing in Azure deployment slots"></p>
<p>With this option, it's even more important that you can provide suitable metrics and logs to determine how your new changes are performing. Without reasonable guidance, you're in the dark as to whether or not it's a good idea to roll out.</p>
<h3>Features as a service</h3>
<p>With the rise of microservices, why not make use of a service that can handle our features? One of those services is <a href="https://launchdarkly.com/">LaunchDarkly</a>, which provides a dashboard for your features and has a number of libraries (inc. JS and .NET) that you can integrate with. As a solution, it'll allow you to get a full feature management tool pretty quickly, and one that should provide plenty of options albeit at a price. Useful to consider, and there may well be others out there. The concepts should still be the same as we've outlined in this article.</p>
<p><strong>[Update]</strong></p>
<p>Since originally writing this article, another option which I've found is the <a href="https://github.com/microsoft/FeatureManagement-Dotnet">.NET Feature Management</a> library. This is built on top of the .NET configuration system and provides a nice set of APIs for using in your applications. It looks like a great option. Here's a <a href="https://docs.microsoft.com/en-us/azure/azure-app-configuration/quickstart-feature-flag-dotnet">quick start guide</a> to set up with Azure.</p>
<h2>Conclusion</h2>
<p>Testing features in production is a big part of continuous improvement and ties in well with the continuous development way of doing things. You can deliver changes quicker and have greater confidence in when a feature is enabled for all. Ideally, you can ramp up usage in a controlled manner.</p>
<p>You can gain feedback on your changes from real users and scenarios, which may in turn provide much greater insight as to how something works. The end goal being that your changes have been well integrated and are of better quality overall.</p>

    ]]></content>
  </entry>
	
  
  <entry>
    <title>Cloudflare page rules</title>
    <link href="https://mozzy.dev/posts/cloudflare-page-rules/"/>
    <updated>2019-07-16T00:00:00+00:00</updated>
    <id>https://mozzy.dev/posts/cloudflare-page-rules/</id>
    <content type="html"><![CDATA[
      <p>As you might have read, I recently moved my site over to a new domain. <a href="https://mozzy.dev">mozzy.dev</a></p>
<p>I needed a way to redirect requests from my old domain to the new one, but I didn't really want to go creating redirect rules at the server level or whatever (think IIS, Apache). In fact, <a href="https://tcmorris.net">tcmorris.net</a> is simply a Github Pages site. It needed to be a 301 redirect and not just a <a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Redirections#HTML_redirections">meta refresh</a> tag, which simply reloads the browser.</p>
<p>Way back, I used Cloudflare to provide free SSL on my site, and the DNS etc is still handled there. So, I had a look around and came across Page Rules. These are neat little rules that you can apply to your app such as 'Always use HTTPS' or 'Auto Minify'. A lot of this is provided by Cloudflare to use across your site, but this allows you to be specific with individual pages if you wish.</p>
<p>The one that I was interested in was 'Forwarding URL', which allows you to forward requests and trigger a redirect of some sort (301/302). You can use wildcards in the matching rule to cover all pages for example, and then set a new destination along with the matching wildcard info. Example below for how I managed to get a 301 redirect working to my new domain.</p>
<p><img src="/images/cloudflare-page-rules.jpg" alt="Cloudflare Page Rule example" title="Setting up 301 redirect in Cloudflare Page Rules."></p>
<p>Rather neat I'm sure you'll agree.</p>
<p>For more info, have a look at their docs: <a href="https://support.cloudflare.com/hc/en-us/articles/218411427">Cloudflare examples</a></p>

    ]]></content>
  </entry>
	
  
  <entry>
    <title>Introducing mozzy.dev</title>
    <link href="https://mozzy.dev/posts/introducing-mozzydev/"/>
    <updated>2019-07-15T00:00:00+00:00</updated>
    <id>https://mozzy.dev/posts/introducing-mozzydev/</id>
    <content type="html"><![CDATA[
      <p>It's been a while, but after the launch of <a href="https://hylia.website">Hylia</a> by Andy Bell, I figured it was about time that I updated my personal site.</p>
<p>With that, the opportunity for a bit of a refresh arised and so <a href="https://mozzy.dev">mozzy.dev</a> was born.</p>
<h2>Personal brand</h2>
<p>I've not toyed too much with changing my username, it's mostly been <code>mozzy16</code> from an early start and then I tried <code>tcmorris</code> to give a more professional spin.</p>
<p>The origins of <code>mozzy16</code> are rather boring, a play on my surname and my birth date. <code>tcmorris</code> was just tied to my name.</p>
<p>After being called mozzy, moz or mo quite often, it seems appropriate to stay along those lines. This time just with a developer spin, since that's what I do.</p>
<h2>Why is this important?</h2>
<p>Here's <a href="https://codeshare.co.uk/blog/boosting-your-career-by-creating-a-personal-brand/">some reading</a> that you might find of interest from Paul Seal of codeshare.co.uk fame.</p>
<p>Andy tells us his story too: <a href="https://andy-bell.design/wrote/so-long-hankchizljaw/">So long, HankChizlJaw</a></p>
<h2>Personal sites</h2>
<p>With a personal brand goes a personal site. Sure, you could write on Medium or some other online community, but in doing so you're effectively losing a level of control over your content. If I wanted to change anything on this site, I've got the source code, including all the posts and images that go with it. In migrating from Jekyll, all I needed to do was copy and paste some files.</p>
<p>If you're wanting to start a personal site, perhaps try something like <a href="https://hylia.website">Hylia</a> as a starting point.</p>

    ]]></content>
  </entry>
	
  
  <entry>
    <title>Using migrations in Umbraco</title>
    <link href="https://mozzy.dev/posts/using-migrations-in-umbraco/"/>
    <updated>2018-10-28T00:00:00+00:00</updated>
    <id>https://mozzy.dev/posts/using-migrations-in-umbraco/</id>
    <content type="html"><![CDATA[
      <p>Migrations are a really handy way to deploy your database changes to new environments. Umbraco use them extensively for processing any upgrades between versions and you can use them too. If you've ever used Entity Framework, then this will probably be fairly familiar.</p>
<h1>What does it do?</h1>
<p>Umbraco has actually been doing this since v6, with the idea that running migrations via code versus having a suite of custom SQL scripts can offer more options.</p>
<p>There is a table which keeps track of all the migrations that have been run called <code>umbracoMigration</code>, it looks a bit like this:</p>
<ul>
<li>add image</li>
</ul>
<p>You'll notice that it has a name next to each migration, as well as the version. This is how we can see what state our database is in. So, for the above it's run up to 7.12.3 in Umbraco. When you deploy changes to a new server, if it's pointing to an older version then it will run the migration on startup. This is mostly used for schema changes, but you can also insert data or run your own custom code.</p>
<h3>How does it work?</h3>
<p>Umbraco has this concept of a MigrationRunner that you can trigger to execute your migrations. You'll need to set the target version and then you can find all the relevant migrations to get to that version and run them.</p>
<p>In order to find these migrations, all you need to do is create a file that looks a bit like this:</p>
<pre class="language-csharp"><code class="language-csharp"><span class="highlight-line"><span class="token comment">/// &lt;summary></span></span><br><span class="highlight-line"><span class="token comment">/// MyCustomTable migration</span></span><br><span class="highlight-line"><span class="token comment">/// &lt;/summary></span></span><br><span class="highlight-line"><span class="token punctuation">[</span><span class="token function">Migration</span><span class="token punctuation">(</span><span class="token string">"1.0.0"</span><span class="token punctuation">,</span> <span class="token number">1</span><span class="token punctuation">,</span> MigrationNames<span class="token punctuation">.</span>MyCustomNamespace<span class="token punctuation">)</span><span class="token punctuation">]</span></span><br><span class="highlight-line"><span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">MyCustomTableMigration</span> <span class="token punctuation">:</span> <span class="token type-list"><span class="token class-name">MigrationBase</span></span></span><br><span class="highlight-line"><span class="token punctuation">{</span></span><br><span class="highlight-line">    <span class="token keyword">private</span> <span class="token keyword">const</span> <span class="token class-name"><span class="token keyword">string</span></span> TableName <span class="token operator">=</span> <span class="token string">"MyCustomTable"</span><span class="token punctuation">;</span></span><br><span class="highlight-line"></span><br><span class="highlight-line">    <span class="token keyword">public</span> <span class="token function">MyCustomTableMigration</span><span class="token punctuation">(</span><span class="token class-name">ISqlSyntaxProvider</span> sqlSyntax<span class="token punctuation">,</span> <span class="token class-name">ILogger</span> logger<span class="token punctuation">)</span></span><br><span class="highlight-line">        <span class="token punctuation">:</span> <span class="token keyword">base</span><span class="token punctuation">(</span>sqlSyntax<span class="token punctuation">,</span> logger<span class="token punctuation">)</span></span><br><span class="highlight-line">    <span class="token punctuation">{</span>            </span><br><span class="highlight-line">    <span class="token punctuation">}</span></span><br><span class="highlight-line"></span><br><span class="highlight-line">    <span class="token comment">/// &lt;summary></span></span><br><span class="highlight-line">    <span class="token comment">/// Process database upgrade</span></span><br><span class="highlight-line">    <span class="token comment">/// &lt;/summary></span></span><br><span class="highlight-line">    <span class="token keyword">public</span> <span class="token keyword">override</span> <span class="token return-type class-name"><span class="token keyword">void</span></span> <span class="token function">Up</span><span class="token punctuation">(</span><span class="token punctuation">)</span></span><br><span class="highlight-line">    <span class="token punctuation">{</span>            </span><br><span class="highlight-line">        <span class="token comment">// create a new table if it doesn't exist</span></span><br><span class="highlight-line">        <span class="token class-name"><span class="token keyword">var</span></span> tables <span class="token operator">=</span> SqlSyntax<span class="token punctuation">.</span><span class="token function">GetTablesInSchema</span><span class="token punctuation">(</span>Context<span class="token punctuation">.</span>Database<span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">ToList</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span><br><span class="highlight-line">        <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token operator">!</span>tables<span class="token punctuation">.</span><span class="token function">InvariantContains</span><span class="token punctuation">(</span>TableName<span class="token punctuation">)</span><span class="token punctuation">)</span></span><br><span class="highlight-line">        <span class="token punctuation">{</span></span><br><span class="highlight-line">            Create<span class="token punctuation">.</span><span class="token function">Table</span><span class="token punctuation">(</span>TableName<span class="token punctuation">)</span><span class="token punctuation">;</span></span><br><span class="highlight-line">        <span class="token punctuation">}</span></span><br><span class="highlight-line"></span><br><span class="highlight-line">        <span class="token comment">// or you can run alterations on existing tables</span></span><br><span class="highlight-line">        <span class="token class-name"><span class="token keyword">var</span></span> columns <span class="token operator">=</span> SqlSyntax<span class="token punctuation">.</span><span class="token function">GetColumnsInSchema</span><span class="token punctuation">(</span>Context<span class="token punctuation">.</span>Database<span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">ToArray</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span><br><span class="highlight-line">        <span class="token class-name"><span class="token keyword">var</span></span> columnExists <span class="token operator">=</span> columns<span class="token punctuation">.</span><span class="token function">Any</span><span class="token punctuation">(</span>x <span class="token operator">=></span></span><br><span class="highlight-line">            <span class="token keyword">string</span><span class="token punctuation">.</span><span class="token function">Equals</span><span class="token punctuation">(</span>x<span class="token punctuation">.</span>TableName<span class="token punctuation">,</span> tableName<span class="token punctuation">)</span> <span class="token operator">&amp;&amp;</span></span><br><span class="highlight-line">            <span class="token keyword">string</span><span class="token punctuation">.</span><span class="token function">Equals</span><span class="token punctuation">(</span>x<span class="token punctuation">.</span>ColumnName<span class="token punctuation">,</span> columnName<span class="token punctuation">)</span></span><br><span class="highlight-line">        <span class="token punctuation">)</span><span class="token punctuation">;</span></span><br><span class="highlight-line">        <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token operator">!</span>columnExists<span class="token punctuation">)</span></span><br><span class="highlight-line">        <span class="token punctuation">{</span></span><br><span class="highlight-line">            Alter<span class="token punctuation">.</span><span class="token function">Table</span><span class="token punctuation">(</span><span class="token string">"SomeOtherTable"</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">AddColumn</span><span class="token punctuation">(</span><span class="token string">"MyCustomString"</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">AsString</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">Nullable</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span><br><span class="highlight-line">        <span class="token punctuation">}</span></span><br><span class="highlight-line">    <span class="token punctuation">}</span></span><br><span class="highlight-line"></span><br><span class="highlight-line">    <span class="token comment">/// &lt;summary></span></span><br><span class="highlight-line">    <span class="token comment">/// Process database downgrade</span></span><br><span class="highlight-line">    <span class="token comment">/// &lt;/summary></span></span><br><span class="highlight-line">    <span class="token keyword">public</span> <span class="token keyword">override</span> <span class="token return-type class-name"><span class="token keyword">void</span></span> <span class="token function">Down</span><span class="token punctuation">(</span><span class="token punctuation">)</span></span><br><span class="highlight-line">    <span class="token punctuation">{</span></span><br><span class="highlight-line">        <span class="token comment">// drop the table</span></span><br><span class="highlight-line">        Delete<span class="token punctuation">.</span><span class="token function">Table</span><span class="token punctuation">(</span>TableName<span class="token punctuation">)</span><span class="token punctuation">;</span></span><br><span class="highlight-line"></span><br><span class="highlight-line">        <span class="token comment">// remove the column from existing table</span></span><br><span class="highlight-line">        Delete<span class="token punctuation">.</span><span class="token function">Column</span><span class="token punctuation">(</span><span class="token string">"MyCustomString"</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">FromTable</span><span class="token punctuation">(</span><span class="token string">"SomeOtherTable"</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span><br><span class="highlight-line">    <span class="token punctuation">}</span></span><br><span class="highlight-line"><span class="token punctuation">}</span></span></code></pre>
<p>The code above is saying add a new table and also alter an existing table by adding a new column of type string. The commands are exposed via the inherited <code>MigrationBase</code> which Umbraco provides. We're stating that this is v1.0.0 in a SemVer format. We're also saying that this is going to have it's own name for the migration (<code>MigrationNames.MyCustomNamespace</code>), this keeps all your migrations grouped for your custom code.</p>
<p>We need to tell Umbraco to run this code on startup. Here is how you can do that:</p>
<pre class="language-csharp"><code class="language-csharp"><span class="highlight-line"><span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">CustomMigrationEventHandler</span> <span class="token punctuation">:</span> <span class="token type-list"><span class="token class-name">ApplicationEventHandler</span></span></span><br><span class="highlight-line"><span class="token punctuation">{</span></span><br><span class="highlight-line">    <span class="token keyword">protected</span> <span class="token keyword">override</span> <span class="token return-type class-name"><span class="token keyword">void</span></span> <span class="token function">ApplicationStarted</span><span class="token punctuation">(</span><span class="token class-name">UmbracoApplicationBase</span> umbracoApplication<span class="token punctuation">,</span> <span class="token class-name">ApplicationContext</span> applicationContext<span class="token punctuation">)</span></span><br><span class="highlight-line">    <span class="token punctuation">{</span></span><br><span class="highlight-line">        <span class="token comment">// check target version</span></span><br><span class="highlight-line">        <span class="token class-name"><span class="token keyword">var</span></span> rawTargetVersion <span class="token operator">=</span> ConfigurationManager<span class="token punctuation">.</span>AppSettings<span class="token punctuation">[</span><span class="token string">"app:MigrationVersion"</span><span class="token punctuation">]</span> <span class="token operator">??</span> <span class="token string">"1.0.0"</span><span class="token punctuation">;</span></span><br><span class="highlight-line">        <span class="token class-name"><span class="token keyword">var</span></span> targetVersion <span class="token operator">=</span> SemVersion<span class="token punctuation">.</span><span class="token function">Parse</span><span class="token punctuation">(</span>rawTargetVersion<span class="token punctuation">)</span><span class="token punctuation">;</span></span><br><span class="highlight-line">        <span class="token keyword">if</span> <span class="token punctuation">(</span>targetVersion <span class="token operator">!=</span> <span class="token keyword">null</span><span class="token punctuation">)</span></span><br><span class="highlight-line">        <span class="token punctuation">{</span></span><br><span class="highlight-line">            <span class="token function">HandleMigrations</span><span class="token punctuation">(</span>targetVersion<span class="token punctuation">)</span><span class="token punctuation">;</span></span><br><span class="highlight-line">        <span class="token punctuation">}</span></span><br><span class="highlight-line"></span><br><span class="highlight-line">        <span class="token keyword">base</span><span class="token punctuation">.</span><span class="token function">ApplicationStarted</span><span class="token punctuation">(</span>umbracoApplication<span class="token punctuation">,</span> applicationContext<span class="token punctuation">)</span><span class="token punctuation">;</span></span><br><span class="highlight-line">    <span class="token punctuation">}</span></span><br><span class="highlight-line"></span><br><span class="highlight-line">    <span class="token keyword">private</span> <span class="token return-type class-name"><span class="token keyword">void</span></span> <span class="token function">HandleMigrations</span><span class="token punctuation">(</span><span class="token class-name">SemVersion</span> targetVersion<span class="token punctuation">)</span></span><br><span class="highlight-line">    <span class="token punctuation">{</span></span><br><span class="highlight-line">        <span class="token comment">// get all migrations already executed</span></span><br><span class="highlight-line">        <span class="token class-name"><span class="token keyword">var</span></span> currentVersion <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token constructor-invocation class-name">SemVersion</span><span class="token punctuation">(</span><span class="token number">0</span><span class="token punctuation">,</span> <span class="token number">0</span><span class="token punctuation">,</span> <span class="token number">0</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span><br><span class="highlight-line">        <span class="token class-name"><span class="token keyword">var</span></span> migrations <span class="token operator">=</span> ApplicationContext<span class="token punctuation">.</span>Current<span class="token punctuation">.</span>Services<span class="token punctuation">.</span>MigrationEntryService<span class="token punctuation">.</span><span class="token function">GetAll</span><span class="token punctuation">(</span>MigrationNames<span class="token punctuation">.</span>MyCustomNamespace<span class="token punctuation">)</span><span class="token punctuation">;</span></span><br><span class="highlight-line"></span><br><span class="highlight-line">        <span class="token comment">// get the latest migration executed</span></span><br><span class="highlight-line">        <span class="token class-name"><span class="token keyword">var</span></span> latestMigration <span class="token operator">=</span> migrations<span class="token punctuation">.</span><span class="token function">OrderByDescending</span><span class="token punctuation">(</span>x <span class="token operator">=></span> x<span class="token punctuation">.</span>Version<span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">FirstOrDefault</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span><br><span class="highlight-line">        <span class="token keyword">if</span> <span class="token punctuation">(</span>latestMigration <span class="token operator">!=</span> <span class="token keyword">null</span><span class="token punctuation">)</span></span><br><span class="highlight-line">        <span class="token punctuation">{</span></span><br><span class="highlight-line">            currentVersion <span class="token operator">=</span> latestMigration<span class="token punctuation">.</span>Version<span class="token punctuation">;</span></span><br><span class="highlight-line">        <span class="token punctuation">}</span></span><br><span class="highlight-line"></span><br><span class="highlight-line">        <span class="token keyword">if</span> <span class="token punctuation">(</span>targetVersion <span class="token operator">==</span> currentVersion<span class="token punctuation">)</span></span><br><span class="highlight-line">        <span class="token punctuation">{</span></span><br><span class="highlight-line">            <span class="token comment">// nothing to do</span></span><br><span class="highlight-line">            <span class="token keyword">return</span><span class="token punctuation">;</span></span><br><span class="highlight-line">        <span class="token punctuation">}</span></span><br><span class="highlight-line"></span><br><span class="highlight-line">        <span class="token class-name"><span class="token keyword">var</span></span> migrationsRunner <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token constructor-invocation class-name">MigrationRunner</span><span class="token punctuation">(</span></span><br><span class="highlight-line">            ApplicationContext<span class="token punctuation">.</span>Current<span class="token punctuation">.</span>Services<span class="token punctuation">.</span>MigrationEntryService<span class="token punctuation">,</span></span><br><span class="highlight-line">            ApplicationContext<span class="token punctuation">.</span>Current<span class="token punctuation">.</span>ProfilingLogger<span class="token punctuation">.</span>Logger<span class="token punctuation">,</span></span><br><span class="highlight-line">            currentVersion<span class="token punctuation">,</span></span><br><span class="highlight-line">            targetVersion<span class="token punctuation">,</span></span><br><span class="highlight-line">            MigrationNames<span class="token punctuation">.</span>MyCustomNamespace<span class="token punctuation">)</span><span class="token punctuation">;</span></span><br><span class="highlight-line"></span><br><span class="highlight-line">        <span class="token keyword">try</span></span><br><span class="highlight-line">        <span class="token punctuation">{</span></span><br><span class="highlight-line">            <span class="token comment">// run migrations</span></span><br><span class="highlight-line">            migrationsRunner<span class="token punctuation">.</span><span class="token function">Execute</span><span class="token punctuation">(</span>UmbracoContext<span class="token punctuation">.</span>Current<span class="token punctuation">.</span>Application<span class="token punctuation">.</span>DatabaseContext<span class="token punctuation">.</span>Database<span class="token punctuation">)</span><span class="token punctuation">;</span></span><br><span class="highlight-line">        <span class="token punctuation">}</span></span><br><span class="highlight-line">        <span class="token keyword">catch</span> <span class="token punctuation">(</span><span class="token class-name">Exception</span> e<span class="token punctuation">)</span></span><br><span class="highlight-line">        <span class="token punctuation">{</span></span><br><span class="highlight-line">            LogHelper<span class="token punctuation">.</span><span class="token generic-method"><span class="token function">Error</span><span class="token generic class-name"><span class="token punctuation">&lt;</span>MigrationEvents<span class="token punctuation">></span></span></span><span class="token punctuation">(</span><span class="token string">"Error running migration"</span><span class="token punctuation">,</span> e<span class="token punctuation">)</span><span class="token punctuation">;</span></span><br><span class="highlight-line">        <span class="token punctuation">}</span></span><br><span class="highlight-line">    <span class="token punctuation">}</span></span><br><span class="highlight-line"><span class="token punctuation">}</span></span></code></pre>
<p>That's a fair chunk of code. Quick run through as to what's happening...</p>
<ul>
<li>find out what version to target</li>
<li>figure out if that is a later version that what we have</li>
<li>if so, run the migrations</li>
<li>throw an error if it blows up</li>
</ul>
<p>Your custom table should get added the next time you start Umbraco. Notice that I've added an appsetting for keeping track of the version called <code>app:MigrationVersion</code>. You can add this via your web.config and then use it to target different versions and update through your deployment variables. This way, we opt in and have a configurable value rather than changing our code each time.</p>
<p>So, we've added our custom table and now want to make a change. What do we do? Well, we create a new migration which inherits from <code>MigrationBase</code>, has our code in and then bump up the version via the config value.</p>
<h3>Any gotchas?</h3>
<p>Yeah, a few things to be aware of.</p>
<p>In the migration examples above, we used static strings to denote the table and column names. You can also use a reference like so, which uses type <code>T</code>.</p>
<pre class="language-csharp"><code class="language-csharp"><span class="highlight-line">Create<span class="token punctuation">.</span><span class="token generic-method"><span class="token function">Table</span><span class="token generic class-name"><span class="token punctuation">&lt;</span>MyCustomTable<span class="token punctuation">></span></span></span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span></code></pre>
<p>The slight issue with this though is that if you want to remove <code>MyCustomTable</code> from your code, then you're going to have to change your migration as you don't particularly want to keep old references around just so that it will compile. The migration shouldn't change though, it should be able to run multiple times and by the end you should be in the same state as the version asked for. The term for this is idempotent.</p>
<p>The other thing that to note is that once you've racked up a few of these, it might be hard to realise which ones relate to which version. Umbraco handles this by using named folders that relate to the version they are targetting. Here's an alternative:</p>
<ul>
<li>001_InitialMigration.cs</li>
<li>002_MyNextMigration.cs</li>
<li>003_AddCustomerTable.cs</li>
</ul>
<p>Essentially, just adding a prefix so that you can easily see at a glance which migrations have been added and what order they occurred. You could also map these to the SemVer version if you wanted.</p>
<p>When you deploy these changes to your site, they will run on startup and could provide a bit of downtime for your customers. Think about what that means to you and figure out if you can do this at low traffic or you could use a blue-green strategy where you alternate between 2 versions of the live site allowing you to prep everything without your customers taking the hit.</p>
<h3>Summary</h3>
<p>Hopefully you now understand a little about what migrations are and can see how to utilise them on your projects. Following the patterns mentioned in this post, you should be deploying with ease.</p>
<h4>References</h4>
<ul>
<li><a href="https://cultiv.nl/blog/using-umbraco-migrations-to-deploy-changes/">https://cultiv.nl/blog/using-umbraco-migrations-to-deploy-changes/</a></li>
<li><a href="https://github.com/umbraco/Umbraco-CMS/tree/dev-v7/src/Umbraco.Core/Persistence/Migrations/Upgrades">https://github.com/umbraco/Umbraco-CMS/tree/dev-v7/src/Umbraco.Core/Persistence/Migrations/Upgrades</a></li>
<li><a href="https://github.com/umbraco/Umbraco-CMS/blob/dev-v7/src/Umbraco.Tests/Migrations/CreateTableMigrationTests.cs">https://github.com/umbraco/Umbraco-CMS/blob/dev-v7/src/Umbraco.Tests/Migrations/CreateTableMigrationTests.cs</a></li>
<li><a href="https://skrift.io/articles/archive/umbraco-migrations-made-easy/">https://skrift.io/articles/archive/umbraco-migrations-made-easy/</a></li>
</ul>

    ]]></content>
  </entry>
	
  
  <entry>
    <title>App offline strategies for your website</title>
    <link href="https://mozzy.dev/posts/app-offline-strategies/"/>
    <updated>2018-10-09T00:00:00+00:00</updated>
    <id>https://mozzy.dev/posts/app-offline-strategies/</id>
    <content type="html"><![CDATA[
      <p>It's undesirable, but sometimes you'll be in a scenario where you may need to take your sife offline for maintenance. This could be an upgrade to your CMS of choice (e.g. <a href="https://umbraco.com/">Umbraco</a>), processing of changes behind the scenes or simply restricting users at high traffic.</p>
<h3>app_offline.htm</h3>
<p>The simplest way to do this is to place an <a href="https://docs.microsoft.com/en-gb/iis/publish/deploying-application-packages/taking-an-application-offline-before-publishing">app_offline.htm</a> file in the root directory of the website. This will instruct .NET to route all traffic to that file and show this to the user. It'll need to be simple html and you'll need to inline any CSS that you want applied.</p>
<p>This is great if you want to restrict traffic altogether, but if you want to do stuff in the background then you are a bit stuck.</p>
<h3>IIS Rewrite</h3>
<p>So, one way in which you can get around that is by using a rewrite rule which negates a certain IP. This will allow whoever visits your site via the IP added, to browse the website without obstruction. Anyone else, will get served the offline file. Below is an example transform that you can use to achieve that.</p>
<pre class="language-xml"><code class="language-xml"><span class="highlight-line"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>rule</span> <span class="token attr-name">name</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>App-offline<span class="token punctuation">"</span></span> <span class="token attr-name">stopProcessing</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>true<span class="token punctuation">"</span></span> <span class="token attr-name">enabled</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>true<span class="token punctuation">"</span></span> <span class="token attr-name"><span class="token namespace">xdt:</span>Transform</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>InsertIfMissing<span class="token punctuation">"</span></span> <span class="token attr-name"><span class="token namespace">xdt:</span>Locator</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>Match(name)<span class="token punctuation">"</span></span><span class="token punctuation">></span></span></span><br><span class="highlight-line">    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>match</span> <span class="token attr-name">url</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>^(.*)$<span class="token punctuation">"</span></span> <span class="token attr-name">ignoreCase</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>false<span class="token punctuation">"</span></span><span class="token punctuation">/></span></span></span><br><span class="highlight-line">    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>conditions</span> <span class="token attr-name">logicalGrouping</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>MatchAll<span class="token punctuation">"</span></span><span class="token punctuation">></span></span></span><br><span class="highlight-line">        <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>add</span> <span class="token attr-name">input</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>{URL}<span class="token punctuation">"</span></span> <span class="token attr-name">pattern</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>/offline.htm$<span class="token punctuation">"</span></span> <span class="token attr-name">ignoreCase</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>false<span class="token punctuation">"</span></span> <span class="token attr-name">negate</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>true<span class="token punctuation">"</span></span><span class="token punctuation">/></span></span></span><br><span class="highlight-line">        <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>add</span> <span class="token attr-name">input</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>{REMOTE_ADDR}<span class="token punctuation">"</span></span> <span class="token attr-name">pattern</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>^127.0.0.1$<span class="token punctuation">"</span></span> <span class="token attr-name">ignoreCase</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>false<span class="token punctuation">"</span></span> <span class="token attr-name">negate</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>true<span class="token punctuation">"</span></span><span class="token punctuation">/></span></span>            </span><br><span class="highlight-line">    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>conditions</span><span class="token punctuation">></span></span></span><br><span class="highlight-line">    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>action</span> <span class="token attr-name">type</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>Redirect<span class="token punctuation">"</span></span> <span class="token attr-name">url</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>/offline.htm<span class="token punctuation">"</span></span> <span class="token attr-name">redirectType</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>Found<span class="token punctuation">"</span></span><span class="token punctuation">/></span></span></span><br><span class="highlight-line"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>rule</span><span class="token punctuation">></span></span></span></code></pre>
<h3>Maintenance manager</h3>
<p>Perhaps you don't have a specific IP you want to allow and are interested in being able to turn this off and on. Well, the good news is if you are using Umbraco, then Kevin Jump has created a package for that. It's called maintenance mode for Umbraco. You can login to Umbraco and then you'll be given the option to apply the restriction to everyone, as well enabling access for back office users if you wish.</p>
<p>You can download that here: <a href="https://our.umbraco.com/packages/backoffice-extensions/maintenance-manager/">https://our.umbraco.com/packages/backoffice-extensions/maintenance-manager/</a></p>
<h3>Limited downtime?</h3>
<p>There's a few ways to achieve this. One of the most common being <a href="https://octopus.com/docs/deployment-patterns/blue-green-deployments">blue-green deployments</a> where you alternate between active and inactive versions of the website, resulting in one being live and the other being updated and switched to. Usually this will require some kind of load balancer although with deployment slots in Azure you can achieve a similar thing.</p>
<p>You could use tooling such as <a href="https://octopus.com/">Octopus Deploy</a> to set up a variety of deployment strategies, with the ability to run custom scripts and actions throughout the deployment. You can also configure a deployment to run at scheduled times (e.g. 2am where there is expected to be little traffic).</p>

    ]]></content>
  </entry>
	
  
  <entry>
    <title>Using Models Builder in a project</title>
    <link href="https://mozzy.dev/posts/using-models-builder/"/>
    <updated>2018-06-03T00:00:00+00:00</updated>
    <id>https://mozzy.dev/posts/using-models-builder/</id>
    <content type="html"><![CDATA[
      <p>A while back I gave <a href="https://tcmorris.net/blog/getting-started-with-models-builder/" title="Getting Started with Models Builder">an overview</a> of the different options that Models Builder provides you. I didn't go into a lot of detail, but I did cover why you might want to use one option over another.</p>
<h3>Structure</h3>
<p>Fast forward a little, and I think I've reached an approach that I'm happy with and allows me to build things in a way I want without adding extra complication. I'm more familiar with an MVC type scenario and so here's the kind of solution I normally end up with for Umbraco projects.</p>
<ul>
<li>Project.Web.Core - class library</li>
<li>Project.Web.UI - website project (reference to the above)</li>
</ul>
<p>There will likely be some other projects in there as well, e.g. tests.</p>
<p>I would typically place my models within the Core project and then utilise these within the views of the UI project. To do that, there are some configuration options to instruct Models Builder as to how to create models.</p>
<pre class="language-xml"><code class="language-xml"><span class="highlight-line"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>add</span> <span class="token attr-name">key</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>Umbraco.ModelsBuilder.Enable<span class="token punctuation">"</span></span> <span class="token attr-name">value</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>true<span class="token punctuation">"</span></span> <span class="token punctuation">/></span></span></span><br><span class="highlight-line"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>add</span> <span class="token attr-name">key</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>Umbraco.ModelsBuilder.ModelsMode<span class="token punctuation">"</span></span> <span class="token attr-name">value</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>AppData<span class="token punctuation">"</span></span> <span class="token punctuation">/></span></span></span><br><span class="highlight-line"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>add</span> <span class="token attr-name">key</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>Umbraco.ModelsBuilder.ModelsNamespace<span class="token punctuation">"</span></span> <span class="token attr-name">value</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>Project.Web.Core.Models.Content<span class="token punctuation">"</span></span> <span class="token punctuation">/></span></span></span><br><span class="highlight-line"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>add</span> <span class="token attr-name">key</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>Umbraco.ModelsBuilder.ModelsDirectory<span class="token punctuation">"</span></span> <span class="token attr-name">value</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>~/../Project.Web.Core/Models/Content/<span class="token punctuation">"</span></span> <span class="token punctuation">/></span></span></span><br><span class="highlight-line"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>add</span> <span class="token attr-name">key</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>Umbraco.ModelsBuilder.AcceptUnsafeModelsDirectory<span class="token punctuation">"</span></span> <span class="token attr-name">value</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>true<span class="token punctuation">"</span></span> <span class="token punctuation">/></span></span></span></code></pre>
<p>The above will place the models generated by Models Builder into my Project.Web.Core project, so that I can then use them how I wish. Include them in the project and do a build, and they will be included in the project dll.</p>
<p>The good thing about this is if you already have a project that was using <code>Model.Content.GetPropertyValue(&quot;propertyAlias&quot;)</code> it's not too difficult to change them over to strongly typed models. Models Builder itself is essentially doing all that for you. If you're starting fresh on a project, then there a few other options for your model/mapping needs. None of the below generate models, so are quite different in usage to Models Builder. They do offer more complex scenarios in terms of mapping and granular view models, and may be something you prefer.</p>
<ul>
<li><a href="https://github.com/AndyButland/UmbracoMapper">Umbraco Mapper</a></li>
<li><a href="https://github.com/JimBobSquarePants/UmbMapper">UmbMapper</a></li>
<li><a href="https://github.com/umco/umbraco-ditto">Ditto</a></li>
</ul>
<h3>Using the models</h3>
<p>I've now got a bunch of files that provide me with the generated models from Umbraco. These are content models and they all inherit from <code>PublishedContentModel</code>. They are partial classes. When it comes to using these models, it might be instantiated via a controller or it might just be there for me via Umbraco's routing.</p>
<p>In a view, this is what we can do:</p>
<pre class="language-csharp"><code class="language-csharp"><span class="highlight-line">@inherits UmbracoViewPage<span class="token operator">&lt;</span>MyModel<span class="token operator">></span></span></code></pre>
<p>Then, within the view there will be intellisense and I will be notified of compilation errors. A nice benefit of using strongly typed models. Since we made use of <code>UmbracoViewPage</code> we also get access to all the Umbraco helper methods.</p>
<p>Ok, that sounds great. But, there's something a little iffy with using a model that Umbraco generated for me and is closely tied with the content in Umbraco. What if I wanted to extend this or have my own properties? Well, there's a solution for that. The official docs suggest that we create another partial class and add what we need there, but I think I prefer this method. We can just inherit from the model that Models Builder gave us.</p>
<pre class="language-csharp"><code class="language-csharp"><span class="highlight-line"><span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">FridayBeersViewModel</span> <span class="token punctuation">:</span> <span class="token type-list"><span class="token class-name">FridayBeers</span></span></span><br><span class="highlight-line"><span class="token punctuation">{</span></span><br><span class="highlight-line">    <span class="token keyword">public</span> <span class="token function">FridayBeersViewModel</span><span class="token punctuation">(</span><span class="token class-name">IPublishedContent</span> content<span class="token punctuation">)</span> </span><br><span class="highlight-line">        <span class="token punctuation">:</span> <span class="token keyword">base</span><span class="token punctuation">(</span>content<span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token punctuation">}</span></span><br><span class="highlight-line"></span><br><span class="highlight-line">    <span class="token comment">// custom properties</span></span><br><span class="highlight-line">    <span class="token keyword">public</span> <span class="token return-type class-name"><span class="token keyword">bool</span></span> ShowBanner <span class="token operator">=></span> BannerImage <span class="token operator">!=</span> <span class="token keyword">null</span><span class="token punctuation">;</span></span><br><span class="highlight-line"><span class="token punctuation">}</span></span></code></pre>
<p>We've still got all the properties from the generated model and we can also build up a custom view model, which more closely matches the output in our views. As a side note, if you're view model ends up with little relation to the generated model then you probably shouldn't be inheriting from it and can just roll your own.</p>
<p>In the controller, you would then have something like this.</p>
<pre class="language-csharp"><code class="language-csharp"><span class="highlight-line"><span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">FridayBeersController</span> <span class="token punctuation">:</span> <span class="token type-list"><span class="token class-name">BasePageController</span></span></span><br><span class="highlight-line"><span class="token punctuation">{</span></span><br><span class="highlight-line">    <span class="token keyword">public</span> <span class="token return-type class-name">ActionResult</span> <span class="token function">FridayBeers</span><span class="token punctuation">(</span><span class="token punctuation">)</span></span><br><span class="highlight-line">    <span class="token punctuation">{</span></span><br><span class="highlight-line">        <span class="token class-name"><span class="token keyword">var</span></span> model <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token constructor-invocation class-name">FridayBeersViewModel</span><span class="token punctuation">(</span>CurrentPage<span class="token punctuation">)</span><span class="token punctuation">;</span></span><br><span class="highlight-line">        <span class="token comment">// apply any other updates on the model</span></span><br><span class="highlight-line">        <span class="token keyword">return</span> <span class="token function">CurrentTemplate</span><span class="token punctuation">(</span>model<span class="token punctuation">)</span><span class="token punctuation">;</span></span><br><span class="highlight-line">    <span class="token punctuation">}</span></span><br><span class="highlight-line"><span class="token punctuation">}</span></span></code></pre>
<p>I'm hijacking the route so that I can amend the default behaviour of Umbraco. I'm also making use of the template based routing in Umbraco, where the template name matches my action. <code>BasePageController</code> just inherits from <code>SurfaceController</code> and <code>IRenderMvcController</code>, and has a method called <code>CurrentTemplate</code> that resolves the template and passes the model to the view. Here's the example in Umbraco core: <a href="https://github.com/umbraco/Umbraco-CMS/blob/7ee510ed386495120666a78c61497f58ff05de8f/src/Umbraco.Web/Mvc/RenderMvcController.cs#L96">view on github</a>.</p>
<h3>Compositions</h3>
<p>The above example would work well for a page or a block of content, but we might want to break things up a little more and make better use of sharing code. When we use compositions, what we get from a generated sense is an interface and then our content models implement those properties. They can also make use of many compositions. This is great, because it means we can then define the interface as the model within a view if we want to. For example, if we had a interface such as IMetaData we can create a related partial that handles the meta tags on our site.</p>
<pre class="language-csharp"><code class="language-csharp"><span class="highlight-line">@inherits UmbracoViewPage<span class="token operator">&lt;</span>IMetaData<span class="token operator">></span></span><br><span class="highlight-line">    </span><br><span class="highlight-line"><span class="token operator">&lt;</span><span class="token class-name">meta</span> name<span class="token operator">=</span><span class="token string">"description"</span> content<span class="token operator">=</span><span class="token string">"@Model.MetaDescription"</span> <span class="token operator">/</span><span class="token operator">></span></span><br><span class="highlight-line"><span class="token comment">// etc.</span></span></code></pre>
<p>Or we might have a couple of pages that have a banner, and a few without. We just let our doc types use the compositions and they know how to render the banner.</p>
<h3>ModelTypeAlias</h3>
<p>I'm sure at one point during development of an Umbraco website you would have created a class with some constants in them, relating to the alias of the doc type. An easy way to vary your code depending on the doc type. Well, Models Builder provides this in a straightforward way.</p>
<pre class="language-csharp"><code class="language-csharp"><span class="highlight-line"><span class="token keyword">public</span> <span class="token keyword">partial</span> <span class="token keyword">class</span> <span class="token class-name">ExamplePage</span> <span class="token punctuation">:</span> <span class="token type-list"><span class="token class-name">PublishedContentModel</span></span></span><br><span class="highlight-line"><span class="token punctuation">{</span></span><br><span class="highlight-line">    <span class="token keyword">public</span> <span class="token keyword">new</span> <span class="token keyword">const</span> <span class="token class-name"><span class="token keyword">string</span></span> ModelTypeAlias <span class="token operator">=</span> <span class="token string">"ExamplePage"</span><span class="token punctuation">;</span></span><br><span class="highlight-line">    <span class="token keyword">public</span> <span class="token keyword">new</span> <span class="token keyword">const</span> <span class="token class-name">PublishedItemType</span> ModelItemType <span class="token operator">=</span> PublishedItemType<span class="token punctuation">.</span>Content<span class="token punctuation">;</span></span><br><span class="highlight-line">    </span><br><span class="highlight-line">    <span class="token keyword">public</span> <span class="token function">BasePage</span><span class="token punctuation">(</span><span class="token class-name">IPublishedContent</span> content<span class="token punctuation">)</span></span><br><span class="highlight-line">        <span class="token punctuation">:</span> <span class="token keyword">base</span><span class="token punctuation">(</span>content<span class="token punctuation">)</span></span><br><span class="highlight-line">    <span class="token punctuation">{</span> <span class="token punctuation">}</span></span><br><span class="highlight-line">        </span><br><span class="highlight-line">    <span class="token comment">// other properties</span></span><br><span class="highlight-line"><span class="token punctuation">}</span></span></code></pre>
<p>To use this, just do <code>ExamplePage.ModelTypeAlias</code> when you need it.</p>
<h3>Summary</h3>
<p>I've outlined a few ways in which you can use Models Builder on a project above perhaps what you get out of the box, so that you can get the most out of it in a simple manner. As a pattern, this should allow for easy extensibility and a quick way of consuming the content from Umbraco.</p>
<h4>Further reading</h4>
<ul>
<li><a href="https://our.umbraco.org/documentation/Reference/Templating/Modelsbuilder/Builder-Modes" title="https://our.umbraco.org/documentation/Reference/Templating/Modelsbuilder/Builder-Modes">Builder-Modes</a></li>
<li><a href="https://our.umbraco.org/documentation/Reference/Templating/Modelsbuilder/Understand-And-Extend" title="https://our.umbraco.org/documentation/Reference/Templating/Modelsbuilder/Understand-And-Extend">Understand-And-Extend</a></li>
<li><a href="https://our.umbraco.org/documentation/Reference/Routing/custom-controllers" title="https://our.umbraco.org/documentation/Reference/Routing/custom-controllers">Routing/custom-controllers</a></li>
</ul>

    ]]></content>
  </entry>
	
  
  <entry>
    <title>Joining BeerBods</title>
    <link href="https://mozzy.dev/posts/joining-beerbods/"/>
    <updated>2018-02-01T00:00:00+00:00</updated>
    <id>https://mozzy.dev/posts/joining-beerbods/</id>
    <content type="html"><![CDATA[
      <p>As of 12th Feb, I will be the newest member of the beer subscription company, <a href="https://beerbods.co.uk/">BeerBods</a> and will be taking up the role of CTO / Head Geek.</p>
<p>That sounds great, but what does it mean I hear you ask? Well, I'll be looking at their current website offering, giving it a refresh and building out new functionality. In terms of infrastructure and integrations, I'll be looking at ways to introduce tech in all aspects of the business. The focus will be on how BeerBods can become better, and how to grow as a company. There are a number of projects on the horizon and lots of great ideas, it'll be my task to understand and evaluate how these can come to fruition and be integrated from a tech point of view.</p>
<p>It's probably worth rewinding for a second, to mention a little more about BeerBods and how they got started. Back in 2011, Matt started having beer tastings in his shed. A year later and an idea about drinking better beer using the web as a platform formed. A simple website to launch and <a href="https://twitter.com/search?q=beerbods">#beerbods</a> was born on Twitter, every Thursday at 9pm you can enjoy a beer (each individual has the same beer) and talk about it online. Shortly after, it managed to become a fully fledged business and the orders were coming in. The social element and the stories behind what you are drinking is a core aspect of the business.</p>
<p>Now, those of you who know me will probably not be surprised to find out that I've managed to get a role working in the beer industry. I've been interested in the beer scene for a number of years. When I was at uni, I remember heading to the local supermarket and getting some mates round to rate the beer we just bought. Back in those days, it was more traditional ale of course, but the experience, finding new beers and social part of the tastings was very much part of it. Similar to what Matt and the BeerBods team aim to do.</p>
<p><strong>I can't wait to get started.</strong></p>

    ]]></content>
  </entry>
	
  
  <entry>
    <title>Getting Started with Docker</title>
    <link href="https://mozzy.dev/posts/getting-started-with-docker/"/>
    <updated>2017-05-31T00:00:00+00:00</updated>
    <id>https://mozzy.dev/posts/getting-started-with-docker/</id>
    <content type="html"><![CDATA[
      <p>It's more than likely that you will have already heard about Docker, but what exactly is it and what does it offer you? Well, Docker is a container platform. But, what is a container? Well, a container is an isolated image that includes everything you need to run your app. So, that includes your code, the runtime, any libraries and settings. Unlike a Virtual Machine (VM), you do not need to bundle a Guest OS. This keeps things lightweight and you can run multiple containers on a single host. The premise for this, is that containerised software will always run the same, regardless of the environment so you shouldn't get the fabled 'works on my machine' issue.</p>
<h3>Downloading Docker</h3>
<p>Docker is available in two editions: Community Edition (CE) and Enterprise Edition (EE). Docker CE is available for Mac, Windows and Linux distros. I'm going to be talking about the Windows version in this article, so grab the stable version of Docker for Windows from here:</p>
<p><a href="https://store.docker.com/editions/community/docker-ce-desktop-windows">https://store.docker.com/editions/community/docker-ce-desktop-windows</a></p>
<p>Docker uses Windows-native Hyper-V virtualisation, so if you haven't enabled this feature it will prompt you to enable this and restart. Once that is done, you'll notice that Docker is running in your taskbar. A quick click on 'About Docker' and you should see confirmation of the current version.</p>
<h3>Running Docker</h3>
<p>To interact with Docker, you can use the <code>docker</code> commands in a terminal such as Powershell. Here's how to run the simple Hello World example.</p>
<pre><code>PS C:\Users\tmorris&gt; docker run hello-world
Unable to find image 'hello-world:latest' locally
latest: Pulling from library/hello-world
78445dd45222: Pull complete
Digest: sha256:c5515758d4c5e1e838e9cd307f6c6a0d620b5e07e6f927b07d05f6d12a1ac8d7
Status: Downloaded newer image for hello-world:latest

Hello from Docker!
This message shows that your installation appears to be working correctly.

To generate this message, Docker took the following steps:
 1. The Docker client contacted the Docker daemon.
 2. The Docker daemon pulled the &quot;hello-world&quot; image from the Docker Hub.
 3. The Docker daemon created a new container from that image which runs the
    executable that produces the output you are currently reading.
 4. The Docker daemon streamed that output to the Docker client, which sent it
    to your terminal.

To try something more ambitious, you can run an Ubuntu container with:
 $ docker run -it ubuntu bash

Share images, automate workflows, and more with a free Docker ID:
 https://cloud.docker.com/

For more examples and ideas, visit:
 https://docs.docker.com/engine/userguide/
</code></pre>
<p>Some useful commands:</p>
<ul>
<li><code>docker version</code>: see version information for Docker</li>
<li><code>docker ps</code>: display running containers</li>
<li><code>docker rm &lt;container&gt;</code>: remove a container</li>
<li><code>docker images</code>: display images</li>
<li><code>docker rmi &lt;image&gt;</code>: remove an image</li>
</ul>
<p>To enable tab completion within Powershell, download <a href="https://github.com/samneirinck/posh-docker">posh-docker</a>.</p>
<h3>An example</h3>
<p>Here is a slightly more involved example that shows a <a href="https://github.com/dotnet/dotnet-docker-samples/blob/master/dotnetapp-prod/Program.cs">simple application</a> running .NET Core in a Linux container. All it does is display a brief welcome by <a href="https://github.com/dotnet-bot">dotnetbot</a>.</p>
<p><code>docker run microsoft/dotnet-samples</code></p>
<p><img src="/images/docker_dotnetbot.png" alt="Docker dotnetbot"></p>
<h3>Options</h3>
<p>Docker opens up a few possibilities in the developer workflow. Here's some usage cases:</p>
<ul>
<li>Create a consistent development environment between your team</li>
<li>Pull in your dependencies as neatly packaged Docker images</li>
<li>Isolate concerns, develop and deploy independently with a microservices architecture</li>
<li>Build and test your apps with Bitbucket Pipelines (or similar) to provide Continuous Integration (CI)</li>
<li>Scale up and manage your infrastructure with Docker Swarm</li>
</ul>
<h3>Summary</h3>
<p>Docker is gaining momentum amongst the dev community. I've given a quick overview here about how to get started and how you can incorporate Docker into your workflow. Give it a try :)</p>
<h4>References</h4>
<ul>
<li><a href="https://www.docker.com/what-docker">Docker: What is Docker</a></li>
<li><a href="https://docs.docker.com/docker-for-windows/">Docker: Getting started</a></li>
<li><a href="https://docs.docker.com/engine/docker-overview/">Docker: Overview</a></li>
<li><a href="https://blogs.msdn.microsoft.com/dotnet/2017/05/25/using-net-and-docker-together/">Microsoft: Using .NET and Docker together</a></li>
<li><a href="https://bitbucket.org/product/features/pipelines">Bitbucket Pipelines</a></li>
</ul>

    ]]></content>
  </entry>
	
  
  <entry>
    <title>Updating older Umbraco packages</title>
    <link href="https://mozzy.dev/posts/updating-older-umbraco-packages/"/>
    <updated>2016-10-27T00:00:00+00:00</updated>
    <id>https://mozzy.dev/posts/updating-older-umbraco-packages/</id>
    <content type="html"><![CDATA[
      <p>In a <a href="http://tcmorris.net/blog/upgrading-umbraco/">recent post</a>, I outlined some of the reasons for upgrading Umbraco and how best to approach the challenge. In that post, I mentioned that you are likely to have a number of issues with custom packages or custom data types. Below is a rundown of some of the examples I have encountered. If you have found others, it'd be great if you could add to the comments section and I'll look to edit this post with extra details in the hope that it can become a valuable resource.</p>
<h3>Packages</h3>
<p>This is basically a list of packages which I have come across via a previous upgrade to Umbraco 7+. Quite a few will have a version that works with Umbraco 7+, others will simply not work. Where possible, I have included a suitable upgrade path.</p>
<table>
<thead>
<tr>
<th>Package</th>
<th>Description</th>
<th>v7 support?</th>
<th>Alternative</th>
</tr>
</thead>
<tbody>
<tr>
<td>AttackMonkey Custom Menus</td>
<td>used to disable delete/copy/move etc on some content nodes, to idiot proof the CMS (e.g. Stop users deleting the home page)</td>
<td>Yes (v2+)</td>
<td></td>
</tr>
<tr>
<td>AttackMonkey Tab Hider</td>
<td>used to hide some of the tabs on content types from certain users (e.g. Only admins can edit the SEO tabs)</td>
<td>No</td>
<td></td>
</tr>
<tr>
<td>AttackMonkey Security</td>
<td>security helper, password strength validation</td>
<td>No</td>
<td>Membership provider regex</td>
</tr>
<tr>
<td>AutoFolders</td>
<td>used to automatically organise news type content into Year/Month folders</td>
<td>No</td>
<td>DateFolders / uDateFoldersy</td>
</tr>
<tr>
<td>CMSImport</td>
<td>used to import content from an old CMS</td>
<td>Yes</td>
<td></td>
</tr>
<tr>
<td>Config Tree</td>
<td>allows you to view all the site config files in the back office</td>
<td>Yes</td>
<td></td>
</tr>
<tr>
<td>Contour</td>
<td>used to provide forms</td>
<td>Yes (use latest)</td>
<td></td>
</tr>
<tr>
<td>Contour Contrib</td>
<td>adds some additional functionality to Contour, e.g. Recaptcha</td>
<td>Yes</td>
<td></td>
</tr>
<tr>
<td>DAMP</td>
<td>used as a replacement for the built in media picker, as it offers more functionality</td>
<td>No</td>
<td>Built in</td>
</tr>
<tr>
<td>DocType Mixins</td>
<td>plugin to allow DocType composition in earlier versions of Umbraco</td>
<td>Sort of</td>
<td>Doc Type Compositions</td>
</tr>
<tr>
<td>Embedded Content</td>
<td>allows for repeating content structures within a single page</td>
<td>No</td>
<td>Archetype / Nested Content</td>
</tr>
<tr>
<td>FamFamFam icons</td>
<td>adds additional icons for use in the content tree to represent Document Types</td>
<td>No</td>
<td>Built in / packages</td>
</tr>
<tr>
<td>Google Maps for Umbraco</td>
<td>Data Type that allows the selection and rendering of Google Maps</td>
<td>No</td>
<td>Alternative packages available</td>
</tr>
<tr>
<td>ImageGen</td>
<td>allows image resizing and compression</td>
<td>Yes</td>
<td>Image Processor</td>
</tr>
<tr>
<td>Mass Replacer</td>
<td>bulk find and replace actions for Umbraco back office, occasionally used when site wide brand names need standardising etc</td>
<td>Maybe</td>
<td></td>
</tr>
<tr>
<td>Media Icons</td>
<td>displays file type icon rather than the built in ones in the Umbraco media library</td>
<td>No</td>
<td></td>
</tr>
<tr>
<td>Open Calais Autotag</td>
<td>can be used as a replacement for the tags data type in earlier versions of Umbraco</td>
<td>No</td>
<td></td>
</tr>
<tr>
<td>Path Fixup</td>
<td>This is a developer dashboard control to fix database issues</td>
<td>N/a</td>
<td>Fixed</td>
</tr>
<tr>
<td>Repeatable Custom Content</td>
<td>A datatype which allows adding repeatable custom contents/child nodes.</td>
<td>No</td>
<td>Archetype / Nested Content</td>
</tr>
<tr>
<td>Robots.txt</td>
<td>allows you to view the robots.txt file for the site in the back office</td>
<td>Yes</td>
<td></td>
</tr>
<tr>
<td>Structure Extensions</td>
<td>allows you to set default Document Types for child pages</td>
<td>Maybe</td>
<td>Built in</td>
</tr>
<tr>
<td>uComponents</td>
<td>used for various additional Data Types</td>
<td>No</td>
<td>Built in</td>
</tr>
<tr>
<td>Yoyo CMS Tag Manager</td>
<td>a plugin that adds an additional section to the CMS allowing you to visually view and manage all of the tags used on the site</td>
<td>Yes (v3+)</td>
<td></td>
</tr>
</tbody>
</table>
<h3>Data Types</h3>
<p>Ok, so this one is more of an extension to the packages section above, but I figured it'd be useful to separate the two.</p>
<table>
<thead>
<tr>
<th>Property Editor</th>
<th>v7 support?</th>
<th>Alternative</th>
<th>Conversion</th>
</tr>
</thead>
<tbody>
<tr>
<td>DAMP</td>
<td>No</td>
<td>Built-in media picker</td>
<td></td>
</tr>
<tr>
<td>Embedded Content</td>
<td>No</td>
<td>Nested Content</td>
<td>Manual</td>
</tr>
<tr>
<td>Form Picker</td>
<td>Yes</td>
<td></td>
<td></td>
</tr>
<tr>
<td>Google Map</td>
<td>No</td>
<td>Package</td>
<td></td>
</tr>
<tr>
<td>Legacy MNTP</td>
<td>No</td>
<td>MNTP</td>
<td>XML to CSV</td>
</tr>
<tr>
<td>Short URL Field</td>
<td>No</td>
<td>Textbox?</td>
<td></td>
</tr>
<tr>
<td>uComponents: Multiple Dates</td>
<td>No</td>
<td>Package</td>
<td>Manual</td>
</tr>
<tr>
<td>uComponents: Multi-URL Picker</td>
<td>No</td>
<td>Related Links</td>
<td>Manual</td>
</tr>
<tr>
<td>uComponents: URL Picker</td>
<td>No</td>
<td>URL Picker</td>
<td>XML to JSON</td>
</tr>
<tr>
<td>XPath DropDownList</td>
<td>No</td>
<td>MNTP</td>
<td></td>
</tr>
</tbody>
</table>
<p>As mentioned before, this is by no means a complete list but should offer some guidance for others who come across a similar task. You might have an existing site or customer who uses some of these packages and been holding off an upgrade. It's easy enough to figure out what the outcome of such an upgrade will be, so I'd say give it a go and figure out what breaks (if anything).</p>

    ]]></content>
  </entry>
	
  
  <entry>
    <title>Getting Started with Models Builder</title>
    <link href="https://mozzy.dev/posts/getting-started-with-models-builder/"/>
    <updated>2016-06-22T00:00:00+00:00</updated>
    <id>https://mozzy.dev/posts/getting-started-with-models-builder/</id>
    <content type="html"><![CDATA[
      <p>Models Builder comes included in Umbraco 7.4 and out of the box it should just work, but what if you want more options? Below is a rundown of all the different modes for Models Builder and what they actually mean in terms of code.</p>
<sub>
I realise that there is some documentation and posts on this already, but this is aimed as a primer and how it worked for me.
</sub>
<h3>Enabling Models Builder</h3>
<p>In order to get Models Builder working, there is one key web.config update that you need to do.</p>
<pre class="language-xml"><code class="language-xml"><span class="highlight-line"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>add</span> <span class="token attr-name">key</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>Umbraco.ModelsBuilder.Enable<span class="token punctuation">"</span></span> <span class="token attr-name">value</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>true<span class="token punctuation">"</span></span> <span class="token punctuation">/></span></span></span><br><span class="highlight-line"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>add</span> <span class="token attr-name">key</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>Umbraco.ModelsBuilder.ModelsMode<span class="token punctuation">"</span></span> <span class="token attr-name">value</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>PureLive<span class="token punctuation">"</span></span> <span class="token punctuation">/></span></span></span></code></pre>
<p>If you set the first one to false, then it simply doesn't do anything and your site runs as before without any of the Models Builder stuff. The next one is important in terms of selecting which mode you want Models Builder to run in. There are quite a few options here, which I've tried to go through and offer the usage case for each.</p>
<h3>PureLive</h3>
<p>This is the default option with Umbraco and is designed as an easy way to get started. You shouldn't have to do anything clever and you will have strongly typed models in your views. Except that, this doesn't come with intellisense and you can't use them anywhere else apart from your views. This is all possible via some in memory compilation, at runtime.</p>
<img src="/images/models_builder_purelive.jpg" title="Models Builder - PureLive" />
<blockquote>
<p>The main point here is that it's really easy to edit your content types and templates from within Umbraco without the need for an application restart.</p>
</blockquote>
<h3>Dll Models</h3>
<p>This option generates the models within ~/App_Data/Models and then compiles them into a single dll, which is added to the bin folder of your website project. A compiled dll allows for intellisense and you can use it throughout your website project. Also, there are two options here: LiveDll and Dll mode. The first one updating (and causing an application restart) whenever content types are changed. The latter working as an opt-in update via the click of a button.</p>
<blockquote>
<p>This one is mainly for working with Visual Studio and leaving as a dll and not much else.</p>
</blockquote>
<h3>AppData Models</h3>
<p>This option generates the models within ~/App_Data/Models, but they aren't added to a dll. If you want them compiled then you can include them within Visual Studio and get intellisense and use throughout the project. Again, two options: LiveAppData and AppData. Works the same as before.</p>
<blockquote>
<p>Very similar to Dll mode but with a bit more selection over what gets compiled.</p>
</blockquote>
<h3>API Models</h3>
<p>This one is a little different in that it doesn't generate the models in the Umbraco website. You decide the location of where they are generated and then reference so that they can be used within your website project. It also relies on a Visual Studio extension and NuGet package (Umbraco.ModelsBuilder.Api) so that it can connect to your Umbraco instance. This means that it is up to you to update your models whenever a change is made to the content types. You probably don't want to generate models in the Umbraco website anymore either so it is advisable to set <code>Umbraco.ModelsBuilder.ModelsMode</code> to <code>Nothing</code> when using this method.</p>
<blockquote>
<p>This is probably useful if you normally have a separate project for all your controllers, models, custom code, etc.</p>
</blockquote>
<h3>What to use?</h3>
<p>At this point in time, I'm thinking the option which is going to get used by myself is the API mode since this allows for a defined location and a separate project. However, it is also quite feasible that I would be keen to use the PureLive mode so that I can take advantage of making quick and easy updates without having to deploy or recompile any of the code.</p>
<h4>References</h4>
<ul>
<li><a href="http://www.zpqrtbnk.net/posts/purelive-models-introduction">zpqrtbnk: PureLive Models Introduction</a></li>
<li><a href="http://www.zpqrtbnk.net/posts/beyond-purelive">zpqrtbnk: Beyond PureLive</a></li>
<li><a href="https://github.com/zpqrtbnk/Zbu.ModelsBuilder/wiki/Builder-Modes">Github: Builder Modes</a></li>
</ul>

    ]]></content>
  </entry>
	
  
  <entry>
    <title>Upgrading Umbraco</title>
    <link href="https://mozzy.dev/posts/upgrading-umbraco/"/>
    <updated>2016-05-17T00:00:00+00:00</updated>
    <id>https://mozzy.dev/posts/upgrading-umbraco/</id>
    <content type="html"><![CDATA[
      <p>During a recent project, I was tasked with upgrading a site from v4 of Umbraco to the latest and greatest. There are a few reasons for this and it doesn't come without it's challenges, but I think the end result is definitely worth it.</p>
<sub>
Note: For reference, I am talking mainly around upgrading an existing implementation of Umbraco and not migrating to another instance. Also, specifically around major releases, since patch updates rarely cause any issues and where possible you should always keep up to date if you can.
</sub>
<h3>Why Upgrade?</h3>
<p>Well, who wouldn't want to make use of the updated UI and far improved underlying architecture of Umbraco. There are many things which the HQ team (and others within the community) have been working on and a lot can change in a relatively short time in the tech world.</p>
<ul>
<li>Complete redesign</li>
<li>Works in mobile formats</li>
<li>Better editing experience</li>
<li>New service layer</li>
<li>Better performance</li>
<li>Greater support for latest technology</li>
<li>Packages!</li>
<li>etc.</li>
</ul>
<p>On the other hand, there may be problems around how the site used to be built (think WebForms/XSLT) which render it difficult to upgrade or simply too time consuming to get back on to the upgrade path and work with the <strong>best version</strong> of Umbraco. These are choices which are largely down to the client and will require some conversations around. Obviously, we'd all like to work to the latest version and be on a common playground, but sometimes other things hinder us from taking these steps.</p>
<p>The good news is that with some planning and a little bit of perserverance and knowledge it isn't actually as daunting as you think it might be. I've heard many a time that the concept of upgrading a site that was built 3-5 years ago was better off with a complete rewrite and rework of the content, including fresh designs. Whilst this might be the path you go down more often than not, sometimes it's not exactly feasible or best placed to migrate a bunch of content and then factor in all of the changes around that. For larger sites, this certainly becomes the case.</p>
<h3>What's the process?</h3>
<p>Since 7.3, largely an Umbraco upgrade can be done via NuGet without too much extra work required. This is all dealt with by the migration scripts that were added and are included with each minor release from now on (even dating back to <a href="https://github.com/umbraco/Umbraco-CMS/tree/dev-v7/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionFourOneZero">FourOneZero</a>). When you update all the files to the latest version, Umbraco will perform a check against the database and if it finds that it needs to update then you will be prompted to upgrade the database via the installer. Click the button and wait until you see the new Umbraco UI.</p>
<p>But things might not go as smooth as that, sometimes the installer might fallover or it will report that there are incompatible data types. What do you do then? When it comes to the data types, I found that you could map these to the newer counterparts or simply take a note and update those once you have performed the base upgrade. Take a note of what was there before and what you want to have afterwards. As for when it fails, find the error and look for support on the forums, or place an issue on the tracker. Everyone that does this, will help Umbraco to help others and make the process better for all.</p>
<p>At this point I'm referring mostly towards the concept of getting Umbraco working in terms of the back-office and having a working CMS. We still need to take a look at our code that actually runs the website. Above I mentioned that you might be using old technology or you might be using packages / data types that are no longer compatible. The prep work around figuring out this stuff before is important and will provide a decent comparison between where you are and where you want to be. I found that exporting the doc types, templates and macros from the database was a particularly useful exercise for this. It's quite possible that there aren't many custom implementations and that actually once you've done the database side of things, Umbraco works without any major adjustments.</p>
<p>Some of the other things you might want to look into:</p>
<ul>
<li>update the icons</li>
<li>update data types (if required)</li>
<li>figure out best use of packages</li>
<li>assess the use of doc types (it's possible to change them and sort into folders)</li>
<li>assess the use of macros (could it just be a Razor partial?)</li>
<li>check over the content</li>
</ul>
<p>Switching out WebForms/XSLT for MVC/Razor can be a time consuming task, but in the end it turns out to be an opportunity to amend some of the methods from before and update to new techniques. It's also a rather nice way of realising that XSLT was rather nasty, and in getting rid of it all you can brief a sigh of relief that another Umbraco site has moved on from the not so distant past. Figuratively speaking of course. Unfortunately, you won't be able to switch out too much when it comes to content structure, but you may be able to upgrade some of those old packages to their equivalent v7 counterparts. For example, Embedded Content now becomes Nested Content and everyone is happy.</p>
<h3>Conclusion</h3>
<p>So, you've got an old site and are thinking about taking the leap. Assess your options, figure out what is important and how big the scale of the job might be. Take backups and compare. Embrace the changes and enjoy the new world of Umbraco. It's quite a good CMS you know.</p>

    ]]></content>
  </entry>
	
  
  <entry>
    <title>Continuous delivery for .NET (revisited)</title>
    <link href="https://mozzy.dev/posts/continuous-delivery-for-dotnet-revisited/"/>
    <updated>2015-07-03T00:00:00+00:00</updated>
    <id>https://mozzy.dev/posts/continuous-delivery-for-dotnet-revisited/</id>
    <content type="html"><![CDATA[
      <p>Last year I wrote about deployments and the idea of <a href="http://tcmorris.net/blog/continuous-delivery-for-dotnet/">continuous delivery for .NET</a>. During that article I spoke about how to set up and configure TeamCity and Octopus Deploy as tools for deployment as well as adding some notes around process.</p>
<p>Well, things change and constant improvements are made, so this is a look back on that article and an update as to how the process has been modified. The good news is that the tools chosen in the first article have become staples in the deployment process and what we are talking about here is a refinement. To reiterate the purpose...</p>
<blockquote>
<p>TeamCity is the build tool, Octopus Deploy is the deployment tool.</p>
</blockquote>
<h2>TeamCity</h2>
<p>As mentioned before we are using TeamCity to build the solution, perform tests and create an artifact for deployment. We also use a template so this can be shared across projects.</p>
<ol>
<li>Configure version (<a href="https://github.com/GitTools/GitVersion">GitVersion</a>)</li>
<li>Fetch packages, build solution and run OctoPack</li>
<li>Front end tasks (e.g. npm install / grunt / gulp)</li>
<li>Perform tests and check code coverage</li>
<li>Publish package to Octopus Deploy NuGet server</li>
</ol>
<p>You may want to split this out into 2 or 3 configurations depending on requirements. Reasons for doing this would be if you wanted to run your unit tests separately (they might take a long time) or if you wanted to publish your artifact as a dependency (i.e. manual task to push the artifact which is created in your other configuration).</p>
<h3>GitVersion</h3>
<p>We are using this as a meta-runner within TeamCity, there are other options as to how you use this tool such as command line or MSBuild tasks. What this does is create our SemVer or NuGet version automatically for us based on our git history. Previously we were doing a lot of the versioning manually and then we came up with a powershell script to achieve a similar outcome until we stumbled upon this which does it all for us. It follows Gitflow and Github flow conventions and can be applied to other branching strategies with some configuration.</p>
<h2>Octopus Deploy</h2>
<p>Used to deploy an artifact (NuGet package) to a given environment, as well as setting up a website in IIS and updating variables for different SQL connections. Our process here is largely the same, yet Octopus Deploy has grown up a little since then and now has support for lifecycles, automatic release creation and (in next release) offline deployments amongst some other really useful features.</p>
<ol>
<li>Test SQL connection</li>
<li>Grab NuGet package</li>
<li>Create / update website in IIS</li>
<li>Deploy files to website folder</li>
<li>Update variables / apply transforms</li>
<li>Test URL (200 OK)</li>
<li>Notify status of deployment via Slack</li>
<li>Clean up / apply retention policies</li>
</ol>
<p>Steps 2, 3, 4 and 5 can actually be done via one step in Octopus Deploy (deploy a NuGet package), but I have split it out here for better readability. We have also added some basic tests around our deployment...</p>
<ul>
<li>Test SQL connection : if we can't access the database using the provided connection string, we don't deploy</li>
<li>Test URL : we ensure that we get a 200 OK status back once we have deployed</li>
<li>Notify status : we use Slack for sending out a deployment status (could also send an email if you prefer traditional methods)</li>
</ul>
<p>Depending on the project or usage case you might want to do other steps such as backup the database or website folder, grant permissions to a certain user, or install a package required for deployment via Chocolatey for example. There are loads of other options in the step template library: <a href="https://library.octopusdeploy.com/">https://library.octopusdeploy.com/</a></p>
<h3>Lifecycles</h3>
<p>This was introduced in 2.6 and allowed for structuring your deployment process between environments. So, you could set it up to no longer allow a release package to be deployed straight to Production without any testing for example. This forces you to take a release through the proper deployment process and get sign-off before promoting.</p>
<p>So, an example lifecycle could be set up like this...</p>
<p><strong>Internal testing</strong></p>
<ul>
<li>Dev (auto-deploy)</li>
<li>QA</li>
</ul>
<p><strong>Client testing</strong> (any 1)</p>
<ul>
<li>UAT</li>
<li>Pre Prod</li>
</ul>
<p><strong>Go live</strong> (any 1)</p>
<ul>
<li>Production</li>
<li>DR (backup servers)</li>
</ul>
<p>Within this you can specify whether all of the environments need to be deployed to or at least one in the lifecycle phase, denoted in brackets above. You can also set different retention policies per phase, so you would probably want to keep all releases in the 'go live' phase, but maybe the latest 5 in the 'internal testing' and 'client testing' phase.</p>
<h3>3.0</h3>
<p>A <a href="http://octopusdeploy.com/blog/octopus-3.0-pre-release-is-here">new version</a> of Octopus Deploy is in pre-release. With this comes a bunch of changes and new features...</p>
<ul>
<li>Deployment targets which allow for offline deployments, Azure websites, SSH and Linux support</li>
<li>Rebuilt with SQL Server rather than RavenDB</li>
<li>Improved performance</li>
<li>Something called <a href="http://octopusdeploy.com/blog/the-octopus-deploy-3.0-time-saver-delta-compression">delta compression</a>, which only transfers things that have changed in your package and should make deployments a lot quicker.</li>
<li>Migration tool so you can export your configuration into JSON and import into other instances of Octopus Deploy</li>
<li>Changes to tentacle architecture, which means that the deployment aspect of a tentacle is no longer tightly coupled to the Octopus version. Enter Calamari, a command-line tool invoked by Tentacle during a deployment for doing deployment tasks. It is also <a href="https://github.com/OctopusDeploy/Calamari">open-source</a>, so you can fork and make it your own.</li>
</ul>

    ]]></content>
  </entry>
	
  
  <entry>
    <title>ASP.NET vNext and Mac OS X</title>
    <link href="https://mozzy.dev/posts/aspnet-vnext-and-mac-osx/"/>
    <updated>2015-06-22T00:00:00+00:00</updated>
    <id>https://mozzy.dev/posts/aspnet-vnext-and-mac-osx/</id>
    <content type="html"><![CDATA[
      <p>One of the highlights of ASP.NET vNext is that it will be cross-platform. What this means is a few things...</p>
<ul>
<li>No more need for Windows VMs (designers will be happy)</li>
<li>Potential for cheaper hosting, can run ASP.NET on Linux</li>
<li>Open to more developers (plus benefits of open source also)</li>
<li>It's pretty cool.</li>
</ul>
<h3>Installing DNVM / DNX</h3>
<p>The first place to go is here: <a href="https://github.com/aspnet/Home">https://github.com/aspnet/Home</a></p>
<p>This will outline the ideas behind the next version of ASP.NET and offer some instructions for install. Below are the outlines.</p>
<hr />
<p>The key to getting set up is something called the .NET Version Manager (DNVM), which is a command line tool you use to download DNX (.NET execution environment). The DNX contains the code to bootstrap and run our applications.</p>
<blockquote>
<p>A lot of this is built into the latest preview of Visual Studio 2015.</p>
</blockquote>
<p>The steps to install DNVM on OS X are far easier if we have <a href="http://brew.sh/">Homebrew</a> installed. So to get that we need to run:</p>
<pre><code>ruby -e &quot;$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)&quot;
</code></pre>
<p>To install the DNVM:</p>
<pre><code>brew tap aspnet/dnx
brew update
brew install dnvm
</code></pre>
<p>Then, we need to ensure that the command is registered with our bash profile:</p>
<pre><code>echo &quot;source dnvm.sh&quot; &gt;&gt; ~/.bashrc
</code></pre>
<p>You can run DNVM to get the latest version of DNX so that we can run our applications:</p>
<pre><code>dnvm upgrade
</code></pre>
<h3>Creating an app</h3>
<p>Now we should have ASP.NET available to us on our Mac. The next thing we want to do is create a test application. To do this, we can use Yeoman to generate this for us. There are a few dependencies... so, to set these up we need to do some more command line entries.</p>
<p>Install node.js:</p>
<pre><code>brew install node
</code></pre>
<p>Install Yeoman:</p>
<pre><code>npm install -g yo
</code></pre>
<p>Install generator-aspnet</p>
<pre><code>npm install -g generator-aspnet
</code></pre>
<p>Details of the ASP.NET vNext generator are here: <a href="https://github.com/OmniSharp/generator-aspnet">https://github.com/OmniSharp/generator-aspnet</a></p>
<p>Now that we have the yo generator, we can type this into a command prompt:</p>
<pre><code>yo aspnet
</code></pre>
<p>... and what you should end up with is something that looks like this:</p>
<img src="/images/aspnet_vnext_1.jpg" title="generator-aspnet on OS X" width="100%" />
<p>Pretty cool huh?! In this example, I am going to choose to create a real basic console application, but the templates allow you to create web applications also.</p>
<p>After answering a few questions, we should have something that we can run and obtain the output from our test console application:</p>
<pre><code>dnu restore
dnx . run
</code></pre>
<img src="/images/aspnet_vnext_2.jpg" title="Running vNext on OS X" width="100%" />
<p>And that just about sums up how to get started with ASP.NET vNext on OS X.</p>

    ]]></content>
  </entry>
	
  
  <entry>
    <title>Umbraco Codegarden review and the future</title>
    <link href="https://mozzy.dev/posts/codegarden15-review/"/>
    <updated>2015-06-19T00:00:00+00:00</updated>
    <id>https://mozzy.dev/posts/codegarden15-review/</id>
    <content type="html"><![CDATA[
      <p>Last week I attended my first Codegarden. It was great to be able to figure out what the fuss was all about. I really enjoyed being able to meet other Umbraco devs and be a part of it all.
Rather than go in to all the details, I'll outline some of the highlights.</p>
<h3>Keynote</h3>
<p>If you hadn't already heard, here are the major announcements:</p>
<ul>
<li>7.3 beta is out and available to <a href="https://www.nuget.org/packages/UmbracoCms/7.3.0-beta">download</a></li>
<li>ASP.NET Identity including support for oAuth so that you can login to the back office with your Facebook or Google account for example.</li>
<li>Load balancing has been updated to work much better with scaling</li>
<li><a href="https://our.umbraco.org/">Our Umbraco</a> has been given a complete overhaul</li>
<li>New <a href="https://www.nuget.org/packages/UmbracoCms.RestApi/">REST API</a> for Content, Media, Members, and Relations using the HAL format. Here's a bit of reading around HAL: <a href="http://stateless.co/hal_specification.html">http://stateless.co/hal_specification.html</a></li>
<li>Content type editor changes within the back office making all those document types a joy to edit</li>
</ul>
<p>I think one of the main things to take away from this is that Umbraco want to be able to iterate in a much faster and open manner, releasing earlier versions for testing and review with the community. So, the REST API and Content type editor are examples of this.</p>
<h3>Sessions and open space</h3>
<p>In my <a href="http://tcmorris.net/blog/codegarden15-preview/">preview</a> I noted some of the sessions which took my interest. As it turned out, there were some great sessions although I felt the urge for some more in-depth talks with more of an emphasis on code. The last day in particular was what I found the most interesting and useful for me. The idea is that the schedule and topics are defined by the people attending. Each person suggests a topic of interest and people go along and discuss where the future of Umbraco lies. Being able to talk directly and in an open manner with others who share similar issues and thoughts was a decent way to provoke ideas and knowledge for the direction of Umbraco and it's community. It wasn't just code... there were also topics around quality of life, communication channels and the future of Codegarden.</p>
<h3>Social</h3>
<p>Part of what adds to the fun of Codegarden is that it is a 3 day event. Evenings are spent hanging out with other developers and there is enough time to not feel like you are there one minute and gone the next (even if it did go rather quickly).</p>
<p>This year, there was a march through Copenhagen to the meatpacking district where we were able to enjoy the clear night sky with a few drinks and good company. Umbraco bingo was as crazy as I thought it might be and the package competition had a nice comic twist to it.</p>
<p><img src="/images/nyhavn_copenhagen.jpg" alt="Nyhavn"></p>
<h3>Until next year</h3>
<p>Next year Codegarden will be moving to a new location, and I'm hoping that I'll be able to join you all for more Umbraco goodness. Until then, I intend to get much more involved with the community and start giving back. Following on from the open space at Codegarden around what you would like to see Umbraco achieve in the next 12 months, here are a few that I've come up with for myself.</p>
<ul>
<li>I have already logged a number of issues re: Our Umbraco and they have been fixed very quickly (kudos on that), it is a simple process but helps shape things to how you might want them. It's also handy to find some bugs and make Umbraco aware.</li>
<li>Submit some pull requests and help fix bugs / add new features. #1 : <a href="http://issues.umbraco.org/issue/U4-6562">http://issues.umbraco.org/issue/U4-6562</a></li>
<li>Attend and present at local events such as <a href="http://www.meetup.com/umBristol/">umBristol</a>. Presenting is still quite a new concept to me and something which I struggle getting to grips with, I'm sure as I throw myself more into these kind of situations I'll become more comfortable.</li>
<li>Kickstart some kind of annual event in the South West. There has been a number of people interested in this, it would be awesome if we could make this happen!</li>
<li>Start creating some packages! Not just for the sake of it, but there are times when we as developers work on a project and it would be good to share some of the more useful custom implementations we have done.</li>
<li>Write an article for the totally awesome <a href="http://skrift.io/">Skrift.io</a>.</li>
<li>Build a new website for my football team on the latest version of Umbraco and using some of the latest methodologies (e.g. strongly typed models for one). This one is currently in progress and I will be hoping to release this within the next couple of months.</li>
</ul>
<p><strong>So there you have it, let's see how much of this I can actually complete.</strong></p>

    ]]></content>
  </entry>
	
  
  <entry>
    <title>Umbraco Codegarden preview</title>
    <link href="https://mozzy.dev/posts/codegarden15-preview/"/>
    <updated>2015-06-03T00:00:00+00:00</updated>
    <id>https://mozzy.dev/posts/codegarden15-preview/</id>
    <content type="html"><![CDATA[
      <p>It seems like the Umbraco community has a particular buzz around this time of year. I have heard quite a few stories about <a href="http://codegarden15.com/">Codegarden</a>, the Umbraco conference which takes place every summer. It is of course situated in Denmark, the birth place of Umbraco and for a number of years now people have been flocking to Copenhagen to hear more about what is on the horizon for this open-source .NET CMS.</p>
<p>I have been working with Umbraco for a while now so it was probably about time that I managed to get a ticket... yes this will be my <a href="http://uhangout.co.uk/videos/ep061-with-the-umbraco-community-pre-codegarden15/">first Codegarden</a>! Big thanks to <a href="https://www.thisiszone.com/join">Zone</a> for making that happen.</p>
<p>After looking at the <a href="http://codegarden15.com/schedule">schedule</a>, here are a few that I have picked out...</p>
<p><strong>Umbraco Roadmap Panel</strong></p>
<p>Find out about all that is coming up in future releases of Umbraco. Version 7 was a big step, but Umbraco is a product that keeps on moving. There have also been some rather big changes within Microsoft and .NET itself and so it could be that we hear about how Umbraco will be looking to integrate with <a href="https://github.com/aspnet/home">vNext</a>. I'm really looking forward to see what is in store.</p>
<p><strong>How to develop a killer package</strong></p>
<p>Lee and Matt outline all that is required to make a package and get it out on the appropriate channels. Kind of like an overview of how to contribute to Umbraco with new ideas or improvements. As someone who would like to get more involved in this side of things, it should prove to be a helpful guide.</p>
<p><strong>Beyond the web</strong></p>
<p>We primarily see Umbraco as a traditional CMS which maps directly to website content and it's HTML. This session looks to help us realise that Umbraco can be used for other purposes and that this can be tied with all sorts of other connected devices. One for the future maybe.</p>
<p><strong>Securing Your Umbraco</strong></p>
<p>We build Umbraco websites on a regular basis and many of these are live at present. All across the world, there could be someone who has malicious intentions towards your website. This session looks at preventing that. This is something I'm hoping I won't walk away from with too much shock, but it's definitely an important aspect of maintaining websites.</p>
<h3>See you there</h3>
<p>I have only listed a few here, but there is a great schedule and I'm sure there will be sessions outside of the above which will really take my attention. For instance, the sessions geared towards customising Umbraco, using ReactJS with Umbraco or how to deal with load balancing and then there are also the workshops...</p>
<p>And of course getting to meet all the people that I follow on Twitter whilst sharing a drink or two will be great too. (I'm a big fan of <a href="http://mikkeller.dk/">Mikkeller</a> btw)</p>
<p>For all those that are attending this year, see you at Codegarden! And to everyone else, be sure to keep track of all of the updates and find out all that is happening with the world of Umbraco.</p>

    ]]></content>
  </entry>
	
  
  <entry>
    <title>Awesome Umbraco</title>
    <link href="https://mozzy.dev/posts/awesome-umbraco/"/>
    <updated>2015-05-01T00:00:00+00:00</updated>
    <id>https://mozzy.dev/posts/awesome-umbraco/</id>
    <content type="html"><![CDATA[
      <p>Many of you are probably aware that one of the great things about Umbraco is the fact that it is easily extendable and can be used for all sorts of flexible solutions. This is mostly down to the community and the people who are constantly building upon a solid foundation.</p>
<p>It would be a shame for all this great work to go unnoticed and so <a href="https://twitter.com/leekelleher">Lee Keheller</a> has created a repository that showcases some of these packages and groups them into their use.</p>
<blockquote>
<p>A collection of awesome Umbraco 7 packages, resources and shiny things.</p>
</blockquote>
<h3>Next steps</h3>
<p>Check out the <a href="https://github.com/leekelleher/awesome-umbraco">Github repo</a> and add some packages to the list!</p>

    ]]></content>
  </entry>
	
  
  <entry>
    <title>Using a custom domain for accessing umbraco</title>
    <link href="https://mozzy.dev/posts/custom-domain-for-umbraco/"/>
    <updated>2015-03-16T00:00:00+00:00</updated>
    <id>https://mozzy.dev/posts/custom-domain-for-umbraco/</id>
    <content type="html"><![CDATA[
      <p>By default, content editors will be editing their content by appending umbraco to their domain. Sometimes you might not want your content editor to use that method and would like them to use an alternative URL. This could be for a few reasons...</p>
<ul>
<li>You don't want Joe public trying to access the Umbraco back-office on your site. This is more security for obscurity and therefore isn't necessarily a perfect solution, but by changing the link to Umbraco, it does partially lock it down. Note, if you set a hostname on your server to the URL you want to use and then point your hosts file to the server it is possible to prevent /umbraco from being publically accessible. i.e. it is only local to the server.</li>
<li>You want to create a different URL for your content editor to use when editing content. Perhaps it might be nicer for them to use or they only want the Umbraco side of things to be under SSL.</li>
<li>You have multiple sites within one Umbraco instance. This actually makes it a lot easier to group sites into one entity, otherwise each site will have their own Umbraco URL. One URL to remember, one URL to use.</li>
</ul>
<p>Below is an example of how to do this. We match the URL for Umbraco and then perform a redirect to our not found page if it doesn't match our pattern. Note this part: <strong>(?!Surface)</strong> - this is important as it means that AJAX calls using Surface controllers still work.</p>
<p>Therefore, when editing the Umbraco site and assuming will only have an SSL certificate for Umbraco, a content editor will use:</p>
<blockquote>
<p>https://admin.example.com/umbraco/</p>
</blockquote>
<p>Whereas, the site will be visible at:</p>
<blockquote>
<p>http://www.example.com/</p>
</blockquote>
<p>If you have done something similar or have alternatives that you use, then please feel free to leave a comment!</p>
<pre class="language-xml"><code class="language-xml"><span class="highlight-line"><span class="token comment">&lt;!-- Restrict access to Umbraco --></span></span><br><span class="highlight-line"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>rule</span> <span class="token attr-name">name</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>Restrict access<span class="token punctuation">"</span></span> <span class="token attr-name">stopProcessing</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>true<span class="token punctuation">"</span></span><span class="token punctuation">></span></span></span><br><span class="highlight-line">    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>match</span> <span class="token attr-name">url</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>umbraco(?!/Surface/)<span class="token punctuation">"</span></span> <span class="token punctuation">/></span></span></span><br><span class="highlight-line">    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>conditions</span> <span class="token attr-name">logicalGrouping</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>MatchAny<span class="token punctuation">"</span></span> <span class="token attr-name">trackAllCaptures</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>false<span class="token punctuation">"</span></span><span class="token punctuation">></span></span></span><br><span class="highlight-line">        <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>add</span> <span class="token attr-name">input</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>{HTTP_HOST}<span class="token punctuation">"</span></span> <span class="token attr-name">matchType</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>Pattern<span class="token punctuation">"</span></span> <span class="token attr-name">pattern</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>admin.example.com<span class="token punctuation">"</span></span> <span class="token attr-name">ignoreCase</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>true<span class="token punctuation">"</span></span> <span class="token attr-name">negate</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>true<span class="token punctuation">"</span></span> <span class="token punctuation">/></span></span></span><br><span class="highlight-line">    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>conditions</span><span class="token punctuation">></span></span></span><br><span class="highlight-line">    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>action</span> <span class="token attr-name">type</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>Redirect<span class="token punctuation">"</span></span> <span class="token attr-name">url</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>/not-found<span class="token punctuation">"</span></span> <span class="token attr-name">appendQueryString</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>false<span class="token punctuation">"</span></span> <span class="token punctuation">/></span></span></span><br><span class="highlight-line"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>rule</span><span class="token punctuation">></span></span></span></code></pre>

    ]]></content>
  </entry>
	
  
  <entry>
    <title>Page Not Found in Umbraco</title>
    <link href="https://mozzy.dev/posts/page-not-found-umbraco/"/>
    <updated>2015-03-02T00:00:00+00:00</updated>
    <id>https://mozzy.dev/posts/page-not-found-umbraco/</id>
    <content type="html"><![CDATA[
      <p>Content finders in Umbraco are really useful as they can intercept the routing and give you access to the context. There are a few uses of this and one on those is to find your page not found page that you have created especially in Umbraco. This differs from the more traditional way of setting a page id within your umbracoSettings.config file and is useful for giving your client complete control over their page not found page. So, in the example below, there would be a corresponding document type in Umbraco called <strong>NotFoundPage</strong>.</p>
<pre class="language-csharp"><code class="language-csharp"><span class="highlight-line"><span class="token keyword">using</span> <span class="token namespace">System<span class="token punctuation">.</span>Linq</span><span class="token punctuation">;</span></span><br><span class="highlight-line"><span class="token keyword">using</span> <span class="token namespace">Umbraco<span class="token punctuation">.</span>Core</span><span class="token punctuation">;</span></span><br><span class="highlight-line"><span class="token keyword">using</span> <span class="token namespace">Umbraco<span class="token punctuation">.</span>Core<span class="token punctuation">.</span>Models</span><span class="token punctuation">;</span></span><br><span class="highlight-line"><span class="token keyword">using</span> <span class="token namespace">Umbraco<span class="token punctuation">.</span>Web</span><span class="token punctuation">;</span></span><br><span class="highlight-line"><span class="token keyword">using</span> <span class="token namespace">Umbraco<span class="token punctuation">.</span>Web<span class="token punctuation">.</span>Routing</span><span class="token punctuation">;</span></span><br><span class="highlight-line"></span><br><span class="highlight-line"><span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">PageNotFoundContentFinder</span> <span class="token punctuation">:</span> <span class="token type-list"><span class="token class-name">IContentFinder</span></span></span><br><span class="highlight-line"><span class="token punctuation">{</span></span><br><span class="highlight-line">    <span class="token keyword">public</span> <span class="token return-type class-name"><span class="token keyword">bool</span></span> <span class="token function">TryFindContent</span><span class="token punctuation">(</span><span class="token class-name">PublishedContentRequest</span> request<span class="token punctuation">)</span></span><br><span class="highlight-line">    <span class="token punctuation">{</span></span><br><span class="highlight-line">        <span class="token comment">// have we got any content?</span></span><br><span class="highlight-line">        <span class="token keyword">if</span> <span class="token punctuation">(</span>request<span class="token punctuation">.</span>PublishedContent <span class="token operator">==</span> <span class="token keyword">null</span><span class="token punctuation">)</span></span><br><span class="highlight-line">        <span class="token punctuation">{</span></span><br><span class="highlight-line">            <span class="token comment">// Get the root node for domain</span></span><br><span class="highlight-line">            <span class="token class-name"><span class="token keyword">var</span></span> home <span class="token operator">=</span> request<span class="token punctuation">.</span>RoutingContext<span class="token punctuation">.</span>UmbracoContext<span class="token punctuation">.</span>ContentCache<span class="token punctuation">.</span><span class="token function">GetByRoute</span><span class="token punctuation">(</span>request<span class="token punctuation">.</span>Domain<span class="token punctuation">.</span>RootNodeId <span class="token operator">+</span> <span class="token string">"/"</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span><br><span class="highlight-line"></span><br><span class="highlight-line">            <span class="token comment">// Try and find the 404 node</span></span><br><span class="highlight-line">            <span class="token class-name"><span class="token keyword">var</span></span> notFoundNode <span class="token operator">=</span> home<span class="token punctuation">.</span>Children<span class="token punctuation">.</span><span class="token function">Where</span><span class="token punctuation">(</span>x <span class="token operator">=></span> x<span class="token punctuation">.</span>DocumentTypeAlias <span class="token operator">==</span> <span class="token string">"NotFoundPage"</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">FirstOrDefault</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span><br><span class="highlight-line">            <span class="token keyword">if</span> <span class="token punctuation">(</span>notFoundNode <span class="token operator">!=</span> <span class="token keyword">null</span><span class="token punctuation">)</span></span><br><span class="highlight-line">            <span class="token punctuation">{</span></span><br><span class="highlight-line">                <span class="token comment">// Set Response Status to be HTTP 404</span></span><br><span class="highlight-line">                request<span class="token punctuation">.</span><span class="token function">SetResponseStatus</span><span class="token punctuation">(</span><span class="token number">404</span><span class="token punctuation">,</span> <span class="token string">"404 Page Not Found"</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span><br><span class="highlight-line"></span><br><span class="highlight-line">                <span class="token comment">// Set the node to be the not found node</span></span><br><span class="highlight-line">                request<span class="token punctuation">.</span>PublishedContent <span class="token operator">=</span> notFoundNode<span class="token punctuation">;</span></span><br><span class="highlight-line">            <span class="token punctuation">}</span></span><br><span class="highlight-line">        <span class="token punctuation">}</span></span><br><span class="highlight-line"></span><br><span class="highlight-line">        <span class="token comment">// hopefully we will have content at this point</span></span><br><span class="highlight-line">        <span class="token keyword">return</span> request<span class="token punctuation">.</span>PublishedContent <span class="token operator">!=</span> <span class="token keyword">null</span><span class="token punctuation">;</span></span><br><span class="highlight-line">    <span class="token punctuation">}</span></span><br><span class="highlight-line"><span class="token punctuation">}</span></span></code></pre>

    ]]></content>
  </entry>
	
  
  <entry>
    <title>Courier investigation</title>
    <link href="https://mozzy.dev/posts/courier-investigation/"/>
    <updated>2015-02-24T00:00:00+00:00</updated>
    <id>https://mozzy.dev/posts/courier-investigation/</id>
    <content type="html"><![CDATA[
      <h3>Installation</h3>
<p>Download from here: <a href="https://our.umbraco.org/projects/umbraco-pro/umbraco-courier-2">https://our.umbraco.org/projects/umbraco-pro/umbraco-courier-2</a></p>
<ul>
<li>Go to required instance of Umbraco to install on.</li>
<li>Go to Developer tab</li>
<li>Open up packages folder and select Install local package</li>
<li>Choose downloaded zip file</li>
<li>Confirm install</li>
<li>Wait for Umbraco to reload</li>
<li>Add location(s) you would like to promote to</li>
</ul>
<p><strong>Example location</strong></p>
<p>This is configurable in <em>courier.config</em></p>
<pre class="language-xml"><code class="language-xml"><span class="highlight-line"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>repository</span> <span class="token attr-name">name</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>Example QA site<span class="token punctuation">"</span></span> <span class="token attr-name">alias</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>example-qa<span class="token punctuation">"</span></span> <span class="token attr-name">type</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>CourierWebserviceRepositoryProvider<span class="token punctuation">"</span></span> <span class="token attr-name">visible</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>true<span class="token punctuation">"</span></span><span class="token punctuation">></span></span></span><br><span class="highlight-line">  <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>url</span><span class="token punctuation">></span></span>http://test.client.example.co.uk/<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>url</span><span class="token punctuation">></span></span></span><br><span class="highlight-line">  <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>user</span><span class="token punctuation">></span></span>0<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>user</span><span class="token punctuation">></span></span></span><br><span class="highlight-line"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>repository</span><span class="token punctuation">></span></span></span></code></pre>
<p>Courier works on the basis of having a connection between Umbraco instances and then being able to compare and push changes. If there is no connection for Umbraco, then a sync will not be possible. This also means that Courier needs to be installed on all environments that need to be in sync.</p>
<h3>Usage</h3>
<p>Once the locations have been set up and proven to work. i.e. they are able to connect without error, the usage from a client perspective is rather simple.</p>
<p><strong>Basic usage</strong></p>
<p>There will be a new context-sensitive option when selecting content called Courier. When this is selected a new window will open asking for a target machine to deploy to, along with confirmation of what content will be transferred. Click the button to deploy and wait for Courier to package the content and transfer across to the other location.</p>
<p><strong>Revisions</strong></p>
<p>An alternative to using the context-sensitive option is to go into the newly added Courier section where you can add a revision. This allows you to choose more than just content and let's you choose things like Dictionary items, Document types, Languages, Media among others. So, if you had created a bunch of content that had some media and potentially some files you wanted to deploy, you could create a revision to transfer elsewhere. The idea is that whatever needs to be transferred, can be. Courier will also help you out and sort out the dependencies if there are any. Once you have selected your options and created your revision (package), then this will be available on other locations to transfer.</p>
<p><strong>Configuration</strong></p>
<p>Since Courier has is it's own section, there is the option to restrict access to revisions. It is possible that you may only want to give developers access to this section whilst giving clients access to the basic use of selecting content. If you do wish to give clients access to the Courier section, then you can also choose what you want them to be able to transfer. So, you probably wouldn't want them to know about the Datatypes or Document types, but you would probably want them to be able to transfer Files, Folders and Media.</p>
<p>By default, Courier is set up quite nicely and will cover most usage cases however there are some other configuration options that might be preferable.</p>
<p>Choose which folders can be included in revisions.</p>
<pre class="language-xml"><code class="language-xml"><span class="highlight-line"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>folderItemProvider</span><span class="token punctuation">></span></span></span><br><span class="highlight-line">  <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>include</span><span class="token punctuation">></span></span></span><br><span class="highlight-line">    <span class="token comment">&lt;!--&lt;folder>~/media/assets/somefolder&lt;/folder>--></span></span><br><span class="highlight-line">  <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>include</span><span class="token punctuation">></span></span></span><br><span class="highlight-line"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>folderItemProvider</span><span class="token punctuation">></span></span></span><br><span class="highlight-line"></span><br><span class="highlight-line">Choose which files can be included in revisions.</span><br><span class="highlight-line"></span><br><span class="highlight-line">```xml</span><br><span class="highlight-line"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>fileItemProvider</span><span class="token punctuation">></span></span></span><br><span class="highlight-line">  <span class="token comment">&lt;!--&lt;folder>~/media/assets/somefolder&lt;/folder>--></span></span><br><span class="highlight-line">  <span class="token comment">&lt;!--&lt;file>~/media/assets/somefile.png&lt;/file>--></span></span><br><span class="highlight-line"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>fileItemProvider</span><span class="token punctuation">></span></span></span></code></pre>
<p>Allow for children/parent media to be included.</p>
<pre class="language-xml"><code class="language-xml"><span class="highlight-line"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>mediaItemProvider</span><span class="token punctuation">></span></span></span><br><span class="highlight-line">  <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>includeChildren</span><span class="token punctuation">></span></span>false<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>includeChildren</span><span class="token punctuation">></span></span></span><br><span class="highlight-line">  <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>includeParents</span><span class="token punctuation">></span></span>true<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>includeParents</span><span class="token punctuation">></span></span></span><br><span class="highlight-line"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>mediaItemProvider</span><span class="token punctuation">></span></span></span></code></pre>
<p>Allow/deny access by IP/users. (in security element)</p>
<pre class="language-xml"><code class="language-xml"><span class="highlight-line"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>filters</span><span class="token punctuation">></span></span></span><br><span class="highlight-line">  <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>ipfilter</span><span class="token punctuation">></span></span></span><br><span class="highlight-line">    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>allow</span><span class="token punctuation">></span></span>*<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>allow</span><span class="token punctuation">></span></span></span><br><span class="highlight-line">  <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>ipfilter</span><span class="token punctuation">></span></span></span><br><span class="highlight-line">  <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>userfilter</span><span class="token punctuation">></span></span></span><br><span class="highlight-line">    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>allow</span><span class="token punctuation">></span></span>*<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>allow</span><span class="token punctuation">></span></span></span><br><span class="highlight-line">    <span class="token comment">&lt;!--&lt;deny>editor&lt;/deny>--></span></span><br><span class="highlight-line">  <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>userfilter</span><span class="token punctuation">></span></span></span><br><span class="highlight-line"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>filters</span><span class="token punctuation">></span></span></span></code></pre>

    ]]></content>
  </entry>
	
  
  <entry>
    <title>Continuous delivery for .NET</title>
    <link href="https://mozzy.dev/posts/continuous-delivery-for-dotnet/"/>
    <updated>2014-10-09T00:00:00+00:00</updated>
    <id>https://mozzy.dev/posts/continuous-delivery-for-dotnet/</id>
    <content type="html"><![CDATA[
      <p>One very important factor of being a developer is deploying your code to the appropriate environment without anything failing. In order to do this, we should be automating as many tasks as possible to reduce human failure. Of course, some degree of human interaction should happen but by in large, we shouldn't need to do much once we have set up our deployment process.</p>
<h2>Simple guide</h2>
<p>At it's very basic, this should happen every time we work on a project.</p>
<ol>
<li>Create project + repo</li>
<li>Write some code</li>
<li>Push some code to repo</li>
<li>Grab code and push to server</li>
</ol>
<p>Now... parts 1, 2 and 3 will largely be the same wherever, but 4 could be done a number of different ways and there are various different settings / updates required to get a working website. Let's not go into too much details of the different options, but look at a particular method for making this work.</p>
<h2>TeamCity and Octopus Deploy</h2>
<p>In order to for us to deploy, we are going to use TeamCity and Octopus Deploy. There is a bit of configuration required to do so, but this should be simpler than the traditional Web Deploy method.</p>
<p>It is worth noting that one of the goals in deployment is to allow different roles within the process. So, the devs can push code and then the sysadmins or tech leads can manage deployments. Therefore, publish from Visual Studio is completely out of the question. This has a few advantages in that the relevant people are in charge of their remit. For example, a dev doesn't have the ability to push changes to Production and therefore a degree of protection / sign-off is involved. sysadmins can create a new server and see at a granular level what gets pushed if they choose to. Important server details are not exposed, which can be the case with Web Deploy.</p>
<p>Below is the basic overview of steps required in set up...</p>
<ol>
<li>Install TeamCity on build server (one time only)</li>
<li>Install <a href="http://docs.octopusdeploy.com/display/OD/TeamCity">Octopus TeamCity plugin</a> (one time only)</li>
<li>Install <a href="http://docs.octopusdeploy.com/display/OD/Installing+Octopus">Octopus Server</a> on build server (one time only)</li>
<li>Create servers for project (one time only for each project)</li>
<li>Install <a href="http://docs.octopusdeploy.com/display/OD/Installing+Tentacles">Octopus Tentacle</a> on required servers (one time only for each server)</li>
<li>Install <a href="http://docs.octopusdeploy.com/display/OD/Using+OctoPack">OctoPack</a> in project via NuGet (one time only for each project)</li>
</ol>
<p>As shown, a lot of these tasks you will not need to revisit and once completed, will allow you to deploy without the need for manual intervention.</p>
<p><strong>TeamCity</strong></p>
<p>Used to build the solution, perform tests and create an artifact for deployment. This will have continuous integration set up for the dev branch so that we don't have to trigger the release each time. We can use a template to share this across projects.</p>
<ol>
<li>Checkout repository and build solution (run OctoPack)</li>
<li>Perform tests and check code coverage</li>
<li>Publish package to Octopus NuGet server</li>
<li>Create Octopus release (trigger Octopus Deploy)</li>
</ol>
<p><strong>Octopus Deploy</strong></p>
<p>Used to deploy an artifact to a given environment, as well as setting up a website in IIS and updating variables for different SQL connections. This all happens on the server we are deploying to via a secure connection.</p>
<ol>
<li>Grab NuGet package</li>
<li>Create website in IIS</li>
<li>Deploy files to website folder</li>
<li>Update variables / apply transforms</li>
<li>Clean up / apply retention policies</li>
</ol>
<p>When a release is created, Octopus Deploy will keep this indefinitely unless you tell it to. This means that you can rollback quickly to a prior release, but also means that you could be left with a number of files left on the server that you don't want. Therefore, within Octopus Portal you can amend the number of releases you want to keep and for how many days. More info can be found in the <a href="http://docs.octopusdeploy.com/display/OD/Retention+policies">documentation</a>.</p>
<p><strong>Why use both?</strong></p>
<p>It is true that you could use TeamCity to deploy to each environment and perform configurations for you. However, this is reliant on Web Deploy being installed on the server you wish to deploy to. This is not a requirement for Octopus Deploy, which uses the idea of tentacles to open up a communication between the build server and the web server. This has several <a href="http://docs.octopusdeploy.com/pages/viewpage.action?pageId=360622">security enhancements</a> and is generally easier to configure. You could also get Octopus Deploy to set up a site in IIS or perform Powershell tasks for you, something TeamCity and other build platforms are not built for.</p>
<p>All in all, it is about using what is built for the task at hand. TeamCity can be used for building the code, running the tests and creating a single release package. Octopus Deploy can then be used to deploy this NuGet package wherever you want and ensure that the configuration is correct for the environment, even cleaning up files in the process.</p>
<p>If you would like to read more, there is a <a href="http://octopusdeploy.com/blog/octopus-vs-build-server">blog post</a> detailing this approach, which explains why Octopus Deploy was created.</p>
<h2>Example setup</h2>
<ul>
<li>1 build server with TeamCity and Octopus server installed</li>
<li>1 web/db server for internal Development/QA (shared web and db)</li>
<li>1 web/db server for UAT (could be separate web and db)</li>
<li>1 web/db server for Production (could be separate web and db)</li>
</ul>
<p>In your project you would need the following <strong>transforms</strong>...</p>
<ul>
<li>Web.Development.config</li>
<li>Web.QA.config</li>
<li>Web.UAT.config</li>
<li>Web.Production.config</li>
</ul>
<p>These will get run automatically when uploaded to the web server by Octopus Deploy. There are a couple of things to take note of, however. Ensure that the transform matches the environment name in Octopus Deploy and make sure that the files are included in the NuGet package. For more notes on this, check the <a href="http://docs.octopusdeploy.com/display/OD/Configuration+files">documentation</a>.</p>
<p>Octopus Deploy also has this idea of <strong>variables</strong> that can be set within the Octopus Portal (admin area). This means that you can define your variables and specify which environment these will apply to. As long as you have these turned on for your project, they will overwrite the name/value pairs within your config files (not just web.config). There is also the added benefit of being able to define variable sets and inherit these on a project. One such example, could be a set of logging options that you only enable for UAT and Production, but you tend to do this on every project. With a variable set, you can ensure they are included with little configuration. See the <a href="http://docs.octopusdeploy.com/display/OD/Variables">documentation</a> for more examples.</p>

    ]]></content>
  </entry>
	
  
  <entry>
    <title>What&#39;s Jekyll?</title>
    <link href="https://mozzy.dev/posts/whats-jekyll/"/>
    <updated>2012-02-06T00:00:00+00:00</updated>
    <id>https://mozzy.dev/posts/whats-jekyll/</id>
    <content type="html"><![CDATA[
      <p><a href="http://jekyllrb.com">Jekyll</a> is a static site generator, an open-source tool for creating simple yet powerful websites of all shapes and sizes. From <a href="https://github.com/mojombo/jekyll/blob/master/README.markdown">the project's readme</a>:</p>
<blockquote>
<p>Jekyll is a simple, blog aware, static site generator. It takes a template directory [...] and spits out a complete, static website suitable for serving with Apache or your favorite web server. This is also the engine behind GitHub Pages, which you can use to host your project’s page or blog right here from GitHub.</p>
</blockquote>
<p>It's an immensely useful tool and one we encourage you to use here with Hyde.</p>
<p>Find out more by <a href="https://github.com/mojombo/jekyll">visiting the project on GitHub</a>.</p>

    ]]></content>
  </entry>
	
</feed>
