<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/rss2full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><rss xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:rssdatehelper="urn:rssdatehelper" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" version="2.0"><channel><title>Umbraco Blog</title><link>http://umbraco.com</link><pubDate /><generator>umbraco</generator><description>Latest blog posts from umbraco.org</description><language>en</language><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/rss+xml" href="http://feeds.feedburner.com/UmbracoBlog" /><feedburner:info uri="umbracoblog" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><item><title>Tracking work items on the Umbraco 5 codebase</title><link>http://feedproxy.google.com/~r/UmbracoBlog/~3/dJkOzbkmvk4/tracking-work-items-on-the-umbraco-5-codebase.aspx</link><pubDate>Thu, 09 Feb 2012 16:40:38 GMT</pubDate><guid isPermaLink="false">http://umbraco.com/follow-us/blog-archive/2012/2/9/tracking-work-items-on-the-umbraco-5-codebase.aspx</guid><content:encoded><![CDATA[<p><a href="http://umbraco.com/media/352471/Windows-Live-Writer_Tracking-work-items-on-the-Umbraco-5-cod_D734_image_5.png"><img src="http://umbraco.com/media/352476/Windows-Live-Writer_Tracking-work-items-on-the-Umbraco-5-cod_D734_image_thumb_1.png" /></a>Now that Umbraco 5.0 is out there
<em><a href="http://umbraco.codeplex.com/releases/view/81440" target="_blank">(with about 5000 downloads - thanks
everyone!),</a></em> we've worked on a small side-project to help
us push forward over the coming months.</p><p>Our <a href="http://issues.umbraco.org/" target="_blank">issue
tracker for Umbraco 5</a>, which we launched in December, is
proving to be a popular hub of information and we're using it to
not only keep a record of what issues people have found and fixed,
but also which ones are being worked on, and their target release
version.</p><p>Since this data is all in one place, Matt, Warren and I decided
to build a really simple aggregation of some of that data in a form
that we hope is easier to scan-read than going through YouTrack
directly.</p><p>We've put up an early version at <a href="http://progress.umbraco.org/" target="_blank">http://progress.umbraco.org/</a> for you to take a
look at.</p><p><a href="http://progress.umbraco.org/" target="_blank"><img src="http://umbraco.com/media/352491/Windows-Live-Writer_Tracking-work-items-on-the-Umbraco-5-cod_D734_image_8.png" /></a></p><p>It's organised by "version" and takes information from the "Due
in build" field inside YouTrack, and presents the assigned issues
categorised by "Not Started", "In Progress" and "Completed" with a
quick progress bar to give you an idea.</p><p>Not every issue in YouTrack is yet assigned to a particular
release, and of course some issues will be left until future
releases in the spirit of getting releases out early and often, so
they might not show up on this page - but it's a great excuse to
make your voice heard directly in <a href="http://issues.umbraco.org/" target="_blank">YouTrack</a> in
the comments and votes for items that are important to you.</p><h2>Next steps</h2><p>We'd like to be able to use this information to help people
gauge when an item is slated for inclusion in an upcoming update
(be that a minor bug-fixing release, or one that contains new
features).</p><p>Another big source of potential is that it could progress into a
great tool that helps the many folks out there that would love to
get involved on the Core team and start issuing pull requests, but
aren't sure which items need focus.</p><p>This is preparing the ground for us to be able to put together
some documentation not only for Umbraco 5 itself, but also some
guides for contributing code to the core - and other pages like
this that help people know what needs focus and when.</p><h2>It's not just the Core that's open source</h2><p>We think it'd be pretty cool to get the code for this up on a
repository somewhere, and if people want to issue pull requests to
add features or add a bit of style to even our Progress page, then
awesome. We just need to jump through a couple of TeamCity hoops
first, and I'll plug the code repository when that's done by
updating this post and shouting out on Twitter.</p><p>Enjoy!</p><div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/UmbracoBlog?a=dJkOzbkmvk4:BTCpe7L40DI:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/UmbracoBlog?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/UmbracoBlog?a=dJkOzbkmvk4:BTCpe7L40DI:V_sGLiPBpWU"><img src="http://feeds.feedburner.com/~ff/UmbracoBlog?i=dJkOzbkmvk4:BTCpe7L40DI:V_sGLiPBpWU" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/UmbracoBlog/~4/dJkOzbkmvk4" height="1" width="1"/>]]></content:encoded><feedburner:origLink>http://umbraco.com/follow-us/blog-archive/2012/2/9/tracking-work-items-on-the-umbraco-5-codebase.aspx</feedburner:origLink></item><item><title>Open Redirect Vulnerability in Umbraco 4</title><link>http://feedproxy.google.com/~r/UmbracoBlog/~3/SBpwuRdFbUM/open-redirect-vulnerability-in-umbraco-4.aspx</link><pubDate>Fri, 03 Feb 2012 12:10:51 GMT</pubDate><guid isPermaLink="false">http://umbraco.com/follow-us/blog-archive/2012/2/3/open-redirect-vulnerability-in-umbraco-4.aspx</guid><content:encoded><![CDATA[<p>Yesterday we got informed that there' was an <a href="http://nlsecurity.org/publications/2012-02-02-Umbraco.txt">"Open
Redirect Vulnerability" issue</a> in Umbraco 4. We fixed it this
morning. While we don't agree with the security consultants that
it's a major issue, we do our best to fix reported security issues
as fast as possible and have full disclosure.</p><p><strong>Is this issue relevant for you?</strong></p><p>The issue means that someone could make your editors click a
link (in an e-mail or on a 3rd party website) pointing to the back
office of your site, but then change where the editor would be
redirected afterwards if they login. This will require that you run
Umbraco with the back office fully open and that it's an active
editor that logins into the site. For instance:<br />
http://yoursite.com/umbraco/?redir=http://myevilsite.com</p><p>Once your editor have authenticated, they'd be redirected to the
evil site. No data is shared with that evil site, but it could add
a fake Umbraco login page and try to fake your editor to submit
their credentials again. That way they could then jump to your
website and login. <strong>All this would require a number of ifs
and ifs, but the risk is real and may be important enough for you
to upgrade…</strong></p><p><strong>How to upgrade</strong></p><p>In a hurry, you can go download the <a href="http://nightly.umbraco.org/umbraco%204.7.1/4.7.1/4.7.1.478.zip">
4.7.1.478 nightly</a> which contains the fix. If you're running
4.7.1.1, all you need to do is to overwrite the "/bin/umbraco.dll"
file. If running older versions, please refer to <a href="http://our.umbraco.org/wiki/install-and-setup/upgrading-an-umbraco-installation">
the upgrade guide</a>.</p><p><strong>4.7.1.2 next week</strong></p><p>We'll be releasing an official 4.7.1.2 early next week.</p><p><strong>Umbraco 5</strong></p><p>This issue is present in Umbraco 5 as well and will be fixed for
5.0.1.</p><p><strong>Questions?</strong></p><p>Feel free to submit questions in the comments.</p><div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/UmbracoBlog?a=SBpwuRdFbUM:jKxNdLdIO2c:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/UmbracoBlog?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/UmbracoBlog?a=SBpwuRdFbUM:jKxNdLdIO2c:V_sGLiPBpWU"><img src="http://feeds.feedburner.com/~ff/UmbracoBlog?i=SBpwuRdFbUM:jKxNdLdIO2c:V_sGLiPBpWU" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/UmbracoBlog/~4/SBpwuRdFbUM" height="1" width="1"/>]]></content:encoded><feedburner:origLink>http://umbraco.com/follow-us/blog-archive/2012/2/3/open-redirect-vulnerability-in-umbraco-4.aspx</feedburner:origLink></item><item><title>Umbraco 5.0 RTM is on CodePlex, ready for download</title><link>http://feedproxy.google.com/~r/UmbracoBlog/~3/ThxXp5xqYdQ/umbraco-50-rtm-is-on-codeplex,-ready-for-download.aspx</link><pubDate>Tue, 31 Jan 2012 13:34:28 GMT</pubDate><guid isPermaLink="false">http://umbraco.com/follow-us/blog-archive/2012/1/31/umbraco-50-rtm-is-on-codeplex,-ready-for-download.aspx</guid><content:encoded><![CDATA[<p><a href="http://umbraco.com/media/349488/Windows-Live-Writer_Umb.0-RTM-is-on-CodePlex-ready-for-downl_AF76_534529467_f0ebb68dbb_2.jpg"><img src="http://umbraco.com/media/349493/Windows-Live-Writer_Umb.0-RTM-is-on-CodePlex-ready-for-downl_AF76_534529467_f0ebb68dbb_thumb.jpg" /></a>Today is a pretty big milestone for
the Umbraco 5 team. It's the end of January 2012, we've had seven
progressively stable preview builds over the past months, and now
it's time to put a stake in the ground.</p><p>After a lot of hard work, late nights, and invaluable help from
the community testing our many preview builds, we've hit our first
production milestone.</p><p><strong><a title="Download Umbraco 5 RTM from CodePlex" href="http://umbraco.codeplex.com/releases/view/81440" target="_blank">Umbraco 5.0 RTM is on CodePlex!</a></strong></p><p>Please do grab a copy - take two, if you like - it's free after
all!</p><h2>Thanks to you</h2><p><a href="http://umbraco.com/media/349437/Windows-Live-Writer_Umb.0-RTM-is-on-CodePlex-ready-for-downl_AF76_image_2.png"><img src="http://umbraco.com/media/349442/Windows-Live-Writer_Umb.0-RTM-is-on-CodePlex-ready-for-downl_AF76_image_thumb.png" /></a>This is a release build and includes
all of the fixes from the RC3 which we put out there last
Wednesday. Since that time, we've already had almost 1000
downloads, which has made us incredibly proud. From our testing and
that of the reported issues, it's ready for you to build your next
live website.</p><h2>Features</h2><p>This is called "version 5 of Umbraco", but it's important to
remember the history of the v5 project. We always intended to
respect the vibrant culture and history of the Umbraco CMS as it
has gone so far, and make a product that was on a fresh &amp;
rewritten technology stack but enabling the same common goals.</p><p>Our target for "5-point-0" out of the box is the most commonly
used features of 4.7. We have a lot of features in 5.0 that enable
you to go into production for the vast majority of site builds, and
we have taken an approach of getting the core features done first -
and stable.</p><p>We are now going to be iterating quickly with new features as
the months progress, so that we reach feature parity with 4.7 and
move beyond that quickly. So, yes it's like a "1.0" in some senses,
but it already has a tonne of features that we think make it a
great CMS.</p><ul><li>Design and produce templates quickly using the excellent Razor
syntax</li><li>Access your content in those templates using an intuitive
dynamic API for both querying and walking up and down your content
structure</li><li>Tailor content types with a variety of customisable fields,
meaning you can focus on your content structure without a hard link
to its layout</li><li>Use multiple templates with pages so you can easily adjust to
your site's needs, do A/B testing, cater for mobile handsets, or
generate RSS feeds</li><li>Have document types that inherit from one or more other types,
making it simple to organise common fields for things like SEO that
are shared across all of your articles</li><li>Create, preview and publish content in a naturally organised
way using folders that can automatically create your site
navigation, if you like</li><li>Create, preview and publish media and other types of
assets</li><li>Store those assets on your server or in the cloud</li><li>Use a rich set of permissions to tailor backoffice access for
your editing team</li><li>Plug in your own existing data in a way that Umbraco natively
understands, rather than the only option being to migrate
everything under Umbraco's control</li><li>Plug in your own backoffice editors, dashboards, and custom
trees</li><li>Expose the underlying MVC stack for mixing in your own
application, controllers and views with the content-managed
portion</li><li>Share common pieces of functionality like Macros with your
team</li><li>Share your own data providers, common templates, handy helpers
and more using NuGet packages</li><li>Have those packages dynamically add configuration to a user's
website so that uninstalling rolls back configuration
seamlessly</li></ul><p>There are many more, but you didn't come here for a list of
bullet points - <a href="http://umbraco.codeplex.com/releases/view/81440" target="_blank">here's that download link again</a>!</p><h2>Documentation &amp; help</h2><p>In the next few weeks we'll be hard at work making tutorials,
documentation and answering questions on the Our forums. <a href="https://twitter.com/#!/warrenbuckley/status/164310213174894593" target="_blank">Warren has already got off to a great start with
some example Macros for common scenarios</a>.</p><h2>Here's to a bright future</h2><p>5.0 is a great foundation for you to build on now, but we aren't
stopping here. In the coming months we'll be focussing on adding
great support for backoffice editing of your own membership data,
and add some great APIs for reading and writing data to Hive in
your own controllers and packages. We'll also be adding a few
exotic things such as distributed caching and the like - if you
have a feature idea, <a href="http://issues.umbraco.org/dashboard/#tab=Hints&amp;newissue=yes" target="_blank">feel free to add it to our issue tracker and
appeal for votes</a>!</p><h2>Performance</h2><p>You might have seen <a href="http://umbraco.com/follow-us/blog-archive/2012/1/4/umbraco-5-on-performance-and-the-perils-of-premature-optimisation.aspx">the post I put up earlier this month about our
approach to performance tuning</a> as we approached RTM, and I also
mentioned it in a recent <a href="http://umbraco.com/newsletter.aspx" title="Sign up to our regular uNews newsletter">uNews-letter</a>. If not,
or at least to put it here for posterity, here's a few of those
figures.</p><p>I've been using the same content within each build of v5, and
the same load script on my own development machine for each test
run. It basically uses all 4 cores on my machine to both generate
and serve the load from my local IIS.</p><table border="0" cellspacing="0" cellpadding="2" width="589"><tbody><tr><td valign="top" width="133"><h3>Database &amp; Build</h3></td><td valign="top" width="209"><h3>Total time for 50 requests</h3></td><td valign="top" width="245"><h3>Equivalent requests per second</h3></td></tr><tr><td valign="top" width="133"><strong>SqlCe4</strong></td><td valign="top" width="209"> </td><td valign="top" width="245"> </td></tr><tr><td valign="top" width="133">RC1</td><td valign="top" width="209">44.514s</td><td valign="top" width="245">1.12</td></tr><tr><td valign="top" width="133">RC2</td><td valign="top" width="209">29.902s</td><td valign="top" width="245">1.67</td></tr><tr><td valign="top" width="133">Mid-Jan</td><td valign="top" width="209">18.839s</td><td valign="top" width="245">2.65</td></tr><tr><td valign="top" width="133"><em>RC3</em></td><td valign="top" width="209"><em>1.693s</em></td><td valign="top" width="245"><em>29.53</em></td></tr><tr><td valign="top" width="133"><em>RTM</em></td><td valign="top" width="209"><em>0.228s</em></td><td valign="top" width="245"><em>219.30</em></td></tr><tr><td valign="top" width="133"> </td><td valign="top" width="209"> </td><td valign="top" width="245"> </td></tr><tr><td valign="top" width="133"><strong>Sql Server 2008
R2</strong></td><td valign="top" width="209"> </td><td valign="top" width="245"> </td></tr><tr><td valign="top" width="133">RC1</td><td valign="top" width="209">25.487s</td><td valign="top" width="245">1.96</td></tr><tr><td valign="top" width="133">RC2</td><td valign="top" width="209">11.681s</td><td valign="top" width="245">4.28</td></tr><tr><td valign="top" width="133">Mid-Jan</td><td valign="top" width="209">5.665s</td><td valign="top" width="245">8.82</td></tr><tr><td valign="top" width="133"><em>RC3</em></td><td valign="top" width="209"><em>1.645s</em></td><td valign="top" width="245"><em>30.39</em></td></tr><tr><td valign="top" width="133"><em>RTM</em></td><td valign="top" width="209"><em>0.134s</em></td><td valign="top" width="245"><em>373.13</em></td></tr></tbody></table><p>To put those final figures into context, I re-ran the test
against RTM with 1000 requests instead, and obtained around
<strong><u>2900rps</u></strong>.</p><p>This seems a steady improvement followed by an astronomical
leap, what could it be?</p><p>It's a technique commonly referred to as "micro-caching". By
default, the base controller that serves Umbraco 5 RTM requests
caches the page output for 1 second. This technique sits on top of
the existing steady improvements in the codebase, and provides the
icing on the cake to help if your websites get a high peak load. So
it's a setting that you might not notice in daily use (unless
you're hitting refresh .. a lot), but your server will thank you if
you get a sudden influx of traffic.</p><p>You can of course tweak this if you prefer; the setting is in
configuration, and we'll be enabling more settings and handy "set
it and forget it" defaults like this as we add features in the
future.</p><h2>Happy downloading!</h2><p>To those of you who have followed us along the way, and to those
who have helped us code and test, a massive thank you. And to those
who will be helping us in the future, too. Have fun with Umbraco 5,
and please do let us know what you think.</p><p><a title="Download Umbraco 5 RTM from CodePlex" href="http://umbraco.codeplex.com/releases/view/81440" target="_blank"><strong>Here's that download link one more
time.</strong></a></p><p>All the best</p><p>Team 5</p><div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/UmbracoBlog?a=ThxXp5xqYdQ:sQ7K_oFvSX4:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/UmbracoBlog?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/UmbracoBlog?a=ThxXp5xqYdQ:sQ7K_oFvSX4:V_sGLiPBpWU"><img src="http://feeds.feedburner.com/~ff/UmbracoBlog?i=ThxXp5xqYdQ:sQ7K_oFvSX4:V_sGLiPBpWU" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/UmbracoBlog/~4/ThxXp5xqYdQ" height="1" width="1"/>]]></content:encoded><feedburner:origLink>http://umbraco.com/follow-us/blog-archive/2012/1/31/umbraco-50-rtm-is-on-codeplex,-ready-for-download.aspx</feedburner:origLink></item><item><title>Back to the roots</title><link>http://feedproxy.google.com/~r/UmbracoBlog/~3/EMlQnImxPOM/back-to-the-roots.aspx</link><pubDate>Thu, 26 Jan 2012 22:59:45 GMT</pubDate><guid isPermaLink="false">http://umbraco.com/follow-us/blog-archive/2012/1/26/back-to-the-roots.aspx</guid><content:encoded><![CDATA[<p>It's weird how something that seems to be perfect, can slowly
turn into a monster. For me it often happens just as I dare to lean
back in the chair, take a deep breath of satisfaction and pat my
own back thinking, "nailed it". Maybe it's because you're
exhausted, maybe because you get lazy or maybe it's because you
start "choosing your battles". Prioritizing if you will. Maybe even
maturing.</p><p>My number one pet - the Umbraco community - has certainly
matured. What started out as a crazy dream by a selected few is now
the daily life of thousands. And during the journey - which is
seven years in a few weeks - we've all been doing a great job of
adjusting. What seemed right in 2005 may not be that great in
2012!</p><p>Why all this rambling? Well, because it's time to make an
adjustment of what I thought was an evergreen in the Umbraco
community - the MVP program - our "Most Valued People". It was
started in 2007 as a way to recognize the selected few who really
made a difference. The crazy ones. It was easy then because there
weren't more than a few to pick from and I knew what every one had
done. Read every post, tried every package.</p><p>As time went on and things grew, I couldn't keep up. Who could?
So in 2010 I moved the responsibility to nominate the MVPs to the
collective intelligence of the community. Based on the 20 community
members who had the most karma, the community voted and the top
five were honored with the recognition of being an MVP. Over five
years Casey, Doug, Jesper, Per, Thomas, Warren, Dirk, Morten, Paul,
Tim, Lee, Richard, Darren, Matt, Sebastiaan and Jan wrote a <a href="http://umbraco.com/about-us/history">little bit of Umbraco history</a> as the
Umbraco MVPs.</p><p>We've been blessed with this fantastic bunch of people who were
crazy enough to believe in an unknown project like Umbraco, crazy
enough to help because it came naturally to them and crazy enough
to share their work for free because it felt right.</p><p><em>Because it felt right</em>. Not because they searched for
recognition. Not because they wanted a badge, an honor, an ego
boost. But simply because it was the building blocks Umbraco is
made of. And the MVPs that followed went in the footsteps of what
became known as the Umbraco culture - we really became the friendly
cms. These are our roots.</p><p>Our culture is fragile, yet it's our most important asset and
what really sets us apart. Our culture is about helping and sharing
because it's the most natural thing to do and because we can't help
it. Not because we strive for recognition. Before that becomes the
norm, I've decided to close the MVP program. It's not worth
striving for. What is worth striving for - while much harder - is a
community that helps each other despite not getting anything
tangible in return.</p><p>So the MVPs of 2011 will be the last ones. There won't be any
voting this year nor the years that follow. The MVP program is
history and we'll only miss it because it never got devalued. Kudos
to the MVPs who brought us here and created a culture that made
recognition obsolete. What a community!</p><p>"<em>The unselfish effort to bring cheer to others will be the
beginning of a happier life for ourselves.</em>", <a href="http://en.wikipedia.org/wiki/Helen_Keller">Helen
Keller</a></p><div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/UmbracoBlog?a=EMlQnImxPOM:oleCkdSveNw:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/UmbracoBlog?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/UmbracoBlog?a=EMlQnImxPOM:oleCkdSveNw:V_sGLiPBpWU"><img src="http://feeds.feedburner.com/~ff/UmbracoBlog?i=EMlQnImxPOM:oleCkdSveNw:V_sGLiPBpWU" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/UmbracoBlog/~4/EMlQnImxPOM" height="1" width="1"/>]]></content:encoded><feedburner:origLink>http://umbraco.com/follow-us/blog-archive/2012/1/26/back-to-the-roots.aspx</feedburner:origLink></item><item><title>Creating my First V5 Package</title><link>http://feedproxy.google.com/~r/UmbracoBlog/~3/rvuD7JIBFto/creating-my-first-v5-package.aspx</link><pubDate>Thu, 26 Jan 2012 10:17:59 GMT</pubDate><guid isPermaLink="false">http://umbraco.com/follow-us/blog-archive/2012/1/26/creating-my-first-v5-package.aspx</guid><content:encoded><![CDATA[<p>Hi there, I wanted to tell you about my experiences of creating
a package for the upcoming brand new version, version 5 of Umbraco.
Which has been rewritten from the ground up to use <a href="http://www.asp.net/mvc" target="_blank">ASP.NET MVC 3</a> and
the <a href="http://www.asp.net/web-pages/tutorials/basics/2-introduction-to-asp-net-web-programming-using-the-razor-syntax" target="_blank">Razor View Engine</a>.</p><p>First, a quick bit about my background, just in case you don't
already know me. My technical knowledge is more of a front-ender
who loves to work with markup, CSS and JavaScript and implementing
sites into Umbraco. When some of more technical guys at the Umbraco
HQ such as Alex, Matt &amp; Shannon who have been working hard
building and architecting V5, talk to me about certain code. I have
no clue what they are talking about and just politely smile and nod
as if I understood everything they say, well sometimes I understand
them :)</p><p>However I wanted to write this blog post and tell you how
incredibly easy it is to build a custom property editor and put in
a package for the rest of the community to use. If I can build a
Property Editor as a package, then I am sure you can do too!</p><h2>The Basics</h2><p>Lets start off with some of the basics, such as a quick glossary
of terms as in V5 a few terms have been changed:</p><p><strong>Property Editor</strong><br />
 A PropertyEditor is a new term in version 5 of Umbraco. In version
