1

Tuesday, January 31, 2012 by Alex Norcliffe

534529467_f0ebb68dbbToday 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.

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.

Umbraco 5.0 RTM is on CodePlex!

Please do grab a copy - take two, if you like - it's free after all!

Thanks to you

imageThis 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.

Features

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 & rewritten technology stack but enabling the same common goals.

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.

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.

  • Design and produce templates quickly using the excellent Razor syntax
  • Access your content in those templates using an intuitive dynamic API for both querying and walking up and down your content structure
  • Tailor content types with a variety of customisable fields, meaning you can focus on your content structure without a hard link to its layout
  • 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
  • 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
  • Create, preview and publish content in a naturally organised way using folders that can automatically create your site navigation, if you like
  • Create, preview and publish media and other types of assets
  • Store those assets on your server or in the cloud
  • Use a rich set of permissions to tailor backoffice access for your editing team
  • 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
  • Plug in your own backoffice editors, dashboards, and custom trees
  • Expose the underlying MVC stack for mixing in your own application, controllers and views with the content-managed portion
  • Share common pieces of functionality like Macros with your team
  • Share your own data providers, common templates, handy helpers and more using NuGet packages
  • Have those packages dynamically add configuration to a user's website so that uninstalling rolls back configuration seamlessly

There are many more, but you didn't come here for a list of bullet points - here's that download link again!

Documentation & help

In the next few weeks we'll be hard at work making tutorials, documentation and answering questions on the Our forums. Warren has already got off to a great start with some example Macros for common scenarios.

Here's to a bright future

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, feel free to add it to our issue tracker and appeal for votes!

Performance

You might have seen the post I put up earlier this month about our approach to performance tuning as we approached RTM, and I also mentioned it in a recent uNews-letter. If not, or at least to put it here for posterity, here's a few of those figures.

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.

Database & Build

Total time for 50 requests

Equivalent requests per second

SqlCe4    
RC1 44.514s 1.12
RC2 29.902s 1.67
Mid-Jan 18.839s 2.65
RC3 1.693s 29.53
RTM 0.228s 219.30
     
Sql Server 2008 R2    
RC1 25.487s 1.96
RC2 11.681s 4.28
Mid-Jan 5.665s 8.82
RC3 1.645s 30.39
RTM 0.134s 373.13

To put those final figures into context, I re-ran the test against RTM with 1000 requests instead, and obtained around 2900rps.

This seems a steady improvement followed by an astronomical leap, what could it be?

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.

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.

Happy downloading!

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.

Here's that download link one more time.

All the best

Team 5

Thursday, January 26, 2012 by Niels Hartvig

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.

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!

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.

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 little bit of Umbraco history as the Umbraco MVPs.

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.

Because it felt right. 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.

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.

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!

"The unselfish effort to bring cheer to others will be the beginning of a happier life for ourselves.", Helen Keller

Thursday, January 26, 2012 by Warren Buckley

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 ASP.NET MVC 3 and the Razor View Engine.

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 & 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 :)

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!

The Basics

Lets start off with some of the basics, such as a quick glossary of terms as in V5 a few terms have been changed:

Property Editor
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.

Pre Values
This may be a new term to you, but Pre Values are the default settings and configurations that allow you to configure a PropertyEditor.

Plugin
A plugin is a single item that extends Umbraco. For example each one of these would be a separate plugin:

  • PropertyEditor
  • Tree
  • Context Menu Items

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.

Package
The term for a package has not really changed, but you may package up one or more plugins to create your package.

What Did I Make?

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.

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.

rgba-picker-sketch

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

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.

rgba-prototype

And finally below is the end result of the property editor inside an Umbraco 5 install.

Disclaimer: The video above is using an old version of Umbraco 5 and does not reflect the speed of V5 RC3 and newer

How to Create a PropertyEditor

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: Visual Web Developer 2010 Express.

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. However with that said it is not required that you know ASP.NET MVC to work with Umbraco V5.

One video series I can highly recommend is this series from PluralSight - Introduction to ASP.NET MVC3  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.

