Error On Line One2013-08-22T17:32:10-07:00http://erroronlineone.comWilliam HorbeltCreating Structure When Creating a New Node in Umbraco 62013-08-22T00:00:00-07:00http://erroronlineone.com/2013/08/22/creating-structure-when-creating-a-new-node-in-umbraco-6<h2>The situation</h2>
<p>Umbraco is an amazing CMS that let’s you define your own data, structure it your way and display it however you want using templates.</p>
<p>I’ve built several websites in the past with recipe sections. A recipe could have multiple lists of ingredients or multiple lists of instructions.</p>
<p>You could just have one or two rich-text editor properties and maybe it will work out, but if you are trying to control the output on the templates you want more control over the input.</p>
<p>Using additional document types which define properties for ingredients and directions I end up using the following structure:</p>
<pre><code>Recipe doctype
Ingredients doctype (for organization)
Ingredients List doctype
Directions doctype (for organization)
Directions List doctype
</code></pre>
<h2>The problem</h2>
<p>The problem with the above setup is that it requires a user to create multiple nodes whenever they want to create a recipe.</p>
<p>My original solution was to just create a unpublished recipe node with the sub structure and just copy it as needed.</p>
<p>While working on a recent project I explored the idea of automatic node creation.</p>
<h2>A solution</h2>
<p>Umbraco has an events system that let’s you wire up your own actions whenever something happens.</p>
<p>For the above I was interested in <em>when a specific document type is created: create additional nodes.</em></p>
<p>Start by creating a new class file in the App_Code folder. It will extend ApplicationEventHandler.</p>
<div class="highlight"><pre><code class="csharp"><span class="lineno"> 1</span> <span class="k">using</span> <span class="nn">System</span><span class="p">;</span>
<span class="lineno"> 2</span> <span class="k">using</span> <span class="nn">Umbraco.Core</span><span class="p">;</span>
<span class="lineno"> 3</span> <span class="k">using</span> <span class="nn">Umbraco.Core.Events</span><span class="p">;</span>
<span class="lineno"> 4</span> <span class="k">using</span> <span class="nn">Umbraco.Core.Models</span><span class="p">;</span>
<span class="lineno"> 5</span> <span class="k">using</span> <span class="nn">Umbraco.Core.Services</span><span class="p">;</span>
<span class="lineno"> 6</span>
<span class="lineno"> 7</span> <span class="k">public</span> <span class="k">class</span> <span class="nc">NewRecipeNodeEventHandler</span> <span class="p">:</span> <span class="n">ApplicationEventHandler</span>
<span class="lineno"> 8</span> <span class="p">{</span>
<span class="lineno"> 9</span> <span class="k">public</span> <span class="nf">NewRecipeNodeEventHandler</span><span class="p">()</span>
<span class="lineno">10</span> <span class="p">{</span>
<span class="lineno">11</span> <span class="n">ContentService</span><span class="p">.</span><span class="n">Created</span> <span class="p">+=</span> <span class="n">ContentService_Created_Recipe</span><span class="p">;</span>
<span class="lineno">12</span> <span class="p">}</span>
<span class="lineno">13</span>
<span class="lineno">14</span> <span class="k">private</span> <span class="k">void</span> <span class="nf">ContentService_Created_Recipe</span><span class="p">(</span><span class="n">IContentService</span> <span class="n">sender</span><span class="p">,</span> <span class="n">NewEventArgs</span><span class="p"><</span><span class="n">IContent</span><span class="p">></span> <span class="n">e</span><span class="p">)</span>
<span class="lineno">15</span> <span class="p">{</span>
<span class="lineno">16</span> <span class="k">if</span> <span class="p">(</span><span class="n">e</span><span class="p">.</span><span class="n">Entity</span><span class="p">.</span><span class="n">ContentType</span><span class="p">.</span><span class="n">Alias</span><span class="p">.</span><span class="n">Equals</span><span class="p">(</span><span class="s">"Recipe"</span><span class="p">,</span> <span class="n">StringComparison</span><span class="p">.</span><span class="n">CurrentCultureIgnoreCase</span><span class="p">))</span>
<span class="lineno">17</span> <span class="p">{</span>
<span class="lineno">18</span> <span class="k">try</span>
<span class="lineno">19</span> <span class="p">{</span>
<span class="lineno">20</span> <span class="kt">var</span> <span class="n">ingredients</span> <span class="p">=</span> <span class="n">sender</span><span class="p">.</span><span class="n">CreateContent</span><span class="p">(</span><span class="s">"Ingredients"</span><span class="p">,</span> <span class="n">e</span><span class="p">.</span><span class="n">Entity</span><span class="p">.</span><span class="n">Id</span><span class="p">,</span> <span class="s">"Ingredients"</span><span class="p">);</span>
<span class="lineno">21</span> <span class="n">sender</span><span class="p">.</span><span class="n">Save</span><span class="p">(</span><span class="n">ingredients</span><span class="p">);</span>
<span class="lineno">22</span>
<span class="lineno">23</span> <span class="kt">var</span> <span class="n">ingredientList</span> <span class="p">=</span> <span class="n">sender</span><span class="p">.</span><span class="n">CreateContent</span><span class="p">(</span><span class="s">"List 1"</span><span class="p">,</span> <span class="n">ingredients</span><span class="p">.</span><span class="n">Id</span><span class="p">,</span> <span class="s">"IngredientList"</span><span class="p">);</span>
<span class="lineno">24</span> <span class="n">sender</span><span class="p">.</span><span class="n">Save</span><span class="p">(</span><span class="n">ingredientList</span><span class="p">);</span>
<span class="lineno">25</span>
<span class="lineno">26</span> <span class="kt">var</span> <span class="n">directions</span> <span class="p">=</span> <span class="n">sender</span><span class="p">.</span><span class="n">CreateContent</span><span class="p">(</span><span class="s">"Directions"</span><span class="p">,</span> <span class="n">e</span><span class="p">.</span><span class="n">Entity</span><span class="p">.</span><span class="n">Id</span><span class="p">,</span> <span class="s">"Directions"</span><span class="p">);</span>
<span class="lineno">27</span> <span class="n">sender</span><span class="p">.</span><span class="n">Save</span><span class="p">(</span><span class="n">directions</span><span class="p">);</span>
<span class="lineno">28</span>
<span class="lineno">29</span> <span class="kt">var</span> <span class="n">directionsList</span> <span class="p">=</span> <span class="n">sender</span><span class="p">.</span><span class="n">CreateContent</span><span class="p">(</span><span class="s">"List 1"</span><span class="p">,</span> <span class="n">directions</span><span class="p">.</span><span class="n">Id</span><span class="p">,</span> <span class="s">"DirectionList"</span><span class="p">);</span>
<span class="lineno">30</span> <span class="n">sender</span><span class="p">.</span><span class="n">Save</span><span class="p">(</span><span class="n">directionsList</span><span class="p">);</span>
<span class="lineno">31</span> <span class="p">}</span>
<span class="lineno">32</span> <span class="k">catch</span> <span class="p">(</span><span class="n">Exception</span><span class="p">)</span>
<span class="lineno">33</span> <span class="p">{</span>
<span class="lineno">34</span>
<span class="lineno">35</span> <span class="p">}</span>
<span class="lineno">36</span> <span class="p">}</span>
<span class="lineno">37</span> <span class="p">}</span>
</code></pre></div>
<p>The code starts by assigning our own event function to Umbraco’s ContentService.Created event handler.</p>
<p>When a new document is created ContentService_Created_Recipe is called and starts by checking the alias of the created document and if it matches create multiple new nodes, saving them along the way.</p>
<p>Since this could fail if a new content alias doesn’t exist I wrapped the content creation code in a try/catch just so the nothing breaks in Umbraco.</p>
<p>I have no idea if this can be improved upon or if there are any potential problems but it is working out fine for now.</p>
<p>References:</p>
<ol>
<li><a href="http://our.umbraco.org/forum/developers/extending-umbraco/38477-ContentService-Created-Event-Entity-doesnt-have-ID">ContentService Created Event – Entity doesn’t have ID</a></li>
<li><a href="http://www.vanarkel.net/umbraco-cms/default-values.aspx">Default values for the properties of you document types</a></li>
<li><a href="http://our.umbraco.org/wiki/reference/api-cheatsheet/attaching-document-event-handlers">Attaching Document Event Handlers</a></li>
</ol>
Ten Goals for 20132013-07-02T00:00:00-07:00http://erroronlineone.com/2013/07/02/goals<p>My current employer uses goals as part of their yearly review process but I want to set my own goals for the rest of the year and with half a year behind us it’s time to get cracking.</p>
<p><strong>My ten goals for 2013:</strong></p>
<ol>
<li>Develop a mobile app</li>
<li>Learn Git and make one GitHub repo</li>
<li>Create a package for Umbraco</li>
<li>Work on a game</li>
<li>Blog regularly</li>
<li>Manage presence</li>
<li>Learn Ruby</li>
<li>Learn a CSS preprocessor</li>
<li>Learn TypeScript</li>
<li>Learn a JavaScript framework</li>
</ol>
<h2>Develop a mobile app</h2>
<p>I’m not too concerned with the platform, whether that is web, iOS or Windows 8/Windows Phone 8 or what it does.</p>
<p>The aim for this goal is to learn the basics of publishing to a specific platform, operating system and devices and to <em>ship something.</em></p>
<h2>Learn Git and make one GitHub repo</h2>
<p>Version control is one of those things that <strong>you should be using but aren’t</strong> and I want to change that.</p>
<p>I included GitHub here because it seems to be definitive platform for managing public projects.</p>
<p>This blog is hosted using GitHub Pages so it doesn’t count for that one repo.</p>
<h2>Create a package for Umbraco</h2>
<p>I’ve worked with Umbraco for several years now and want to give something back and I have some ideas for a package that could be useful.</p>
<p>The purpose here is to learn how to create packages and how to automate their setup.</p>
<h2>Work on a game</h2>
<p>Again platform isn’t too important, especially when certain workflows make developing for different platforms easy.</p>
<p>This goal isn’t meant to ship anything but I have some game ideas that I want to take the time trying to build.</p>
<h2>Blog regularly</h2>
<p>The goal every blogger makes, then blogs about how they failed and will try again.</p>
<p>I want to talk about the things I’m learning, if only to provide reference for myself or to help reenforce what I’ve learned. I’ve also developed a large list of topics I’m interested in, so hopefully I just need to focus and write.</p>
<h2>Manage presence</h2>
<p>I need to finish my resume and create or manage some accounts with third parties to help tell the world <del>how awesome</del> who I am and … <em>network,</em> ugh.</p>
<h2>Learn Ruby</h2>
<p>Working with Jekyll and another Ruby project at work this is something I really want to do; especially when you have services like Heroku that allow you to get a project out there for free.</p>
<h2>Learn a CSS preprocessor</h2>
<p>I consider myself a front end developer and the benefits that a CSS preprocessor offer is something I want to get into my workflow.</p>
<h2>Learn TypeScript</h2>
<p>TypeScript takes any JavaScript and helps you to develop it using the same benefits of other languages with compliers and produces … wait for it … JavaScript.</p>
<p>Similar to the usefulness of a CSS preprocessor, TypeScript is a great benefit to developers working with JavaScript.</p>
<h2>Learn a JavaScript framework (or two)</h2>
<p>As websites become more complicated or if a web app is needed JavaScript will be the answer; whether that is a client side framework or JavaScript that runs on the server it is something to learn.</p>
<p>I’ll be using this blog (making number five easier) to reinforce what I’ve learned and as a way to track progress at the end of the year.</p>
Live2013-07-01T00:00:00-07:00http://erroronlineone.com/2013/07/01/live<p>New blog created with <a href="https://github.com/mojombo/jekyll">Jekyll</a>, using the <a href="http://carlosbecker.com/posts/up-a-jekyll-theme/">UP theme</a>, created by <a href="http://github.com/caarlos0">caarlos0</a> and hosted on <a href="http://pages.github.com">GitHub Pages</a>.</p>
<p>Favicon and Apple touch icons created with the free <a href="http://www.smashingmagazine.com/2013/01/06/freebie-gemicon-icon-set-600-psd-source-png/">Gemicon Icon Set</a>.</p>
<div class="highlight"><pre><code class="ruby"><span class="lineno">1</span> <span class="k">def</span> <span class="nf">foo</span>
<span class="lineno">2</span> <span class="nb">puts</span> <span class="s1">'foo'</span>
<span class="lineno">3</span> <span class="k">end</span>
</code></pre></div>
<div class="highlight"><pre><code class="csharp"><span class="lineno">1</span> <span class="k">void</span> <span class="nf">functionName</span><span class="p">(</span><span class="kt">int</span> <span class="n">_a</span><span class="p">)</span>
<span class="lineno">2</span> <span class="p">{</span>
<span class="lineno">3</span> <span class="n">console</span><span class="p">.</span><span class="n">WriteLine</span><span class="p">(</span><span class="s">"Hello World"</span><span class="p">);</span>
<span class="lineno">4</span> <span class="p">}</span>
</code></pre></div>