4 of Umbraco this was known as the render control for a DataType in
Umbraco. So for example you could create multiple DataTypes in
Umbraco that all use the Rich Text Editor render control or as it
is now known as, PropertyEditor. So a DataType allows you to create
variations of a PropertyEditor by changing the settings for that
PropertyEditor.</p><p><strong>Pre Values</strong><br />
 This may be a new term to you, but Pre Values are the default
settings and configurations that allow you to configure a
PropertyEditor.</p><p><strong>Plugin</strong><br />
 A plugin is a single item that extends Umbraco. For example each
one of these would be a separate plugin:</p><ul><li>PropertyEditor</li><li>Tree</li><li>Context Menu Items</li></ul><p>There are more plugin types available, but I won't cover that
here in this post. I recommend you take a look through the list of
resources at the bottom of the post to know what is possible.</p><p><strong>Package</strong><br />
 The term for a package has not really changed, but you may package
up one or more plugins to create your package.</p><h2>What Did I Make?</h2><p>For my first package I decided to build a property editor that I
could use in a new simple starter website kit I am attempting to
make. I decided to build an RGBA colour picker that allows a
content editor to save a colour to change in the front end of the
website.</p><p>Below you can see the initial idea sketch I had for creating a
very simple property editor, which involves four jQuery UI sliders
that allow the user to control the individual values that make up a
RGBA colour.</p><p><img src="http://umbraco.com/media/348244/Windows-Live-Writer_Creating-my-First-V5-Package_76D1_rgba-picker-sketch_3.jpg" /></p><p>When I was sketching the property editor out, I thought it would
be a good idea to put in some safe guards for the property editor,
as not all browsers support RGBA I decided it would be a good idea
to have two fallbacks of RGB and then a Hexadecimal colour such as
#FFF000</p><p>Before I even started writing any code specific to Umbraco. I
wanted to create a static HTML page along with the JavaScript I
needed to write in order to see how easy or hard it was to achieve
my idea. I created my prototype fairly quickly and was happy for me
to try and attempt this as a PropertyEditor.</p><p><img src="http://umbraco.com/media/348249/Windows-Live-Writer_Creating-my-First-V5-Package_76D1_rgba-prototype_3.jpg" /></p><p>And finally below is the end result of the property editor
inside an Umbraco 5 install.</p><p><iframe src="http://www.screenr.com/embed/kUas" width="790" height="481" frameborder="0" /></p><p><em>Disclaimer: The video above is using an old version of Umbraco 5 and does not reflect the speed of V5 RC3 and newer</em></p><h2>How to Create a PropertyEditor</h2><p>First things first you will need Visual Studio installed. If you
don't have Visual Studio installed, you can download a simpler free
version of Visual Studio called: <a href="http://www.microsoft.com/visualstudio/en-us/products/2010-editions/visual-web-developer-express" target="_blank">Visual Web Developer 2010 Express</a>.</p><p>Before we start doing any coding, if you are new to ASP.NET MVC
then I highly recommend you learn the fundamentals as this will
help you to understand a lot better what is going on.
<strong>However with that said it is not required that you know
ASP.NET MVC to work with Umbraco V5.</strong></p><p>One video series I can highly recommend is this series from <a href="http://www.pluralsight-training.net/microsoft/Courses/TableOfContents?courseName=aspdotnet-mvc3-intro" target="_blank">PluralSight - Introduction to ASP.NET
MVC3</a>  You can watch the entire series for free, as they
have a 10 day trial but I must admit it converted me into a paid
subscriber.</p><p>Now that we have got a basic understanding of MVC, lets get to
work...<br />
 Firstly download a copy of the source code of my <a href="http://umbraco5contrib.codeplex.com/SourceControl/changeset/changes/e67d0c3dc0c6" target="_blank">RGBA PropertyEditor from the Umbraco5Contrib