Now that we have got a basic understanding of MVC, lets get to work...
Firstly download a copy of the source code of my RGBA PropertyEditor from the Umbraco5Contrib project on CodePlex, as we will need this to copy some files and for you to use a guide.

  • Create a new project in Visual Studio of the project type Class Library using C#
  • Name your project RGBA.Umbraco.PropertyEditor
  • Create a folder called Resources 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.
  • Next create a folder called Views 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.
  • 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.
    • RGBAPickerEditor.cs
    • RGBAPickerEditorModel.cs
    • RGBAPickerPreValueModel.cs

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.

The files that we need to have as embedded resources are:

  • Resources/RGBAPicker.css
  • Resources/RGBAPicker.js
  • Resources/transparent-grid.png
  • Views/RGBAPickerEditor.cshtml

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 Build Action and choose the option labelled Embedded Resource

embedded-resource

Now when you build your project all those items will be available inside the DLL.

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.

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.

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.

RGBAPickerEditor.cs
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.

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.

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 - http://createguid.com

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.


//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<RGBAPickerEditorModel, RGBAPickerPreValueModel>
    {
        public override RGBAPickerEditorModel CreateEditorModel(RGBAPickerPreValueModel preValues)
        {
            return new RGBAPickerEditorModel(preValues);
        }
 
        public override RGBAPickerPreValueModel CreatePreValueEditorModel()
        {
            return new RGBAPickerPreValueModel();
        }
    }
}

RGBAPickerEditorModel.cs
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

  • Red
  • Green
  • Blue
  • Alpha
  • Hex
  • RGB
  • RGBA

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.

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.

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.

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...


//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<RGBAPickerPreValueModel>
    {
        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<string, object> 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();
        }
    }
}

RGBAPreValueModel.cs
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.

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.


//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; }
    }
}

Views/RGBAPickerEditor.cshtml
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.


@inherits WebViewPage<RGBA.Umbraco.PropertyEditor.RGBAPickerEditorModel>

//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 <div>
    var uniqueID = Guid.NewGuid().ToString();
    var pickerID = "rgba-" + uniqueID; 
}
 
<script type="text/javascript">
    $(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 => Model.Red)',
            blueID:     '#@Html.IdFor(x => Model.Blue)',
            greenID:    '#@Html.IdFor(x => Model.Green)',
            alphaID:    '#@Html.IdFor(x => Model.Alpha)',
            hexID:      '#@Html.IdFor(x => Model.Hex)'
        });
    });
</script>
 
 
@{
    //Here we need to say we want to use the CSS & JS file in our view
    Html
    .RequiresJsResource(typeof(RGBAPickerEditor), "RGBA.Umbraco.PropertyEditor.Resources.RGBAPicker.js")
    .RequiresCssResource(typeof(RGBAPickerEditor), "RGBA.Umbraco.PropertyEditor.Resources.RGBAPicker.css");
}
 
 
<!-- We give this div the unique pickerID -->
<div id="@pickerID" class="rgbaPicker">
    <div class="sliders">
        <div class="item">
            <!-- CSS classes used to easily target in JS to update -->
            <label>Red: <span class="redDisplay"></span></label>
            <div class="redSlider"></div>
            <!-- 
            Hidden textbox for the Red value we want to save.
            The value gets updated by the JS
             -->
            @Html.HiddenFor(x => Model.Red)
        </div>
 
        <div class="item">
            <!-- CSS classes used to easily target in JS to update -->
            <label>Green: <span class="greenDisplay"></span></label>
            <div class="greenSlider"></div>
            <!-- 
            Hidden textbox for the Green value we want to save.
            The value gets updated by the JS
             -->
            @Html.HiddenFor(x => Model.Green)
        </div>
 
        <div class="item">
            <!-- CSS classes used to easily target in JS to update -->
            <label>Blue: <span class="blueDisplay"></span></label>
            <div class="blueSlider"></div>
            <!-- 
            Hidden textbox for the Blue value we want to save.
            The value gets updated by the JS
             -->
            @Html.HiddenFor(x => Model.Blue)
        </div>
 
        <div class="item">
            <!-- CSS classes used to easily target in JS to update -->
            <label>Alpha: <span class="alphaDisplay"></span>%</label>
            <div class="alphaSlider"></div>
            <!-- 
            Hidden textbox for the Alpha value we want to save.
            The value gets updated by the JS
             -->
            @Html.HiddenFor(x => Model.Alpha)
        </div>
        
        <div>
            <!-- Disabled input for Hex # colour -->
            @Html.LabelFor(x => Model.Hex)
            @Html.TextBoxFor(x => Model.Hex, new { @class = "hex",  @readonly = "readonly" })
        </div>
    </div>
 
    <!-- Colour is previewed here -->
    <div class="livePreview"><span></span></div>