project on CodePlex</a>, as we will need this to copy some files
and for you to use a guide.</p><ul><li>Create a new project in Visual Studio of the project type
<strong>Class Library</strong> using <strong>C#</strong></li><li>Name your project
<strong>RGBA.Umbraco.PropertyEditor</strong></li><li>Create a folder called <strong>Resources</strong> This is where
we will put our CSS and JavaScript needed for our RGBA
PropertyEditor. Copy the JS, CSS and PNG from the source on
CodePlex into this folder.</li><li>Next create a folder called <strong>Views</strong> This is
where will store the Razor View file for our PropertyEditor, which
allows us to write our HTML markup for. Copy the
RGBAPickerEditor.cshtml file into this folder.</li><li>Next at the root of the project create three new class files
called and it is important you keep to naming conventions here as
this helps to wire everything up in MVC automatically. 

<ul><li><strong>RGBAPickerEditor.cs</strong></li><li><strong>RGBAPickerEditorModel.cs</strong></li><li><strong>RGBAPickerPreValueModel.cs</strong></li></ul></li></ul><p>Before we continue I need to explain to you what Embedded
Resources are. An embedded resource allows you to embed a file,
such as a JavaScript file or a CSS file inside the binary DLL for
the class project. So why this is useful for our plugin development
is that we only have to deploy one DLL for our plugin to work as we
can embedded any other items into that file.</p><p>The files that we need to have as embedded resources are:</p><ul><li>Resources/RGBAPicker.css</li><li>Resources/RGBAPicker.js</li><li>Resources/transparent-grid.png</li><li>Views/RGBAPickerEditor.cshtml</li></ul><p>To embed a resource you need to select the file from the
Solution Explorer window (normally on the right hand side of the
Visual Studio application) and from the properties window below
find the row labelled <strong>Build Action</strong> and choose the
option labelled <strong>Embedded Resource</strong></p><p><img src="http://umbraco.com/media/348254/Windows-Live-Writer_Creating-my-First-V5-Package_76D1_embedded-resource_3.jpg" /></p><p>Now when you build your project all those items will be
available inside the DLL.</p><p>Next you will need to reference the Umbraco V5 DLLs for your
project, you can retrieve these from the source code of the project
if needed.</p><p>Rather than explain what code you need to type in, let's paste
in the example code from the source code of the RGBA Picker project
we downloaded from CodePlex and then we can look at parts of the
files below to dissect them and understand what is going on.</p><p><em>Note: That some of the snippets below have been shortened to
save space in this post, I recommend you refer to the source code
for the original files.</em></p><p><strong>RGBAPickerEditor.cs</strong><br />
At the top of this file you can see we are saying that our RGBA
property editor needs to use the files from the Resources folder.
It's important to note this is the full namespace of the file. So
the name of our project followed by the resources folder then the
filename. The extra parameter for the CSS file of
PerformSubstitution allows us to use a similar web resource url for
a background image  of a DOM element.</p><p>Next you will also notice above the class is a PropertyEditor
attribute, which we use to say this class is a PropertyEditor and
then we pass in some parameters.</p><p>The first is a unique GUID string which is the ID of our
package, make sure this is unique as if you were to copy this ID
and someone else developed a plugin with the same GUID there would
be a conflict. To create your own GUID you can either use the tools
inside Visual Studio or simply visit this website - <a href="http://createguid.com">http://createguid.com</a></p><p>The second parameter is the alias of the property editor and the
third parameter is the friendly name of the property editor, that
will displayed in the dropdown list when creating a new data
type.</p><pre class="brush: csharp; auto-links: true; collapse: false; first-line: 1; gutter: true; html-script: false; light: false; ruler: false; smart-tabs: true; tab-size: 4; toolbar: true;">

//Using statements go here - see source code from original on Codeplex

[assembly: WebResource("RGBA.Umbraco.PropertyEditor.Resources.RGBAPicker.js", "application/x-javascript")]
[assembly: WebResource("RGBA.Umbraco.PropertyEditor.Resources.RGBAPicker.css", "text/css", PerformSubstitution = true)]
[assembly: WebResource("RGBA.Umbraco.PropertyEditor.Resources.transparent-grid.png", "image/png")]
 
namespace RGBA.Umbraco.PropertyEditor
{
    [PropertyEditor("04B0F923-E780-42DA-869E-32C118E12364", "RGBA.Umbraco.PropertyEditor", "RGBA Picker")]
    public class RGBAPickerEditor : PropertyEditor&lt;RGBAPickerEditorModel, RGBAPickerPreValueModel&gt;
    {
        public override RGBAPickerEditorModel CreateEditorModel(RGBAPickerPreValueModel preValues)
        {
            return new RGBAPickerEditorModel(preValues);
        }
 
        public override RGBAPickerPreValueModel CreatePreValueEditorModel()
        {
            return new RGBAPickerPreValueModel();
        }
    }
}
</pre><p><strong>RGBAPickerEditorModel.cs<br /></strong> This class file is where we define the properties of our
model. In this case the values we want to store when a content
editor uses our property editor and that the same values can be
used to be output them into our templates. Here you can see I have
created seven properties to store the values</p><ul><li>Red</li><li>Green</li><li>Blue</li><li>Alpha</li><li>Hex</li><li>RGB</li><li>RGBA</li></ul><p>If you notice I am using ASP.NET MVC Data Annotations to allow
me to put validation on these fields very simply and very quickly.
Here you can see I use the required and range annotations. It's
literally that simple to do validation in Umbraco with MVC.</p><p>Inside the RGBAPropertyEditorModel stub you can see that we set
the default values for the property editor when no values have yet
been saved as the prevalues from the configuration of the property
editor.</p><p>Finally the GetSerializedValue stub allows me to concatenate the
values from Red, Green, Blue and Alpha to populate the values for
RGB and RGBA when the user saves the content node.</p><p>Also on the class you can see we have embedded the view which is
the HTML output for our property editor, which will contain our
sliders etc...</p><pre class="brush: csharp; auto-links: true; collapse: false; first-line: 1; gutter: true; html-script: false; light: false; ruler: false; smart-tabs: true; tab-size: 4; toolbar: true;">

//Using statements go here - see source code from original on Codeplex
 
namespace RGBA.Umbraco.PropertyEditor
{
    [EmbeddedView("RGBA.Umbraco.PropertyEditor.Views.RGBAPickerEditor.cshtml", "RGBA.Umbraco.PropertyEditor")]
    public class RGBAPickerEditorModel : EditorModel&lt;RGBAPickerPreValueModel&gt;
    {
        public RGBAPickerEditorModel(RGBAPickerPreValueModel preValues) : base(preValues)
        {
            //Use prevalues as the default values until it's saved
            //Tip from Shannon's CG11 Plugin talk...
            Red     = preValues.initRed;
            Green   = preValues.initGreen;
            Blue    = preValues.initBlue;
            Alpha   = preValues.initAlpha;
        }
 
        [Range(0, 255, ErrorMessage = "Please select the Red value of 0 - 255")]
        [Required]
        [DisplayName("Red")]
        public int Red { get; set; }
 
        [Range(0, 255, ErrorMessage = "Please select the Red value of 0 - 255")]
        [Required]
        [DisplayName("Green")]
        public int Green { get; set; }
 
        [Range(0, 255, ErrorMessage = "Please select the Red value of 0 - 255")]
        [Required]
        [DisplayName("Blue")]
        public int Blue { get; set; }
 
        [Range(0, 100, ErrorMessage = "Please select the Alpha % of 0 - 100")]
        [Required]
        [DisplayName("Alpha")]
        public int Alpha { get; set; }
 
        [HiddenInput]
        public string Hex { get; set; }
 
        [HiddenInput(DisplayValue = false)]
        public string RGB { get; set; }
 
        [HiddenInput(DisplayValue = false)]
        public string RGBA { get; set; }
 
 
        public override IDictionary&lt;string, object&gt; GetSerializedValue()
        {
            //RGB
            RGB = string.Concat(Red, ",", Green, ",", Blue);
 
            //RGBA
            //Convert alpha to decimal
            var AlphaDecimal = Convert.ToDecimal(Alpha) / 100;
            RGBA = string.Concat(Red, ",", Green, ",", Blue, ",", AlphaDecimal);
            
            return base.GetSerializedValue();
        }
    }
}
</pre><p><strong>RGBAPreValueModel.cs<br /></strong> This class file stores the PreValues properties, so these
will be the items that you will be able to configure for your
property editor, along with validation again.</p><p>A new annotion you can see is the
AllowDocumentTypePropertyOverride which is very useful as this
allows us to say this prevalue item can be configured on the data
type but also when you add the data type to a document type, you
are able to override the values used in the prevalues and change
them. This stops you from creating a duplicate data type to only
change one small prevalue.</p><pre class="brush: csharp; auto-links: true; collapse: false; first-line: 1; gutter: true; html-script: false; light: false; ruler: false; smart-tabs: true; tab-size: 4; toolbar: true;">

//Using statements go here - see source code from original on Codeplex
 
namespace RGBA.Umbraco.PropertyEditor
{
    public class RGBAPickerPreValueModel : PreValueModel
    {
        [AllowDocumentTypePropertyOverride]
        [Range(0,255, ErrorMessage = "Please select the Red value of 0 - 255")]
        [Required]
        [DisplayName("Red")]
        public int initRed { get; set; }
 
        [AllowDocumentTypePropertyOverride]
        [Range(0, 255, ErrorMessage = "Please select the Red value of 0 - 255")]
        [Required]
        [DisplayName("Green")]
        public int initGreen { get; set; }
 
        [AllowDocumentTypePropertyOverride]
        [Range(0, 255, ErrorMessage = "Please select the Red value of 0 - 255")]
        [Required]
        [DisplayName("Blue")]
        public int initBlue { get; set; }
 
        [AllowDocumentTypePropertyOverride]
        [Range(0, 100, ErrorMessage = "Please select the Alpha % of 0 - 100")]
        [Required]
        [DisplayName("Alpha")]
        public int initAlpha { get; set; }
    }
}
</pre><p><strong>Views/RGBAPickerEditor.cshtml<br /></strong> As you can see below the Razor view is heavily commented
to explain what it is doing, but this is the HTML markup that will
be generated for each RGBA Picker on a content node.</p><pre class="brush: csharp; auto-links: true; collapse: false; first-line: 1; gutter: true; html-script: false; light: false; ruler: false; smart-tabs: true; tab-size: 4; toolbar: true;">

@inherits WebViewPage&lt;RGBA.Umbraco.PropertyEditor.RGBAPickerEditorModel&gt;

//Using statements go here - see source code from original on Codeplex
 
@{
    //Create a unique GUID so that this property has a unique ID for the &lt;div&gt;
    var uniqueID = Guid.NewGuid().ToString();
    var pickerID = "rgba-" + uniqueID; 
}
 
&lt;script type="text/javascript"&gt;
    $(document).ready(function () {
 
        //Call the plugin with our options
        //Pass in the HTML ID's of the hidden input boxes
        //So our JS can update these boxes with the new values to save
        $('#@pickerID').rgbaPicker({
            redID:      '#@Html.IdFor(x =&gt; Model.Red)',
            blueID:     '#@Html.IdFor(x =&gt; Model.Blue)',
            greenID:    '#@Html.IdFor(x =&gt; Model.Green)',
            alphaID:    '#@Html.IdFor(x =&gt; Model.Alpha)',
            hexID:      '#@Html.IdFor(x =&gt; Model.Hex)'
        });
    });
&lt;/script&gt;
 
 
@{
    //Here we need to say we want to use the CSS &amp; JS file in our view
    Html
    .RequiresJsResource(typeof(RGBAPickerEditor), "RGBA.Umbraco.PropertyEditor.Resources.RGBAPicker.js")
    .RequiresCssResource(typeof(RGBAPickerEditor), "RGBA.Umbraco.PropertyEditor.Resources.RGBAPicker.css");
}
 
 
&lt;!-- We give this div the unique pickerID --&gt;
&lt;div id="@pickerID" class="rgbaPicker"&gt;
    &lt;div class="sliders"&gt;
        &lt;div class="item"&gt;
            &lt;!-- CSS classes used to easily target in JS to update --&gt;
            &lt;label&gt;Red: &lt;span class="redDisplay"&gt;&lt;/span&gt;&lt;/label&gt;
            &lt;div class="redSlider"&gt;&lt;/div&gt;
            &lt;!-- 
            Hidden textbox for the Red value we want to save.
            The value gets updated by the JS
             --&gt;
            @Html.HiddenFor(x =&gt; Model.Red)
        &lt;/div&gt;
 
        &lt;div class="item"&gt;
            &lt;!-- CSS classes used to easily target in JS to update --&gt;
            &lt;label&gt;Green: &lt;span class="greenDisplay"&gt;&lt;/span&gt;&lt;/label&gt;
            &lt;div class="greenSlider"&gt;&lt;/div&gt;
            &lt;!-- 
            Hidden textbox for the Green value we want to save.
            The value gets updated by the JS
             --&gt;
            @Html.HiddenFor(x =&gt; Model.Green)
        &lt;/div&gt;
 
        &lt;div class="item"&gt;
            &lt;!-- CSS classes used to easily target in JS to update --&gt;
            &lt;label&gt;Blue: &lt;span class="blueDisplay"&gt;&lt;/span&gt;&lt;/label&gt;
            &lt;div class="blueSlider"&gt;&lt;/div&gt;
            &lt;!-- 
            Hidden textbox for the Blue value we want to save.
            The value gets updated by the JS
             --&gt;
            @Html.HiddenFor(x =&gt; Model.Blue)
        &lt;/div&gt;
 
        &lt;div class="item"&gt;
            &lt;!-- CSS classes used to easily target in JS to update --&gt;
            &lt;label&gt;Alpha: &lt;span class="alphaDisplay"&gt;&lt;/span&gt;%&lt;/label&gt;
            &lt;div class="alphaSlider"&gt;&lt;/div&gt;
            &lt;!-- 
            Hidden textbox for the Alpha value we want to save.
            The value gets updated by the JS
             --&gt;
            @Html.HiddenFor(x =&gt; Model.Alpha)
        &lt;/div&gt;
        
        &lt;div&gt;
            &lt;!-- Disabled input for Hex # colour --&gt;
            @Html.LabelFor(x =&gt; Model.Hex)
            @Html.TextBoxFor(x =&gt; Model.Hex, new { @class = "hex",  @readonly = "readonly" })
        &lt;/div&gt;
    &lt;/div&gt;
 
    &lt;!-- Colour is previewed here --&gt;
    &lt;div class="livePreview"&gt;&lt;span&gt;&lt;/span&gt;&lt;/div&gt;
&lt;/div&gt;
</pre><p><strong>Resources/RGBAPicker.js<br /></strong> I won't copy and paste the source for this file here in
the post, but if you take a look at the source code you will be
able to figure out easily what is going on, as the code is heavily
commented.</p><p>But in a nutshell the Javascript is doing the following, wiring
up the jQuery UI slider divs and updating the value in the hidden
textboxes and labels. In addition when the slider is moved the live
preview &lt;div&gt; is getting updated to preview the colour along
with a JS function being calculated to generate the hexadecimal
colour as well. As long as the values in the hidden textboxes are
updated with our new values then when the user presses save the
values are saved back to Umbraco automatically. I have not had to
worry about writing complex code to save the values back to the
database, all of this hard work is done for me magically. <em>Those
V5 devs are a clever bunch, aren't they!</em></p><p>Now that we have all the parts in place inside our class project
we can build our project and have it compile to a single DLL, as we
are using embedded resources.</p><p>To test your property editor I was copying the DLL and placing
it inside the bin folder of my Umbraco V5 website. Then I was able
to go to the developer section and create a new data type with my
RGBA Picker property editor and test it out on a document type.</p><h2>Outputting the Values</h2><p>So now that we have our property editor inside Umbraco and setup
on a content type and tested out our property editor, we will want
to output those values into a template. I liked the idea of
overriding elements in my main CSS file to allow me to change
colour of certain elements.</p><p>So in my template I have the following code that outputs the
values from a property with the alias of
<strong>sidebarColour</strong></p><pre class="brush: csharp; auto-links: true; collapse: false; first-line: 1; gutter: true; html-script: false; light: false; ruler: false; smart-tabs: true; tab-size: 4; toolbar: true;">

&lt;style type="text/css"&gt;
    /* Overrides */
    aside 
    {
       /* Safe fallbacks to RGB then fallback to solid Hex */
        background-color: @DynamicModel.sidebarColour.Hex;
        background-color: rgb(@DynamicModel.sidebarColour.RGB);
        background-color: rgba(@DynamicModel.sidebarColour.RGBA);
    }
&lt;/style&gt;
</pre><p>Once you are happy with the results, it's time to package it up
so you can share it with the community and just generally re-use a
component for other sites you will build with Umbraco.</p><h2>How to Create the Package</h2><p>Packages in Umbraco use a package format that is fairly new to
ASP.NET which is called Nuget. But to create our property editor
package for Umbraco, you will need to <a href="http://docs.nuget.org/docs/creating-packages/using-a-gui-to-build-packages" target="_blank">download the Nuget GUI tool</a>.</p><p>Once you have it installed, open the program and choose the
<strong>create a new package</strong> option. Next we need to edit
the metadata for our package. You can do this by finding the option
<strong>Edit Package Metadata</strong> in the application menu.
Here you will need to supply a unique ID for the package, but for
best practises I would recommend you use the same alias as you used
for the property editor in <strong>RGBAPickerEditor.cs</strong>.
However if the package contained more than one plugins this won't
apply. Just choose a sensible name that would be unique, such as
CompanyName.PluginName</p><p>Before we add our DLL to our package, we need to make one small
modification to the project. If you open the file
<strong>AssemblyInfo.cs</strong> found under the
<strong>Properties</strong> folder. We need to add one line of code
to the file along with adding a using statement. What this does, is
let Umbraco know that this DLL contains plugins that need to be
installed. If we don't do this Umbraco won't pick up our DLL, as
when a package is installed the files do not get copied to the bin
folder but instead get installed to
<strong>/App_Plugins/Packages/PackageID</strong></p><pre class="brush: csharp; auto-links: true; collapse: false; first-line: 1; gutter: true; html-script: false; light: false; ruler: false; smart-tabs: true; tab-size: 4; toolbar: true;">

using Umbraco.Cms.Web;
[assembly: AssemblyContainsPlugins]
</pre><p>After adding in this change you will need to rebuild your
project to ensure this change is made to the DLL.</p><p>The final step for creating our package, is to add the single
DLL for our property editor that needs to be installed. If you drag
the DLL into the middle column of the Nuget Package tool. You will
be prompted with a dialog box. Make sure you say yes to add it to
the lib folder.</p><p><img src="http://umbraco.com/media/348259/Windows-Live-Writer_Creating-my-First-V5-Package_76D1_nuget-dialog_3.jpg" /></p><p>Once your done, your nuget package should look something like
below.</p><p><img src="http://umbraco.com/media/348264/Windows-Live-Writer_Creating-my-First-V5-Package_76D1_rgba-package-meta_6.jpg" /></p><p>Save the package to a convenient location and it's time to test
out your package. I would recommend you test your package in a
clean install of Umbraco 5, as if you use the same install as for
your previous test. You will need to delete the property of the
document type along with the data type and then finally remove the
DLL from the Bin folder otherwise it will cause a conflict.</p><p>Volia one property editor package, now you can install it into
an Umbraco 5 website to test out your work.</p><h2>Resources</h2><p>Here are some useful resources that I recommend you take a look
through:</p><p><strong>Shannon Deminick's Blog Post Series on Plugins<br /></strong><a href="http://shazwazza.com/post/Umbraco-Jupiter-Plugins-Part-1.aspx" target="_blank">http://shazwazza.com/post/Umbraco-Jupiter-Plugins-Part-1.aspx</a><br /><a href="http://shazwazza.com/post/Umbraco-Jupiter-Plugins-Part-2-Routing.aspx" target="_blank">http://shazwazza.com/post/Umbraco-Jupiter-Plugins-Part-2-Routing.aspx</a><br /><a href="http://shazwazza.com/post/Umbraco-Jupiter-Plugins-Part-3-Trees.aspx" target="_blank">http://shazwazza.com/post/Umbraco-Jupiter-Plugins-Part-3-Trees.aspx</a><br /><a href="http://shazwazza.com/post/Umbraco-Jupiter-Plugins-Part-4-Editors.aspx" target="_blank">http://shazwazza.com/post/Umbraco-Jupiter-Plugins-Part-4-Editors.aspx</a><br /><a href="http://shazwazza.com/post/Umbraco-Jupiter-Plugins-Part-5-Surface-Controllers.aspx" target="_blank">http://shazwazza.com/post/Umbraco-Jupiter-Plugins-Part-5-Surface-Controllers.aspx</a></p><p><strong>Shannon Deminick's CodeGarden 11 Session on Plugins
Video</strong><br /><a href="http://codegarden11.com/sessions/day-1/slot-two/get-plugged-in-to-umbraco-jupiter.aspx" target="_blank">http://codegarden11.com/sessions/day-1/slot-two/get-plugged-in-to-umbraco-jupiter.aspx</a></p><p><strong>The Umbraco V5 Contrib Project</strong><br /><a href="http://umbraco5contrib.codeplex.com" target="_blank">http://umbraco5contrib.codeplex.com</a></p><p><strong>Work in Progress: Estate Agent Starter
Website</strong><br /><a href="https://bitbucket.org/warrenbuckley/estate-agents-starter-site" target="_blank">https://bitbucket.org/warrenbuckley/estate-agents-starter-site</a></p><h2>The End Result</h2><p>So what have we covered? Well I have shown you from initial
sketch all the way upto a working PropertyEditor package for
Umbraco 5 and how easy it is to do. Remember if I can do it then
certainly you clever lot can!</p><p>You can download the RGBA Property Editor from <a href="http://our.umbraco.org/" target="_blank">our.umbraco.org</a>
along with another property editor I made which was the Bing Maps
property editor.</p><p><a href="http://our.umbraco.org/projects/backoffice-extensions/rgba-property-editor" target="_blank">http://our.umbraco.org/projects/backoffice-extensions/rgba-property-editor</a><br /><a href="http://our.umbraco.org/projects/backoffice-extensions/bing-maps-property-editor" target="_blank">http://our.umbraco.org/projects/backoffice-extensions/bing-maps-property-editor</a></p><p>Got any questions, just leave a comment and I will get back to
you.</p><p>Cheers,<br />
 Warren - The friendly front end dev!</p><div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/UmbracoBlog?a=rvuD7JIBFto:SaGFVkeMTe8:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/UmbracoBlog?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/UmbracoBlog?a=rvuD7JIBFto:SaGFVkeMTe8:V_sGLiPBpWU"><img src="http://feeds.feedburner.com/~ff/UmbracoBlog?i=rvuD7JIBFto:SaGFVkeMTe8:V_sGLiPBpWU" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/UmbracoBlog/~4/rvuD7JIBFto" height="1" width="1"/>]]></content:encoded><feedburner:origLink>http://umbraco.com/follow-us/blog-archive/2012/1/26/creating-my-first-v5-package.aspx</feedburner:origLink></item><item><title>Persistence model in v5</title><link>http://feedproxy.google.com/~r/UmbracoBlog/~3/rWEHslv-Pns/persistence-model-in-v5.aspx</link><pubDate>Mon, 23 Jan 2012 19:40:19 GMT</pubDate><guid isPermaLink="false">http://umbraco.com/follow-us/blog-archive/2012/1/23/persistence-model-in-v5.aspx</guid><content:encoded><![CDATA[<p>The idea with this post is to give a basic understanding of the