</div>

Resources/RGBAPicker.js
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.

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 <div> 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. Those V5 devs are a clever bunch, aren't they!

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.

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.

Outputting the Values

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.

So in my template I have the following code that outputs the values from a property with the alias of sidebarColour


<style type="text/css">
    /* 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);
    }
</style>

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.

How to Create the Package

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 download the Nuget GUI tool.

Once you have it installed, open the program and choose the create a new package option. Next we need to edit the metadata for our package. You can do this by finding the option Edit Package Metadata 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 RGBAPickerEditor.cs. 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

Before we add our DLL to our package, we need to make one small modification to the project. If you open the file AssemblyInfo.cs found under the Properties 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 /App_Plugins/Packages/PackageID


using Umbraco.Cms.Web;
[assembly: AssemblyContainsPlugins]

After adding in this change you will need to rebuild your project to ensure this change is made to the DLL.

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.

nuget-dialog

Once your done, your nuget package should look something like below.

rgba-package-meta

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.

Volia one property editor package, now you can install it into an Umbraco 5 website to test out your work.

Resources

Here are some useful resources that I recommend you take a look through:

Shannon Deminick's Blog Post Series on Plugins
http://shazwazza.com/post/Umbraco-Jupiter-Plugins-Part-1.aspx
http://shazwazza.com/post/Umbraco-Jupiter-Plugins-Part-2-Routing.aspx
http://shazwazza.com/post/Umbraco-Jupiter-Plugins-Part-3-Trees.aspx
http://shazwazza.com/post/Umbraco-Jupiter-Plugins-Part-4-Editors.aspx
http://shazwazza.com/post/Umbraco-Jupiter-Plugins-Part-5-Surface-Controllers.aspx

Shannon Deminick's CodeGarden 11 Session on Plugins Video
http://codegarden11.com/sessions/day-1/slot-two/get-plugged-in-to-umbraco-jupiter.aspx

The Umbraco V5 Contrib Project
http://umbraco5contrib.codeplex.com

Work in Progress: Estate Agent Starter Website
https://bitbucket.org/warrenbuckley/estate-agents-starter-site

The End Result

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!

You can download the RGBA Property Editor from our.umbraco.org along with another property editor I made which was the Bing Maps property editor.

http://our.umbraco.org/projects/backoffice-extensions/rgba-property-editor
http://our.umbraco.org/projects/backoffice-extensions/bing-maps-property-editor

Got any questions, just leave a comment and I will get back to you.

Cheers,
Warren - The friendly front end dev!

Monday, January 23, 2012 by Morten Christensen

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.
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.

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.

Lets dive a little deeper into the TypedEntity object and explore some of the related objects, which you need to know about.
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.
A TypedEntity consists of an EntitySchema, a TypedAttributeCollection, a list of AttributeGroup objects and a RelationProxyCollection.
The EntitySchema is used to describe the data that you want your TypedEntity to store - hence the word schema.
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.
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.
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.

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.
An EntitySchema consists of a SchemaType, AttributeTypes, AttributeDefinitions, AttributeGroups, XmlConfiguration and a RelationProxyCollection.
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.
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.
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.
The AttributeGroups collection on the EntitySchema is Get-only, which returns an EntityCollection with all the groups defined in the AttributeDefinitions.
XmlConfiguration is a XDocument which is used to store the selected icon / thumbnail and description for a document type.
The RelationProxyCollection is similar to that found on the TypedEntity except here we find proxies for the EntitySchema's relations.

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.

This is what the FileSchema object looks like:

namespace Umbraco.Framework.Persistence.Model.IO
{
    public class FileSchema : EntitySchema  {
        public FileSchema()
        {
            SchemaType = FixedSchemaTypes.File;
            AttributeDefinitions.Add(new AttributeDefinition  {
                Alias = "name",
                Name = "Name",
                AttributeType = AttributeTypeRegistry.Current.GetAttributeType(StringAttributeType.AliasValue),
                AttributeGroup = FixedGroupDefinitions.GeneralGroup
            });

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

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

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

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

            AttributeDefinitions.Add(new AttributeDefinition  {
                Alias = "contentBytes",
                Name = "Content Bytes",
                AttributeType = new BytesAttributeType(),
                AttributeGroup = FixedGroupDefinitions.GeneralGroup
            });
        }
    }
}


The schema has five AttributeDefinitions, which corresponds to the properties on the File object, which is shown below.
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.
And this is what the File object looks like:

namespace Umbraco.Framework.Persistence.Model.IO
{
    public class File : TypedEntity  {
        public File()
        {
            this.SetupFromSchema<FileSchema>();
            IsContainer = false;
        }

        public File(TypedEntity fromEntity)
        {
            this.SetupFromEntity(fromEntity);

        }

        public File(HiveId id)
            : this()
        {
            Id = id;
        }

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

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

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

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

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

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

                Attributes["contentBytes"].DynamicValue = value;
            }
        }

  public Lazy<Stream> LazyContentStream { get; set; }
    }
}

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.
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.

This is how we save a File object using Unit of Work and Hive when an image is being uploaded in the backoffice:

private HiveId StoreFile(HttpPostedFileBase file)
{
    var hive = BackOfficeRequestContext.Application.Hive.GetWriter<IFileStore>(new Uri("storage://file-uploader"));

    var mediaId = Guid.NewGuid();   

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

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

        return f.Id;
    }
}


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.

Summary description of the concepts/classes involved:
TypedEntity - Contains a key value collection of attributes, ea. a collection of TypedAttribute objects. The TypedEntity also contains the schema that defines it.
TypedAttribute - Contains the actual value(s) and conforms to an AttributeDefinition.
EntitySchema - Definition of a schema used by a TypedEntity.
AttributeDefinition - Definition of the attribute ea. Alias, Name, AttributeType and AttributeGroup.
AttributeGroup - The group which the attribute belongs to.
AttributeType -The type of the attribute, i.e. string, integer, bool, text.
- 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).

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.

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: https://bitbucket.org/boxbinary/hive-wordpress-provider/src/bb3055fd06ad/Umbraco.Hive.Providers.Wordpress/Schema/Model

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.

Wednesday, January 11, 2012 by Alex Norcliffe

imageBefore Christmas, we put up RC 1 - 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.

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.

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, YouTrack, which so far is proving very popular; we've had a lot of really useful reports - please keep them coming. There's even a great pull request in there too, not bad for the first week in January!

You can download the build from the CodePlex page here.

Upgrading from RC 1:

  1. 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
  2. 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
  3. Copy over the /Bin, /Areas and /App_Plugins/Core folders and the root Web.config file from the downloaded zip
  4. Restore the config files you backed up

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.

We'll continue to work hard to get critical bugs and performance 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!

Wednesday, January 04, 2012 by Alex Norcliffe

imageJust 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.

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.

And this is why we're really 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 new v5 issue tracker and a great bunch of useful issues reported that we're already working hard to eradicate.

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.

imageOne 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.

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.

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.

Make it work, then make it work good, then make it work fast

Basically, I can sum it up pretty quick: there's no caching in there yet. Job done, right? Blogpost over.

Well, that's actually just a small part of the story.

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.

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.

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?

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.

Making it production-ready

Starting this week, we've split effort into two tracks to take us to our first production release: resolving critical logged issues, and performance profiling. The below is basically my primary focus for the rest of this month:

Code profiling

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.

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.

Here, I've artificially slowed down 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:

image

The level of detail is fantastic for forensic investigations and finding those hotspots.

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.

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:

image

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 <1ms. Prior to today, that same operation was 5 queries, 158 rows and 252ms.

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.

In the meantime this month, we're working on improving the code itself so that we can make smarter optimisations.

My aim as always is 200ms response times for an average page, before adding the catch-all page-level output caching.

A quick note about caching

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.

 

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 get in touch!