persistence model in Umbraco v5 with a primary focus on the
objects, which I expect are the ones you as an Umbraco developer
will need to be familiar with. This post isn't a full blown deep
dive into persistence in Umbraco v5, but it will  help you
understand the inner workings of dealing with persistence.<br />
 Please note that this is primarily intended for developers, who
wants to familiarize themselves with the low level API in v5. A
higher level API is in the works, which should make it simple for
all types of developers (frontend, backend etc.) doing tasks like
creating/updating/deleting a content item, querying and
publishing.</p><p>In Umbraco v4 there were a lot of different concepts like a
Document, a Node, a CMSNode and Media.  When dealing with the
API  you would use Document for programmatically creating a
content item, but after the item was published you would treat it
as a Node. So basically you would use different approaches for
dealing with data depending on the type of item (i.e., content,
media, document type, etc.) you were working with in the Umbraco
backoffice. In v5 its all about the TypedEntity object. All the
different types of items in the Umbraco backoffice are based on the
TypedEntity object, which makes the API much simpler to work
with.</p><p>Lets dive a little deeper into the TypedEntity object and
explore some of the related objects, which you need to know
about.<br />
 Basically the TypedEntity is the object you want to store in your
persisted storage and what you request when you want to retrieve
data and display it on your site or in the backoffice.<br />
 A <strong>TypedEntity</strong> consists of an
<strong>EntitySchema</strong>, a
<strong>TypedAttributeCollection</strong>, a list of
<strong>AttributeGroup</strong> objects and a
<strong>RelationProxyCollection</strong>.<br />
 The EntitySchema is used to describe the data that you want your
TypedEntity to store - hence the word schema.<br />
 The TypedAttributeCollection is, as the name implies, a collection
of TypedAttribute objects. A TypedAttribute contains the actual
value(s), which you want your TypedEntity to store.<br />
 An AttributeGroup is a group to which certain types of attributes
belong. You can think of a 'group of attributes' as being similar
to a 'tab with properties'. The groups which are available for this
TypedEntity is based on the AttributeDefinitions assigned to the
EntitySchema.<br />
 The RelationProxyCollection is an enumerable sequence of
RelationProxy objects, which I won't go into details about. For now
you just need to know that it contains proxy classes for
Relations.</p><p>So now we know a little bit about what the TypedEntity looks
like. The EntitySchema is also fairly important to learn about as
it contains the schema for our TypedEntity, so before putting all
of these objects into context I'll outline the EntitySchema
object.<br />
 An <strong>EntitySchema</strong> consists of a
<strong>SchemaType</strong>, <strong>AttributeTypes</strong>,
<strong>AttributeDefinitions</strong>,
<strong>AttributeGroups</strong>, <strong>XmlConfiguration</strong>
and a <strong>RelationProxyCollection</strong>.<br />
 SchemaType is simply a string which represents which type of
schema this EntitySchema is. As an example this could be "file",
"system", "content", "user" etc.<br />
 AttributeTypes is a collection of AttributeType objects, which
describes the type of attribute we are dealing with. So this is the
schema for our TypedAttribute, which we use to describe how an
attribute is stored.<br />
 AttributeDefinitions is a collection of AttributeDefinition
objects, which define each attribute that is added to a schema. An
AttributeDefinition stores an Alias, Name, AttributeType and
AttributeGroup.<br />
 The AttributeGroups collection on the EntitySchema is Get-only,
which returns an EntityCollection with all the groups defined in
the AttributeDefinitions.<br />
 XmlConfiguration is a XDocument which is used to store the
selected icon / thumbnail and description for a document
type.<br />
 The RelationProxyCollection is similar to that found on the
TypedEntity except here we find proxies for the EntitySchema's
relations.</p><p>Lets try to put the above into the context of a File object,
which we already have in the source of Umbraco v5. The File object
is a strongly typed object based on TypedEntity with its own
EntitySchema (FileSchema), which is used to describe the properties
on our File object.<br /><br />
 This is what the FileSchema object looks like:</p><pre class="code"><span>namespace</span> Umbraco.Framework.Persistence.Model.IO
{
    <span>public class</span><span>FileSchema</span> : <span>EntitySchema</span>  {
        <span>public</span> FileSchema()
        {
            SchemaType = <span>FixedSchemaTypes</span>.File;
            AttributeDefinitions.Add(<span>new</span><span>AttributeDefinition</span>  {
                Alias = <span>"name"</span>,
                Name = <span>"Name"</span>,
                AttributeType = <span>AttributeTypeRegistry</span>.Current.GetAttributeType(<span>StringAttributeType</span>.AliasValue),
                AttributeGroup = <span>FixedGroupDefinitions</span>.GeneralGroup
            });

            AttributeDefinitions.Add(<span>new</span><span>AttributeDefinition</span>  {
                Alias = <span>"rootedPath"</span>,
                Name = <span>"RootedPath"</span>,
                AttributeType = <span>AttributeTypeRegistry</span>.Current.GetAttributeType(<span>StringAttributeType</span>.AliasValue),
                AttributeGroup = <span>FixedGroupDefinitions</span>.GeneralGroup
            });

            AttributeDefinitions.Add(<span>new</span><span>AttributeDefinition</span>  {
                Alias = <span>"rootRelativePath"</span>,
                Name = <span>"Root Relative Path"</span>,
                AttributeType = <span>AttributeTypeRegistry</span>.Current.GetAttributeType(<span>StringAttributeType</span>.AliasValue),
                AttributeGroup = <span>FixedGroupDefinitions</span>.GeneralGroup
            });

            AttributeDefinitions.Add(<span>new</span><span>AttributeDefinition</span>  {
                Alias = <span>"publicUrl"</span>,
                Name = <span>"Public URL"</span>,
                AttributeType = <span>AttributeTypeRegistry</span>.Current.GetAttributeType(<span>StringAttributeType</span>.AliasValue),
                AttributeGroup = <span>FixedGroupDefinitions</span>.GeneralGroup
            });

            AttributeDefinitions.Add(<span>new</span><span>AttributeDefinition</span>  {
                Alias = <span>"isContainer"</span>,
                Name = <span>"Is Container"</span>,
                AttributeType = <span>AttributeTypeRegistry</span>.Current.GetAttributeType(<span>IntegerAttributeType</span>.AliasValue),
                AttributeGroup = <span>FixedGroupDefinitions</span>.GeneralGroup
            });

            AttributeDefinitions.Add(<span>new</span><span>AttributeDefinition</span>  {
                Alias = <span>"contentBytes"</span>,
                Name = <span>"Content Bytes"</span>,
                AttributeType = <span>new</span><span>BytesAttributeType</span>(),
                AttributeGroup = <span>FixedGroupDefinitions</span>.GeneralGroup
            });
        }
    }
}
</pre><p><br />
 The schema has five AttributeDefinitions, which corresponds to the
properties on the File object, which is shown below.<br />
 Each definition is put in the GeneralGroup AttributeGroup and
assigned a Name and Alias, which is used to put values in the
TypedAttributeCollection of the TypedEntity. Each AttributeType in
the AttributeDefinitions are strings, so the standard
StringAttributeType is used.<br />
 And this is what the File object looks like:</p><pre class="code"><span>namespace</span> Umbraco.Framework.Persistence.Model.IO
{
    <span>public class</span><span>File</span> : <span>TypedEntity</span>  {
        <span>public</span> File()
        {
            <span>this</span>.SetupFromSchema&lt;<span>FileSchema</span>&gt;();
            IsContainer = <span>false</span>;
        }

        <span>public</span> File(<span>TypedEntity</span> fromEntity)
        {
            <span>this</span>.SetupFromEntity(fromEntity);

        }

        <span>public</span> File(<span>HiveId</span> id)
            : <span>this</span>()
        {
            Id = id;
        }

        <span>public string</span> Name
        {
            <span>get</span> { <span>return</span> (<span>string</span>)Attributes[<span>"name"</span>].DynamicValue; }
            <span>set</span>  {                
                <span>if</span> (!RootedPath.IsNullOrWhiteSpace() &amp;&amp; <span>Path</span>.GetFileName(RootedPath) != <span>value</span>)
                {
  <span>var</span> rootLocation = RootedPath.Substring(0, RootedPath.LastIndexOf(Name));
                    Attributes[<span>"rootedPath"</span>].DynamicValue = <span>Path</span>.Combine(rootLocation, <span>value</span>);
                }
                Attributes[<span>"name"</span>].DynamicValue = <span>value</span>;
            }
        }

        <span>public bool</span> IsContainer
        {
            <span>get</span> { <span>return</span> (<span>bool</span>)Attributes[<span>"isContainer"</span>].DynamicValue; }
            <span>set</span> { Attributes[<span>"isContainer"</span>].DynamicValue = <span>value</span>; }
        }

        <span>public string</span> RootedPath
        {
            <span>get</span> { <span>return</span> (<span>string</span>)Attributes[<span>"rootedPath"</span>].DynamicValue; }
            <span>set</span>  {
                Attributes[<span>"rootedPath"</span>].DynamicValue = <span>value</span>;
  <span>if</span> (Name != <span>Path</span>.GetFileName(<span>value</span>))
                {
                    Attributes[<span>"name"</span>].DynamicValue = <span>Path</span>.GetFileName(<span>value</span>);    
                }
            }
        }

        <span>public string</span> RootRelativePath
        {
            <span>get</span> { <span>return</span> (<span>string</span>)Attributes[<span>"rootRelativePath"</span>].DynamicValue; }
            <span>set</span> { Attributes[<span>"rootRelativePath"</span>].DynamicValue = <span>value</span>; }
        }

        <span>public string</span> PublicUrl
        {
            <span>get</span> { <span>return</span> (<span>string</span>)Attributes[<span>"publicUrl"</span>].DynamicValue; }
            <span>set</span> { Attributes[<span>"publicUrl"</span>].DynamicValue = <span>value</span>; }
        }

        <span>public byte</span>[] ContentBytes
        {
            <span>get</span>  {
                <span>var</span> content = (<span>byte</span>[])Attributes[<span>"contentBytes"</span>].DynamicValue;
                <span>if</span> (content == <span>null</span>)
                {
                    <span>if</span> (LazyContentStream == <span>null</span>)
                        <span>return new byte</span>[0];  <span>using</span> (<span>var</span> streamValue = LazyContentStream.Value)
                    {
                        ContentBytes = content = streamValue.ReadAllBytes();
                    }
                }
                <span>return</span> content;
            }
            <span>set</span>  {
                <span>if</span> (IsContainer)
                    <span>throw new</span><span>InvalidOperationException</span>(
                        <span>string</span>.Format(
                            <span>"Entity '</span><span>{0}</span><span>' is a container and hence cannot have content assigned to it. To set content ensure that the IsContainer property is false."</span>,
                            Id));

                Attributes[<span>"contentBytes"</span>].DynamicValue = <span>value</span>;
            }
        }

  <span>public</span><span>Lazy</span>&lt;<span>Stream</span>&gt; LazyContentStream { <span>get</span>; <span>set</span>; }
    }
}
</pre><p>As the code shows we have three options for constructing the
File object. All of them use the FileSchema which has been defined
for this type of entity.<br />
 The interesting part of the File is how we get and set the various
properties. Notice that we are using the underlying
TypedAttributeCollection to get and set the actual values of the
properties. You might also want to note that because we are using
dynamic we can add more than one value, which in turn has to
correspond with the defined AttributeType.</p><p>This is how we save a File object using Unit of Work and Hive
when an image is being uploaded in the backoffice:</p><pre class="code"><span>private</span><span>HiveId</span> StoreFile(<span>HttpPostedFileBase</span> file)
{
    <span>var</span> hive = BackOfficeRequestContext.Application.Hive.GetWriter&lt;<span>IFileStore</span>&gt;(<span>new</span><span>Uri</span>(<span>"storage://file-uploader"</span>));

    <span>var</span> mediaId = <span>Guid</span>.NewGuid();   

    <span>using</span> (<span>var</span> uow = hive.Create())
    {
        <span>var</span> f = <span>new</span><span>File</span>  {
            RootedPath = mediaId.ToString(<span>"N"</span>) + <span>"/"</span> + file.FileName
        };
        <span>var</span> stream = file.InputStream;
        <span>if</span> (stream.CanRead &amp;&amp; stream.CanSeek)
        {
            stream.Seek(0, <span>SeekOrigin</span>.Begin);
            <span>using</span> (<span>var</span> mem = <span>new</span><span>MemoryStream</span>())
            {
                stream.CopyTo(mem);
                f.ContentBytes = mem.ToArray();
            }
        }

        uow.Repositories.AddOrUpdate(f);
                
        uow.Complete();

        <span>return</span> f.Id;
    }
}
</pre><p><br />
 I hope you are getting the broader picture here, because with a
schema defined we can store any object that derive from TypedEntity
as the schema is telling Hive how the data should be stored and
retrieved.</p><p>Summary description of the concepts/classes involved:<br /><strong>TypedEntity</strong> - Contains a key value collection of
attributes, ea. a collection of TypedAttribute objects. The
TypedEntity also contains the schema that defines it.<br /><strong>TypedAttribute</strong> - Contains the actual value(s) and
conforms to an AttributeDefinition.<br /><strong>EntitySchema</strong> - Definition of a schema used by a
TypedEntity.<br /><strong>AttributeDefinition</strong> - Definition of the attribute
ea. Alias, Name, AttributeType and AttributeGroup.<br /><strong>AttributeGroup</strong> - The group which the attribute
belongs to.<br /><strong>AttributeType</strong> -The type of the attribute, i.e.
string, integer, bool, text.<br /><em>- A side note: An AttributeType has a SerializationType, which
implements IAttributeSerializationDefinition. This tells Hive the
format the data is stored in (String, LongString, SmallInt,
LargeInt, Decimal, Date, Guid, Boolean, ByteArray).</em></p><p>There are a lot of predefined AttributeType(s) in Umbraco v5,
which you can re-use. They can be found in the
Umbraco.Framework.Persistence project under the following folder
\Model\Constants\AttributeTypes.</p><p>If you want to see more examples of defining your own
AttributeType, AttributeDefinition and AttributeGroup I recommend
that you take a look at the source code of the WordPress Hive
provider, which Alex created for a presentation in Sweden last
year: <a href="https://bitbucket.org/boxbinary/hive-wordpress-provider/src/bb3055fd06ad/Umbraco.Hive.Providers.Wordpress/Schema/Model">
https://bitbucket.org/boxbinary/hive-wordpress-provider/src/bb3055fd06ad/Umbraco.Hive.Providers.Wordpress/Schema/Model</a></p><p>I will do a follow post about repositories in v5, which should
give some insight into the various repositories we work with when
we want to persist a TypedEntity, EntitySchema etc. in Umbraco
v5.</p><div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/UmbracoBlog?a=rWEHslv-Pns:3u9fGqYMg7w:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/UmbracoBlog?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/UmbracoBlog?a=rWEHslv-Pns:3u9fGqYMg7w:V_sGLiPBpWU"><img src="http://feeds.feedburner.com/~ff/UmbracoBlog?i=rWEHslv-Pns:3u9fGqYMg7w:V_sGLiPBpWU" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/UmbracoBlog/~4/rWEHslv-Pns" height="1" width="1"/>]]></content:encoded><feedburner:origLink>http://umbraco.com/follow-us/blog-archive/2012/1/23/persistence-model-in-v5.aspx</feedburner:origLink></item><item><title>Umbraco 5 RC 2 is on CodePlex, ready for download</title><link>http://feedproxy.google.com/~r/UmbracoBlog/~3/MCleizMzD7w/umbraco-5-rc-2-is-on-codeplex,-ready-for-download.aspx</link><pubDate>Wed, 11 Jan 2012 18:50:59 GMT</pubDate><guid isPermaLink="false">http://umbraco.com/follow-us/blog-archive/2012/1/11/umbraco-5-rc-2-is-on-codeplex,-ready-for-download.aspx</guid><content:encoded><![CDATA[<p><a href="http://issues.umbraco.org/releaseNotes?q=Fix+versions%3A+%7B5.0+RC+2%7D&amp;title=Fix+version%3A+RC+2&amp;token=3571C3085FBD1FD25D6E8F2F4B1D5F88&amp;verbose=false"><img src="http://umbraco.com/media/342832/Windows-Live-Writer_Umbraco-5-RC-2_F3FB_image_3.png" /></a><a href="http://umbraco.com/follow-us/blog-archive/2011/12/22/umbraco-5-rc1-is-out-today.aspx">Before Christmas, we put up RC 1</a> - our first
build of the "last mile to 5.0" process, so to speak. That was just
under three weeks ago, meaning about 1.5 weeks of "official"
working time for many, but the community have already put in a
brilliant effort and we've got a lot of useful issues resolved.</p><p>To get the latest fixes in the hands of people who might not be
following the code repository or using nightlies, we thought we'd
put up an RC 2.</p><p><a href="http://issues.umbraco.org/releaseNotes?q=Fix+versions%3A+%7B5.0+RC+2%7D&amp;title=Fix+version%3A+RC+2&amp;token=3571C3085FBD1FD25D6E8F2F4B1D5F88&amp;verbose=false" target="_blank" title="Changeset for Umbraco 5 RC 2">There's a
fairly long list of fixes / changes that were possible in time for
the RC 2. The list is available on our new issue tracker</a>,
YouTrack, which so far is proving very popular; we've had a lot of
really useful reports - <a href="http://issues.umbraco.org/dashboard/#tab=Hints" target="_blank">please keep them coming</a>. There's even <a href="http://umbraco.codeplex.com/SourceControl/network/Forks/abutland/InheritanceOnlyDocTypes/contribution/1764" target="_blank">a great pull request in there too</a>, not bad for
the first week in January!</p><p><a href="http://umbraco.codeplex.com/releases/view/80350" target="_blank" title="Download page for Umbraco 5.0 RC 2">You can
<strong>download the build</strong> from the CodePlex page
here</a>.</p><h3>Upgrading from RC 1:</h3><ol><li>Backup your existing site (of course!) and for good measure,
keep a copy of your Hive connection string config at
/App_Data/Umbraco/HiveConfig/web.config</li><li>Backup any other config files in /App_Data/Umbraco/Config to
which you've made any changes (Hive, Trees, etc), as well as the
root Web.config file</li><li>Copy over the /Bin, /Areas and /App_Plugins/Core folders and
the root Web.config file from the downloaded zip</li><li>Restore the config files you backed up</li></ol><p>If you have been developing packages or plugins, and you
encounter any type-load issues, please flush your temporary ASP.NET
files and let us know on the issue tracker.</p><p>We'll continue to work hard to get critical bugs <a href="http://umbraco.com/follow-us/blog-archive/2012/1/4/umbraco-5-on-performance-and-the-perils-of-premature-optimisation.aspx">and performance</a> nailed for our first
production release of Umbraco 5.0 in the next few weeks. Thanks
again to all who are helping us get there!</p><div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/UmbracoBlog?a=MCleizMzD7w:48grAbWpDC0:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/UmbracoBlog?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/UmbracoBlog?a=MCleizMzD7w:48grAbWpDC0:V_sGLiPBpWU"><img src="http://feeds.feedburner.com/~ff/UmbracoBlog?i=MCleizMzD7w:48grAbWpDC0:V_sGLiPBpWU" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/UmbracoBlog/~4/MCleizMzD7w" height="1" width="1"/>]]></content:encoded><feedburner:origLink>http://umbraco.com/follow-us/blog-archive/2012/1/11/umbraco-5-rc-2-is-on-codeplex,-ready-for-download.aspx</feedburner:origLink></item><item><title>Umbraco 5: On performance and the perils of premature optimisation</title><link>http://feedproxy.google.com/~r/UmbracoBlog/~3/s0jciBeRqNI/umbraco-5-on-performance-and-the-perils-of-premature-optimisation.aspx</link><pubDate>Wed, 04 Jan 2012 22:46:44 GMT</pubDate><guid isPermaLink="false">http://umbraco.com/follow-us/blog-archive/2012/1/4/umbraco-5-on-performance-and-the-perils-of-premature-optimisation.aspx</guid><content:encoded><![CDATA[<p><a href="http://umbraco.codeplex.com/releases/view/79260" target="_blank" title="Umbraco CMS 5.0 RC 1 download page on CodePlex"><img src="http://umbraco.com/media/340788/Windows-Live-Writer_Umbraco-5-On-performance-and-premature-o_EF8E_image_14.png" /></a>Just before Christmas we released the latest
pre-production build of Umbraco 5 for testing, and so far we've had
about 800 downloads and great feedback.</p><p>Great feedback is not necessarily "Guys, everything is awesome
and works". While nice star-ratings are always lovely (thanks!),
truly 'great' feedback is valuable info about what is broken: the
reports of quirks, bugs and any user confusion that show us areas
that we've missed and can fix in time for the first
production-ready build.</p><p>And this is why we're <em>really</em> happy: it's been two weeks
since we put that release out just before Christmas, and over the
holiday period we've already had around 40 users register at our <a href="http://issues.umbraco.org/issues" target="_blank">new v5
issue tracker</a> and a great bunch of useful issues reported that
<a href="https://twitter.com/#!/umbraco/status/154200477070929920" target="_blank">we're already working hard to eradicate</a>.</p><p>You have to notice a flaw in something in order to fix it, and
we've been delighted to accept pull requests submitted over the
holidays from dedicated folks that prove how awesome the Umbraco
community is.</p><p><img src="http://umbraco.com/media/340778/Windows-Live-Writer_Umbraco-5-On-performance-and-premature-o_EF8E_image_13.png" />One thing which rightly has cropped up, and I
consider it a valid issue worth tracking just like anything else,
is the speed of running a website on these pre-production v5
builds. If you've taken the builds for a spin, especially on a
machine using a spindle-based hard drive and using SqlCe, you'll
have noticed it's very slow.</p><p>I thought I'd put up a quick post reassuring you that with the
testing builds so far, this is partly by design, and explain how
it'll receive focus this month as we prep for a production-ready
5.0 at the end of Jan.</p><p><em>If you're not into the technical details, the primary point
is that this month is our planned moment when we make v5 shiny,
speedy and ready.</em></p><h2>Make it work, then make it work good, then make it work
fast</h2><p>Basically, I can sum it up pretty quick: there's no caching in
there yet. Job done, right? Blogpost over.</p><p>Well, that's actually just a small part of the story.</p><p>When putting out these pre-release builds, we've had to strike a
balance between features and performance precisely to help the
bug-reporting process. And so, the preview builds have run slow,
but the bugs that have cropped up have been due to real code rather
than caching, and can be reproduced - and fixed - much easier.</p><p><a href="http://www.lovepetrol.com/images/1/wtf/25592390411_large.jpg" target="_blank" title="Image from ExoticSpotter.com"><img src="http://www.lovepetrol.com/images/1/wtf/25592390411_large.jpg" width="400" height="300" style="display: inline; float: right;" align="right" /></a>Imagine you're
good with tools, and you're building a family car from a kit. You
only have the engine fitted to the chassis and some wheels at the
moment, and it goes OK but it's a bit slow already.</p><p>So, given you want the car to be fast when it's finished, do you
spend weeks optimising the engine now, maybe replacing heavier
suspension with the latest trendy lightweight component, even
though your beloved creation doesn't yet have any doors? Or do you
carry on, and take quantitative measurements later when you are
approaching an understanding of the whole car and how it behaves
when everything is fitted - and it's heavier?</p><p>Well, the automotive engineers amongst us will point out I know
nothing about how to build a car :) But when it comes to software,
it pays to wait. As I've mentioned before, premature optimisation
is a big killer on complex projects. We could have piled hundreds
of hours into shaving 5kg off the weight of the car's suspension,
only to find out it's actually now top-heavy and rolls in corners.
Likewise, a few days could have been spent optimising a v5 database
query we thought would be crucial, but it turns out the query only
gets run once a month. It pays dividends time and time again to
wait until your architecture is at least 80% feature-complete
before you can begin to gauge where to put your effort and
resources into optimising it in daily use.</p><h2>Making it production-ready</h2><p>Starting this week, we've split effort into two tracks to take
us to our first production release: resolving <a href="http://issues.umbraco.org/issues" target="_blank">critical
logged issues</a>, and performance profiling. The below is
basically my primary focus for the rest of this month:</p><h3>Code profiling</h3><p>Profilers are a fantastic weapon in the developer's armoury.
They allow you to get quantitative data about the performance of
individual portions of your application, without resorting to tons
of trace logging and guesswork.</p><p>For .NET code, I like dotTrace from JetBrains, because it allows
you to profile unit tests straight from Visual Studio so you can
get at performance data for known, repeatable units of work.</p><p>Here, I've <em>artificially slowed down</em> a unit test and
used the product's "Tracing" technique which gives accurate
measurements of how long each of my .NET methods takes. This
measuring slows down my application, but it does so uniformly, so
as long as you deal in percentage improvements between tests,
you're good to go. Below you can see this test exercises a chain of
methods involved in finding an entity in Hive when given a route.
Basically, one of the first things to happen when a request for a
URL comes in:</p><p><a href="http://umbraco.com/media/340690/Windows-Live-Writer_Umbraco-5-On-performance-and-premature-o_EF8E_image_6.png"><img src="http://umbraco.com/media/340695/Windows-Live-Writer_Umbraco-5-On-performance-and-premature-o_EF8E_image_thumb_2.png" /></a></p><p>The level of detail is fantastic for forensic investigations and
finding those hotspots.</p><p>This is the type of testing I'm doing at the moment and for the
rest of this month: looking at common methods, seeing where the
bottlenecks are, and working on improving them. You can see here
I've reduced the GetEntityByPath method to 10% of its original
execution time, and I can measure the impact on the rest of the
stack with dotTrace. If this method is used in many places (and it
is), the benefits go across the board.</p><p>Code itself is not the only thing to blame: sometimes you have a
lot of database queries, or they are poorly optimised. Since the
default Hive provider in Umbraco 5 uses NHibernate, I can use the
excellent NHProf from Hibernating Rhinos to get insight into
exactly what queries resulted from a test:</p><p><a href="http://umbraco.com/media/340700/Windows-Live-Writer_Umbraco-5-On-performance-and-premature-o_EF8E_image_8.png"><img src="http://umbraco.com/media/340705/Windows-Live-Writer_Umbraco-5-On-performance-and-premature-o_EF8E_image_thumb_3.png" /></a></p><p>The unit test I've been focussing on today does a lot of work
all in one NHibernate "session", and that's really not a problem as
I'm in a contrived testing scenario, but it's useful as I can
repeat that same scenario and compare the results each time. The
above SQL that is selected in the screenshot is 1 query returning 1
row taking &lt;1ms. <em>Prior to today, that same operation was 5
queries, 158 rows and 252ms.</em></p><p>It's a fairly well-worn path from here-on out. We have unit
tests that we know represent the status quo of the build out there
receiving feedback from the community, and we have a track that is
busy working on those bugs already. Matt managed to fix almost 10
in his first day back, which is awesome.</p><p>In the meantime this month, we're working on improving the code
itself so that we can make smarter optimisations.</p><p>My aim as always is 200ms response times for an average page,
before adding the catch-all page-level output caching.</p><h3>A quick note about caching</h3><p>Code that works well rather than relying on caching is easier to
maintain, easier to test, easier to predict, and easier to fix. But
that's not to say caching doesn't have a place at all. There is
very little caching in the codebase; it's something I prefer to add
at the last stage, but it does still require attention. Caching
which URL resolves to which piece of content, for example, requires
us to cleverly invalidate the cache if any of the content's parents
change. But we've put the hooks in place for this type of eventing
and this is getting wired-up at the moment. And finally, output
caching of common website pages will be enabled in
configuration.</p><p> </p><p>Core features for a 5-point-0 release are pretty much there,
they primarily just need polishing and speeding-up. We'll be
putting out another RC release containing fixes and the first half
of the performance improvements next week, so you'll get a version
that is more fun to play with. In the meantime, thanks again for
all the testing and reporting that you are doing - it's absolutely
brilliant so far. If you would like to help out, we always love
pull requests, and if like me you get a weird nerdy kick out of
code profiling please do <a href="https://twitter.com/#!/umbracoproject" target="_blank">get in
touch</a>!</p><div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/UmbracoBlog?a=s0jciBeRqNI:euRM2tzM0OQ:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/UmbracoBlog?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/UmbracoBlog?a=s0jciBeRqNI:euRM2tzM0OQ:V_sGLiPBpWU"><img src="http://feeds.feedburner.com/~ff/UmbracoBlog?i=s0jciBeRqNI:euRM2tzM0OQ:V_sGLiPBpWU" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/UmbracoBlog/~4/s0jciBeRqNI" height="1" width="1"/>]]></content:encoded><feedburner:origLink>http://umbraco.com/follow-us/blog-archive/2012/1/4/umbraco-5-on-performance-and-the-perils-of-premature-optimisation.aspx</feedburner:origLink></item><item><title>Umbraco 5 RC1 is out today</title><link>http://feedproxy.google.com/~r/UmbracoBlog/~3/uo_o1dRAIpU/umbraco-5-rc1-is-out-today.aspx</link><pubDate>Thu, 22 Dec 2011 12:30:32 GMT</pubDate><guid isPermaLink="false">http://umbraco.com/follow-us/blog-archive/2011/12/22/umbraco-5-rc1-is-out-today.aspx</guid><content:encoded><![CDATA[<p>Hi everyone! Have you booked up your Seasonal Religious-or-not
Coding Fun calendar yet? No? Well, allow me to proffer a toy for
the holidays. We've put up a couple of new Umbraco 5 builds for you
to try out. We're calling it Release Candidate 1 - we're almost
there in terms of features, and the remaining work for us to get to
a 5.0 release is around performance, bugfixes from community
testing, and any quick wins around handy methods that help with
building a site.</p><p>As usual, if you're new to Umbraco 5 or you've come here from a
web search, there is some background to the other releases we've
done in the previous few months:</p><p>- <a href="http://umbraco.com/follow-us/blog-archive/2011/9/5/umbraco-5-alpha-1-release.aspx">Umbraco 5 Alpha 1 Release</a></p><p>- <a href="http://umbraco.com/follow-us/blog-archive/2011/9/28/umbraco-5-alpha-2-is-out-today.aspx">Umbraco 5 Alpha 2 is out today</a></p><p>- <a href="http://umbraco.com/follow-us/blog-archive/2011/10/21/umbraco-5-alpha-3-is-out-today.aspx">Umbraco 5 Alpha 3 is out today</a></p><p>- <a href="http://umbraco.com/follow-us/blog-archive/2011/11/11/umbraco-5-beta-1-is-out-today.aspx">Umbraco 5 Beta 1 is out today</a></p><p>You can <a href="http://umbraco.codeplex.com/releases/view/79260" target="_blank">download the RC 1 web application zip from
CodePlex</a>, and within minutes of this blogpost going up <a href="http://umbraco.com/umbraco-5-status">our status page will reflect the latest
updates too</a>.</p><p>Before we crack on, a quick word about timings: while we haven't
matched our recent hopes for a Christmas 5.0 completed release, we
do know that we will be able to put it out by the end of January.
We have now reached the point where we're going to be working on
performance and bugfixes in time for 5.0, so that we can then
quickly add any popular missing features with future releases (5.1,
etc.) We're really grateful for your help testing this release, and
we'll be using your feedback to make a lightning-fast, stable 5.0
after Christmas.</p><h2>What's in the release?</h2><p>Today's release has two parts. The first has the same level of
User support as Beta 1 - i.e., no Members section. The second
download is the same fundamental codebase, but with the Members
section added. Work on this has not yet been completed, and we're
keeping it on a parallel build for the moment so that we can
evaluate community feedback and leave the option open for us to
release 5.0 either with or without Members support depending on how
the testing goes. We'd really appreciate if you could give that one
a try too and let us know how you get on.</p><h3>Issue Tracker</h3><p>Speaking of "letting us know", it's about time we helped you
help the project, by introducing the promised place to log v5
issues. We have used the CodePlex Issues tracker for some time, and
it's been very good to us, but there are some niggles - and so <a href="http://issues.umbraco.org">we've created a new issue tracker
at <strong>http://issues.umbraco.org</strong></a> for people to use
for v5 RC1. We'd love feedback on this too, as if all goes well, we
could see this as the new central tracker in the future.</p><p>We also have some exciting ideas about how to integrate this
with the Karma system on Our - if you have any ideas too, please <a href="http://our.umbraco.org" target="_blank">let us know</a>!</p><p>The tracker is based on the excellent YouTrack from JetBrains,
who have been kind enough to give us a free license for our
open-source project.</p><p>Registration is open to all. After logging in, you will see the
welcome page that gives you a few hints on querying the issues
log.</p><p><a href="http://umbraco.com/media/337537/Windows-Live-Writer_a50cf434f8cb_9BC5_image_2.png"><img src="http://umbraco.com/media/337542/Windows-Live-Writer_a50cf434f8cb_9BC5_image_thumb.png" /></a></p><p>We've got some issues in there already that we'll be working on
in time for 5.0:</p><p><a href="http://umbraco.com/media/337547/Windows-Live-Writer_a50cf434f8cb_9BC5_image_4.png"><img src="http://umbraco.com/media/337552/Windows-Live-Writer_a50cf434f8cb_9BC5_image_thumb_1.png" /></a></p><p>Logging an issue is really straightforward. You can select a
release that you're targeting, and easily include screenshots from
your clipboard or filesystem from the "Attach" menu:</p><p><a href="http://umbraco.com/media/337557/Windows-Live-Writer_a50cf434f8cb_9BC5_image_6.png"><img src="http://umbraco.com/media/337562/Windows-Live-Writer_a50cf434f8cb_9BC5_image_thumb_2.png" /></a></p><h2>Features added since Beta 1</h2><h3>Composite document types</h3><p>A few people noticed a big feature lacking in Beta 1: inherited
document types. Support for this was in the architecture from the
beginning, but it didn't make the cut for that release. Today's
download has the feature ready and waiting to be tested.</p><p>Where it slightly differs from v4.7 is that you can now have
multiple parent document types! <img src="http://umbraco.com/media/337567/Windows-Live-Writer_a50cf434f8cb_9BC5_wlEmoticon-partysmile_2.png" /> You can have two master document types, say
"SEO Fields" and "Article Fields", and have a "News Article"
document type that inherits the fields of both. We merge any tabs
that have the same alias too, so that your editors see fields in
common tabs grouped together.</p><p>You can change this inheritance structure at any time, but be
warned of course that you may end up removing existing properties
that you have filled out for content.</p><p>Here's an example: I've got a News Article document type which
inherits from both "Seo Fields" and "Article Fields". My News
Article type has a tab called "Article", and so does the "Article
Fields" document type. If I edit "Article Fields", I can see my
"Article" tab with its "Body Text" field:</p><p><a href="http://umbraco.com/media/337781/Windows-Live-Writer_a50cf434f8cb_9BC5_image_18.png"><img src="http://umbraco.com/media/337786/Windows-Live-Writer_a50cf434f8cb_9BC5_image_thumb_8.png" /></a></p><p>If I edit the child "News Article" document type, I can see the
inherited properties greyed-out for reference, and also the "News
Title" field that only exists on this document type. I've also got
some greyed-out Seo fields there because I'm also inheriting from
my handy "Seo Fields" document type.</p><p><a href="http://umbraco.com/media/337791/Windows-Live-Writer_a50cf434f8cb_9BC5_image_16.png"><img src="http://umbraco.com/media/337796/Windows-Live-Writer_a50cf434f8cb_9BC5_image_thumb_7.png" /></a></p><p>Editing some content that is a "News Article" shows the two
fields merged into one Article tab:</p><p><a href="http://umbraco.com/media/337801/Windows-Live-Writer_a50cf434f8cb_9BC5_image_20.png"><img src="http://umbraco.com/media/337806/Windows-Live-Writer_a50cf434f8cb_9BC5_image_thumb_9.png" /></a></p><h3>Dictionary</h3><p>The dictionary is now in there too. You'll notice it in the
backoffice under the Settings tree, and you can use the
@Umbraco.GetDictionaryItem helper in your templates to insert a
value. As I mentioned in the previous release, the Dictionary in v5
uses our revised Language support that allows for fallbacks. So, if
you specify that the Belgian French language "falls back" to
regular French, any Dictionary items that are blank for Belgian
French will revert to the value in the regular French language.
This should be a timesaver for scenarios where your usage of the
language in your website only differs in a few key words.</p><p>A quick word about keys: many have seen that you can have a
"hierarchical" dictionary in v4, but you still have to find unque
names for your keys, because you refer to them by only their key
and not their path in your templates.</p><p>This changes in v5. Here's two dictionary items that I have:</p><p><a href="http://umbraco.com/media/337592/Windows-Live-Writer_a50cf434f8cb_9BC5_image_12.png"><img src="http://umbraco.com/media/337597/Windows-Live-Writer_a50cf434f8cb_9BC5_image_thumb_5.png" /></a></p><p>Here's the code for using them:</p><div style="background-color: #201629; display: inline; float: none; margin: 0px; max-height: 400px; overflow: auto; padding: 0px; white-space: nowrap;" id="scid:9ce6104f-a9aa-4a17-a79f-3a39532ebf7c:1ceec1f4-3df7-430f-9008-2de39cd90df3" class="wlWriterEditableSmartContent"><span>&lt;</span><span>p</span><span>&gt;</span><span>My
key:</span><span>@</span><span>Umbraco.GetDictionaryItem(</span><span>"MyKey"</span><span>
)</span><span>&lt;/</span><span>p</span><span>&gt;</span><br /><span>&lt;</span><span>p</span><span>&gt;</span><span>My key
2:</span><span>@</span><span>Umbraco.GetDictionaryItem(</span><span>"MyKey/MyKey2"</span><span>
)</span><span>&lt;/</span><span>p</span><span>&gt;</span></div><p>Also, since Dictionary items are "just regular content" in Hive,
we get Rollback, Move, Copy, and Permissions, all "for free":</p><p><a href="http://umbraco.com/media/337602/Windows-Live-Writer_a50cf434f8cb_9BC5_image_14.png"><img src="http://umbraco.com/media/337607/Windows-Live-Writer_a50cf434f8cb_9BC5_image_thumb_6.png" /></a></p><h3>Preview</h3><p>You can now click the 'Save' button followed by the 'Preview'
button and see your page rendered with the latest revision rather
than the published copy.</p><h3>Hierarchy navigators on DynamicModel</h3><p>In your templates, you can now use the following navigators:</p><ul><li>DynamicModel.Ancestors</li><li>DynamicModel.AncestorsOrSelf</li><li>DynamicModel.Descendants</li><li>DynamicModel.DescendantsOrSelf</li><li>DynamicModel.Children</li><li>DynamicModel.Parent</li></ul><p>Each of these navigators also has more querying and sorting
support on there. The following methods are available:</p><ul><li>Single</li><li>SingleOrDefault</li><li>First</li><li>FirstOrDefault</li><li>Last</li><li>LastOrDefault</li><li>Any</li><li>Count</li><li>Where</li><li>OrderBy</li><li>OrderByDescending</li></ul><p>All of these methods except the last two accept a string for
querying against the dynamic properties on a piece of content. You
can just supply the string, like v4:</p><div style="background-color: #201629; display: inline; float: none; margin: 0px; max-height: 400px; overflow: auto; padding: 0px; white-space: nowrap;" id="scid:9ce6104f-a9aa-4a17-a79f-3a39532ebf7c:9cb4eb05-956c-4c96-b425-209005334ff4" class="wlWriterEditableSmartContent"><span>DynamicModel.Children.FirstOrDefault(</span><span>"publisher
== \"APRESS\""</span><span>)</span></div><p>or you can supply parameters in order if you prefer - the
numbers just correspond to the order of parameters that you supply
after the first part:</p><div style="background-color: #201629; display: inline; float: none; margin: 0px; max-height: 400px; overflow: auto; padding: 0px; white-space: nowrap;" id="scid:9ce6104f-a9aa-4a17-a79f-3a39532ebf7c:8be92aa4-5496-4c29-b43f-557c1acd4373" class="wlWriterEditableSmartContent"><span>DynamicModel.Children.FirstOrDefault(</span><span>"publisher
== @0"</span><span>,</span><span>"APRESS"</span><span>)</span></div><p>Normally, if you're used to dealing with lists of objects in
.NET (IEnumerable&lt;Something&gt;) you may know that when you
access methods like myList.Count(), the Count() method is actually
what's called an "extension method" - it's a static method defined
in one place that can be used on anything that implements
IEnumerable&lt;Something&gt;. Why do we care? Because these static
methods don't work on dynamic objects - those where not even Visual
Studio knows the properties available, because .NET figures it out
when your page is being rendered. But it would be a great pain to
have to either not have those handy methods like Count(), Any(),
First() on DynamicModel or have to call them in the alternative
unintuitive way. So we've added them explicitly to the collection
that underpins Ancestors, Children etc.</p><p>Long story short, it means you can also do queries like this,
using Where() with Count() tacked on the end:</p><div style="background-color: #201629; display: inline; float: none; margin: 0px; max-height: 400px; overflow: auto; padding: 0px; white-space: nowrap;" id="scid:9ce6104f-a9aa-4a17-a79f-3a39532ebf7c:5a7c8574-9722-45ad-b48f-977fe34f0f95" class="wlWriterEditableSmartContent"><span>DynamicModel.Descendants.Where(</span><span>"NodeTypeAlias ==
@0"</span><span>,</span><span>"BookPage"</span><span>).Count()</span></div><p>The OrderBy and OrderByDescending methods take a property alias,
e.g. OrderBy("Name")</p><p>You can also use the same underscore prefix as in v4.7 in order
to put a "recursive" property into your template. This is a
throwback to the legacy of XSLT when it was straightforward to say
"my current page might not have this property, but please go up the
tree until you've found one". A bit like an "inherited" property.
Where you would normally write <em>DynamicModel.SiteName</em> to
put the Name property from the current page, you can put
<em>DynamicModel._siteName</em> with the underscore and lowercasing
indicating to the system that, if that property isn't found, it'll
go up the tree until it's found it.</p><h3>Alternative Templates</h3><p>If you have more than one template available for the document
type of your content, you can now include that in the Url similarly
to v4. For example, here's the homepage template that I've been
using to test querying, it has some cruft at the top:</p><p><a href="http://umbraco.com/media/337572/Windows-Live-Writer_a50cf434f8cb_9BC5_image_10.png"><img src="http://umbraco.com/media/337577/Windows-Live-Writer_a50cf434f8cb_9BC5_image_thumb_4.png" /></a></p><p>And here's the cleaner one that I called AltHomepage.cshtml on
my filesystem, and added to my Homepage doctype, accessed by adding
?altTemplate=althomepage to my browser address bar:</p><p><a href="http://umbraco.com/media/337582/Windows-Live-Writer_a50cf434f8cb_9BC5_image_8.png"><img src="http://umbraco.com/media/337587/Windows-Live-Writer_a50cf434f8cb_9BC5_image_thumb_3.png" /></a></p><h2>Happy bug-hunting holidays!</h2><p>As always, we really appreciate the time people take to test out
these releases - even putting up with it not having many
performance optimisations until the final stage - and both
reporting issues, and collaborating on <a href="http://our.umbraco.org" target="_blank">the community
site</a> and <a href="http://umbraco5contrib.codeplex.com" target="_blank">on the contrib project</a>.</p><p>So, best wishes to you and yours, and see you in the forums!</p><p>Team 5</p><div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/UmbracoBlog?a=uo_o1dRAIpU:0HHS-TWn9P0:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/UmbracoBlog?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/UmbracoBlog?a=uo_o1dRAIpU:0HHS-TWn9P0:V_sGLiPBpWU"><img src="http://feeds.feedburner.com/~ff/UmbracoBlog?i=uo_o1dRAIpU:0HHS-TWn9P0:V_sGLiPBpWU" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/UmbracoBlog/~4/uo_o1dRAIpU" height="1" width="1"/>]]></content:encoded><feedburner:origLink>http://umbraco.com/follow-us/blog-archive/2011/12/22/umbraco-5-rc1-is-out-today.aspx</feedburner:origLink></item><item><title>Community Compatibility</title><link>http://feedproxy.google.com/~r/UmbracoBlog/~3/mmBRc93Fyrs/community-compatibility.aspx</link><pubDate>Wed, 14 Dec 2011 13:22:03 GMT</pubDate><guid isPermaLink="false">http://umbraco.com/follow-us/blog-archive/2011/12/14/community-compatibility.aspx</guid><content:encoded><![CDATA[<p><img src="http://umbraco.com/media/335732/compatexample.png" />Today we
released a new feature over at <a href="http://our.umbraco.org">our.umbraco.org</a> to help identify
package version compatibility. </p><p>Previously it was up to the developer to specify whether a
package was compatible with certain versions, however it
sometimes wasn't entirely accurate.  So we decided to give it
to you, the community, to report on whether or not a package works
with a certain version of Umbraco. </p><p>If you are logged in and once you have downloaded a package you
will be given an opportunity to report on compatibility.  This
information will be shared with the community via a small report
displayed in the side bar of the package detail page. </p><h3>What do the Smileys mean?</h3><p>The smiley faces specify how satisfied the community is that it
works with that version of Umbraco. 0%, it has been reported that
it doesn't work through to 100%, everyone has reported that it does
work.</p><h3>Whats in it for me?</h3><p>For every package you submit a report for you will receive one
karma point.  You can report as many times as you like, if a
report exists from you we will simply update your existing report,
however only one karma point will be given per package.  We
believe this will lead to data on compatibility being far more
accurate and will give confidence when downloading a package for
the first time, knowing somebody within the community has tested it
before you.  We already know what packages you have downloaded
in the past, <a href="http://our.umbraco.org/projects">so get to
it</a>, earn a little karma and spread a little love. </p><div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/UmbracoBlog?a=mmBRc93Fyrs:_m-P2kx4jAM:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/UmbracoBlog?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/UmbracoBlog?a=mmBRc93Fyrs:_m-P2kx4jAM:V_sGLiPBpWU"><img src="http://feeds.feedburner.com/~ff/UmbracoBlog?i=mmBRc93Fyrs:_m-P2kx4jAM:V_sGLiPBpWU" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/UmbracoBlog/~4/mmBRc93Fyrs" height="1" width="1"/>]]></content:encoded><feedburner:origLink>http://umbraco.com/follow-us/blog-archive/2011/12/14/community-compatibility.aspx</feedburner:origLink></item></channel></rss>

