Visual Studio Extensions for Umbraco

Hello all,
I haven’t blogged for a little while, as I have been busy with my new pet project uHangout. If you haven’t checked it out yet I highly recommend you do, as it s a weekly Google Hangout that I record and publish on YouTube with guests from the Umbraco community demoing implementations, snippets, packages or just general interviews like I did with founder Niels Hartvig & Per Ploug

So my next little lunchtime hacks has been involved in working with extending Visual Studio to make our life’s easier when working with Umbraco. After recently coming across the project SideWaffle from Sayed Hashimi and Mads Kristensen from Microsoft, I was inspired by how they have added new file templates such as an AngularJS Controller and others.

So with this idea I approached Sayed for some advice on how I can create Umbraco file templates in the same way. I was given some great pointers and I am now able to present to you the

Umbraco Community – Visual Studio Project Item Templates package for Visual Studio

You can download the extension directly inside Visual Studio from the extensions section or on the Visual Studio Gallery website.

If you are intrigued on how it all works then the full source code is available on GitHub for you to look through as well.

But it doesn’t stop there!

As I created another Visual Studio package that adds a new project template to Visual Studio. So with one click you can do File -> New Project and select the new Umbraco project template. This will install and setup Umbraco for you by fetching the latest version of Umbraco from NuGet.

Now you will be able to impress your boss as you install & setup Umbraco so quickly.
Like before this extension can be found when searching inside Visual Studio for extensions and the gallery website but I have also put the source code of is extension on GitHub as well.

I have a few more ideas for Visual Studio Extensions to make our lives easier as Umbraco Developers, but I would love to hear what you think.

Cheers,
Warren 🙂

Restrict Umbraco Media Filesize with JS

Hello all,
This is a very quick & brief blog post for a quick code snippet. I had a requirement today to at The CogWorks restrict file size upload for media items in Umbraco and to display a friendly error message.

For this to work easily, I created a .NET usercontrol with the following in:


<script type="text/javascript">
 //Go get file size from .config value in bytes
 var fileSizeToCheck = <%= ((HttpRuntimeSection) ConfigurationManager.GetSection("system.web/httpRuntime")).MaxRequestLength %>
</script>
<script type="text/javascript" src="/usercontrols/MediaFileSize/MediaFileSizeValidation.js"></script>

<div id="fileSize"></div>

The next part was to create a custom document type in Umbraco using the UserControl Wrapper method and pointing the datatype to my newly created usercontrol.

The next step was to assign this document type as a property on my image media type. I gave it name like FileSize Check, however this name does not matter as I do not use the property value at all, it’s only purpose is to run the custom Javascript inside it, which is as follows:

//When DOM ready
$(function () {
    
    //Get the File Size DOM element & hide it's label & property area
    $('#fileSize').closest('.propertypane').hide();

    //On form submit
    $("form").on("submit", function (event) {

        //Get the file input type
        var fileInput = $("input[type=file]")[0];

        console.log(fileInput);
        console.log(fileSizeToCheck);

        //Validate filesize
        if (!validateFileSize(fileInput, fileSizeToCheck)) {
            
            //Show validtion message
            UmbClientMgr.mainWindow().UmbSpeechBubble.ShowMessage('error', 'File Size', 'The file chosen is too big, please choose a smaller file than ' + fileSizeToCheck/1024 + 'kb');
            
            //Cancel form event
            event.preventDefault();
        }        
    });
});

///http://deepeshdarshan.wordpress.com/2012/06/20/how-to-validate-upload-file-size-and-file-extension-using-javascript/
function validateFileSize(component, maxSize) {
    
    if (navigator.appName == "Microsoft Internet Explorer") {
        if (component.value) {
            var oas = new ActiveXObject("Scripting.FileSystemObject");
            var e = oas.getFile(component.value);
            var size = e.size;
        }
    }
    else {
        if (component.files[0] != undefined) {
            size = component.files[0].size;
        }
    }
    
    if (size != undefined && size > maxSize) {
        component.value = "";
        component.focus();
        
        return false;
    }
    else {
        return true;
    }
}

As you can see from the JavaScript I first hide the property from the Umbraco backoffice UI, as we don’t need to show a label and an emtpy box for the media UI, but the main part of the code hooks into the form on submit event and then grabs the file input type and passes it to the validateFileSize function(). If the file is too big then we display an error message using the Umbraco message notification bubble in the bottom right hand corner.

Well that’s all there is to it.
Hopefully this little snippet will have helped you out.

Cheers,
Warren 🙂

Umbraco Community Google Hangouts

Hello all,
I had a brilliant idea on the train ride into work this morning. Why don’t we do a Google Hangout where members of the Umbraco community can join and show of their website implementations, packages or general code snippets and advice.

So I thought let’s just make it happen rather than just sit around and think about it, otherwise it will be another one of my ideas that just dies a miserable death!

I asked around on twitter if anyone was able to join me on my lunch break and join me for twenty or so minutes to chat and demo some stuff. Luckily someone replied!

So I present to you the first Umbraco Community Google Hangout with Jon Humphrey as the guest who demo’d his Umbraco 6 MVC implementation of http://lawcare.org.uk

My goal is to try and do this quite regularly with the community so we can all learn from one another and also learn about the awesome but often hidden Umbraco packages within the community. Depending on feedback I may make this a regular weekly Friday slot or perhaps bi-weekly.

Let me know what you think of the format and how often I should do it please in the comments!

Tea Commerce – Certified Developer

Well I have just got back into The Cogworks office after having two days out to do some training in one of the most popular E-Commerce packages, Tea Commerce for Umbraco which is from the fantastic Danish developers Anders Burla Johansen & Rune Grønkjær over at Tea Solutions.

First of all I have to say I have no commercial experience with building e-commerce websites, so going on a two day course to learn how to build E-Commerce websites using my favorite and flexible CMS Umbraco was a very exciting prospect.

The course itself was very well structured and thought out and Anders from Tea Commerce taught us on day one how to build a very simple WebShop using Tea Commerce using some of the basic APIs and on the second day we learnt about product variants, multilingual and the more advanced .NET APIs along with the very clean and well structured JavaScript API.

My colleague at The CogWorks is a big fan of version one of Tea Commerce and was keen to hear about my experience of using version two of Tea Commerce at the training. My colleague previous niggle was that there was little or no documentation that he could easily find. I can proudly say to him now that the guys from Tea Commerce have put a lot of effort into this with thorough documentation across all of their APIs with good real world examples that allow a quick copy and paste coding if you wish to.

So after two fantastic days with Anders and a bunch of other Umbraco developers we can now all proudly say we are now certified Umbraco Tea Commerce Developers!

Warren Buckley is a Tea Commerce Certified Developer
Warren Buckley is a Tea Commerce Certified Developer

I can highly recommend this course if you are considering getting into the world of E-Commerce with Umbraco and is well worth the money and the two days out of the office to learn something new & exciting.

The wonderful assistant

Today I helped out ex colleague and good friend Per Ploug with his first LIVE Google Hangout broadcast to YouTube to help direct some questions and interject with some questions of my own.

So if you missed Per giving a fantastic demo & introduction on how to build a Markdown Property Editor for Umbraco Belle, then I highly recommend you watch the video from the hangout, in order to catch up.

How I built my first property editor for Umbraco Belle

After recently building my first AngularJS project, Diagnostics for Umbraco so I can learn the framework as Umbraco Belle is built with Angular.

So my next step was to learn how to build an Umbraco property editor for Belle, before me and my colleagues at The CogWorks along with lead Belle developer Per Ploug to host a Belle hands on workshop.

Currently Per has written a fantastic tutorial for creating your first property editor in where you create a markdown property editor which is a great tutorial that I followed.

But for me to ensure I learnt the skills properly then I decided to create my first property editor by myself.

If you remember when I was working at the HQ I wrote a blog tutorial on creating a property editor which was a RGBA colour picker. In this tutorial I will be recreating the same property editor for Belle.

So first thing first is to create a folder called RGBAEditor in App_Plugins in an Umbraco Belle installation. This is where we store the HTML, JS and package manifest file for our property editor.

{
    propertyEditors: [      
        {
            id: "B2FE9CFE-50FC-42A5-9DFE-35DE84953C67",
            name: "(CWS) RGBA Colour Picker",
            editor: {
                view: "~/App_Plugins/RGBAEditor/rgba-editor.html"
            }
        }
    ]
    ,
    javascript: [
        '~/App_Plugins/RGBAEditor/rgba.controller.js'
    ]
}

In this JSON, we give our property a unique GUID, a friendly name for our property editor so we can choose it from the back office and then we define the HTML Angular JS view for our property editor in this case it’s rgba-editor.html and finally we define our Javascript we need to load for this property editor which in this case is our AngularJS controller file – rgba.controller.js

Next we need to our HTML for our property editor, in this case it will contain three sliders and an element to show a live preview of the RGBA colour. So in rgba-editor.html file we need the following.

<div ng-controller="CWS.RGBAController">

    <div class="row">
        <!-- SLIDERS -->
        <div class="sliders span8">
            <!-- RED -->
            <div class="control-group">
                 <label class="control-label" for="rgba-red">Red</label>
                <div class="controls">
                     <input type="text" name="rgba-red" ng-model="renderModel.red" class="slider red" data-slider-min="0" data-slider-max="255" data-slider-step="1" data-slider-value="255" data-slider-orientation="horizontal" data-slider-selection="after" data-slider-tooltip="show"/>
                </div>
            </div>

            <!-- GREEN -->
            <div class="control-group">
                 <label class="control-label" for="rgba-green">Green</label>
                <div class="controls">
                     <input type="text" name="rgba-green" ng-model="renderModel.green" class="slider green" data-slider-min="0" data-slider-max="255" data-slider-step="1" data-slider-value="0" data-slider-orientation="horizontal" data-slider-selection="after" data-slider-tooltip="show"/>
                </div>
            </div>

            <!-- BLUE -->
            <div class="control-group">
                 <label class="control-label" for="rgba-blue">Blue</label>
                <div class="controls">
                     <input type="text" name="rgba-blue" ng-model="renderModel.blue" class="slider blue" data-slider-min="0" data-slider-max="255" data-slider-step="1" data-slider-value="0" data-slider-orientation="horizontal" data-slider-selection="after" data-slider-tooltip="show"/>
                </div>
            </div>

            <!-- ALPHA -->
            <div class="control-group">
                 <label class="control-label" for="rgba-alpha">Alpha (%)</label>
                <div class="controls">
                     <input type="text" name="rgba-alpha" ng-model="renderModel.alpha" class="slider alpha" data-slider-min="0" data-slider-max="100" data-slider-step="1" data-slider-value="100" data-slider-orientation="horizontal" data-slider-selection="after" data-slider-tooltip="show"/>
                </div>
            </div>
        </div>

        <!-- PREVIEW -->
        <div class="preview span4">
            <!-- This will show a live preview of the RGBA colour based on jQuery UI sliders below -->
            <div id="rgba-preview-{{model.alias }}"><span ng-style="{background: preview}"></span></div>
            {{ renderModel.red }} {{ renderModel.green }} {{ renderModel.blue }} {{ renderModel.alpha }}
        </div>
    </div>

    <hr/>

    <h6>Debug JSON</h6>
    {{ model | json }}

</div>

In this HTML I am using the Bootstrap CSS styles to help create a simple layout as Belle uses Twitter Bootstrap for it’s styling. The ng-controller attribute on the opening div is used to map our AngularJS controller to our view. We then have lots of data attributes on our inputs, this is because we are using a jQuery plugin for Bootstrap styled sliders that require these attributes to be present on the text input field.

The slider plugin that I am using for this is the Eyecon.ro Bootstrap Slider. In addition in this view you will see we use some custom properties that we store on the scope such as red, green, blue etc so that when the slider is updated our AngularJS controller knows about it and finally we use the ng-style attribute to update the CSS background property on the element from the concatenated value of preview stored on our scope in our controller.

Lets now move onto our JS controller to see the final piece of the puzzle.

angular.module("umbraco").controller("CWS.RGBAController", function ($scope, $log, assetsService) {

    //tell the assetsService to load the bootstrap slider
    //libs from the plugin folder
    assetsService
        .loadJs("/app_plugins/RGBAEditor/lib/bootstrap-slider/bootstrap-slider.js")
        .then(function () {

            //Initiate sliders
            $('.slider').slider();

            //Update the preview DIV function...
            var RGBChange = function () {
                //Log...
                $log.log("Fired RGBCHange()");

                $scope.$apply(function () {
                    //Divide by 100 to get decimal needed for RGBA css
                    var alpha = a.getValue() / 100;

                    //Store the value as a CSV
                    $scope.model.value = [r.getValue(), g.getValue(), b.getValue(), alpha].join();

                    //Set the preview value, so we can update the view
                    $scope.preview = 'rgba(' + $scope.model.value + ')';
                });
            };

            //Slider values stored in data object
            var r = $('.red').slider().on('slideStop', RGBChange).data('slider');
            var g = $('.green').slider().on('slideStop', RGBChange).data('slider');
            var b = $('.blue').slider().on('slideStop', RGBChange).data('slider');
            var a = $('.alpha').slider().on('slideStop', RGBChange).data('slider');

            //this will be comma delimited 'r,g,b,a'
            if ($scope.model.value && (typeof $scope.model.value === "string")) {
                var splitVals = $scope.model.value.split(",");

                //Get values from split and set the sliders
                r.setValue(splitVals[0].trim());
                g.setValue(splitVals[1].trim());
                b.setValue(splitVals[2].trim());

                //Alpha convert back to full %
                var alphaConvert = splitVals[3].trim() * 100;
                a.setValue(alphaConvert);

                //set the preview background value
                $scope.preview = 'rgba(' + $scope.model.value + ')';
            }
        });

    //load the seperate css for the editor to avoid it blocking our js loading
    assetsService.loadCss("/app_plugins/RGBAEditor/lib/CWS-rgba.css");
    assetsService.loadCss("/app_plugins/RGBAEditor/lib/bootstrap-slider/slider.css");

});

The code is heavily commented above and should make sense, but I will go over some key points in it. First we define our controller CWS.RGBAController which is the same as the ng-controller attribute in our view. Next key point is the assetsService which the Umbraco guys have made that allows us to load in external Javascript dependencies. In this case I am loading in the Eyecon.ro Bootstrap Slider library so that I can use it. Once it’s loaded we can work with it inside the .then function.

In here we initiate our sliders and then have a function for every time one of the sliders is updated we update our scope values, the most important being $scope.model.value as this is what will be saved back into Umbraco when the user clicks save on the document and in addition we update the preview as well on the scope so that we can allow the colour preview to be updated in the HTML view. We store the RGBA value in Umbraco as a CSV string r,g,b,a.

The final part to this is to get the values when the property editor is initially loaded and set the sliders to those values. Which we will need to do for when we come back to the node when the values have been saved by doing a simple split of the values and then setting the sliders back to those values from the CSV string stored in Umbraco.

It’s as easy as that to create a property editor for Umbraco Belle, no Visual Studio needed. No compiling down to DLLs and writing C# code. This is so easy to do that your front-end developer can start writing property editors for Umbraco. Which is fantastic news 🙂

Here’s to a bright and happy future with Umbraco Belle.

Diagnostics for Umbraco

Well after a short weeks holiday I have come back and released a new must have package for any Umbraco 6.1 site or newer. This handy little package is called Diagnostics and it does exactly what it says on the tin. It shows you diagnostical information about your Umbraco install.

Features

This package was a bit of an experiment for me in order to learn how to write an AngularJS application. So later on this post I will cover some of the basics of what I wrote and show you some parts of the code.

  • Umbraco Version, assembly & release notes
  • Database type & connection string
  • Server information, ASP.NET version etc…
  • Assemblies along with MD5 & SHA1 Checksums
  • List the packages installed
  • List the Umbraco backoffice users
  • List the domains in use for the site
  • List all the folders and their current permissions applied to them
  • List all the Umbraco events and what is attached to those events
  • List the MVC Routes used in the site
  • List all the Trees used within the Umbraco backoffice

Let’s see it in action

Please note this video is ever so slightly out of date and the UI has been given a little bit love rather than messy UL list’s

http://screenr.com/0iRH

Download it

You can download the Diagnostics package from the Our Umbraco project page and the source code is publicly available on GitHub where you can view the source and log any issues along with any feature requests.

Show me the code!

OK so this was my first experiment into the world of AngularJS and I wanted to build a small app using it, as the new Umbraco user interface is getting overhauled in version 7 aka Belle and will be using AngularJS as well. So any head start on this would be highly beneficial.

Firstly I looked at many videos and resources before diving in. But the video I highly recommend you watch is this one from Dan Wahlin

Now you have watched that I can go over some parts of the code.

First let’s start with the index.html page found in /App_Plugins/Diagnostics.

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <title>Umbraco Diagnostics</title>

    <!-- Latest compiled and minified CSS -->
    <link rel="stylesheet" href="//netdna.bootstrapcdn.com/bootstrap/3.0.0-rc1/css/bootstrap.min.css">
</head>
<body ng-app="umbracoDiagnosticsApp">
    
    <h1>Diagnostics</h1>
    <!-- Nav -->
    <ul class="nav nav-tabs">
        <li ng-class="{active: locationUrl == '/'}">
            <a href="#/">General</a>
        </li>
        <li ng-class="{active: locationUrl == '/packages'}">
            <a href="#/packages">Packages</a>
        </li>
        <li ng-class="{active: locationUrl == '/users'}">
            <a href="#/users">Users</a>
        </li>
        <li ng-class="{active: locationUrl == '/domains'}">
            <a href="#/domains">Domains</a>
        </li>
        <li ng-class="{active: locationUrl == '/assemblies'}">
            <a href="#/assemblies">Assemblies</a>
        </li>
        <li ng-class="{active: locationUrl == '/permissions'}">
            <a href="#/permissions">Permissions</a>
        </li>
        <li ng-class="{active: locationUrl == '/events'}">
            <a href="#/events">Events</a>
        </li>
        <li ng-class="{active: locationUrl == '/routes'}">
            <a href="#/routes">MVC Routes</a>
        </li>
        <li ng-class="{active: locationUrl == '/trees'}">
            <a href="#/trees">Trees</a>
        </li>
    </ul>

    <!-- Placeholder for views -->
    <div ng-view=""></div>
    
    <!-- JS -->
    <script type="text/javascript" src="scripts/angular1.0.7.min.js"></script>
    <script type="text/javascript" src="scripts/app.js"></script>

    <!-- Latest compiled and minified JavaScript -->
    <script src="//netdna.bootstrapcdn.com/bootstrap/3.0.0-rc1/js/bootstrap.min.js"></script>
</body>
</html>

The things to note is the ng-app attribute on the body tag, the ng-class attributes on the LI elements and the ng-view on the div.

I will cover what these items do a bit later on.

Next we need to take a look at the app.js file in /App_plugins/Diagnositcs/scritps/app.js

var umbracoDiagnosticsApp = angular.module('umbracoDiagnosticsApp', []);

umbracoDiagnosticsApp.config(function($routeProvider) {
    $routeProvider
        .when('/',
            {
                controller: 'GeneralController',
                templateUrl: 'partials/general.html'
            })
        .when('/packages',
            {
                controller: 'PackagesController',
                templateUrl: 'partials/packages.html'
            })        
        .otherwise({ redirectTo: '/' });
});


/*
=====================================
CONTROLLERS
=====================================
*/

//General Controller
umbracoDiagnosticsApp.controller('GeneralController', function ($scope, $http, $rootScope, $location) {
    $http.get('/Umbraco/Api/DiagnosticsApi/GetVersion').success(function (data) {
        $scope.version = data;
    });

    $http.get('/Umbraco/Api/DiagnosticsApi/GetVersionAssembly').success(function (data) {
        $scope.assembly = data;
    });
    
    $http.get('/Umbraco/Api/DiagnosticsApi/GetVersionComment').success(function (data) {
        $scope.comment = data;
    });
    
    $http.get('/Umbraco/Api/DiagnosticsApi/GetServerInfo').success(function (data) {
        $scope.server = data;
    });
    
    $http.get('/Umbraco/Api/DiagnosticsApi/GetDBInfo').success(function (data) {
        $scope.db = data;
    });
    
    //Pass location url value into an item on our scope object
    $rootScope.locationUrl = $location.$$url;
});

//Packages Controller
umbracoDiagnosticsApp.controller('PackagesController', function ($scope, $http, $rootScope, $location) {
    $http.get('/Umbraco/Api/DiagnosticsApi/GetPackages').success(function (data) {
        $scope.packages = data;
    });
    
    //Pass location url value into an item on our scope object
    $rootScope.locationUrl = $location.$$url;
});

The very first line in this app.js defines our AngularJS module and in this case it’s called umbracoDiagnosticsApp and this needs to be in the ng-app attribute in the HTML document as shown above.

The next part of this file is to wire up the URL routes, so when the link/URL changes we can load in a different view and controller into our div with the attribute of ng-view.

So when we click on the different tabs such as Packages, it loads the URL #/packages and then maps the view /partials/packages.html and to use the packages controller.

In this controller for packages we do a HTTP WebAPI call to /Umbraco/Api/DiagnosticsApi/GetPackages fetch some JSON and then we store the results of the JSON into an object called packages which we then use in our view.

So lets take a look at the partial view for packages to see how we display the package information.

<table class="table table-striped table-hover">
    <thead>
        <tr>
            <th>ID</th>
            <th>Name</th>
            <th>Version</th>
            <th>Author</th>
            <th>Has Update?</th>
        </tr>
    </thead>
    <tbody>
        <tr ng-repeat="package in packages">
            <td>{{ package.Id }}</td>
            <td>{{ package.Name }}</td>
            <td>{{ package.Version }}</td>
            <td>{{ package.Author }}</td>
            <td>{{ package.HasUpdate }}</td>
        </tr>
    </tbody>
</table>

So we use mustache in our partial view to output the properties stored in our packages JSON we received from our WebAPI call and with the ng-repeat attribute we can easily loop over each item in the collection and output the properties stored in the JSON.

So the final piece of the puzzle is to have a WebAPI setup in Umbraco to get our information back as JSON.

using umbraco.cms.businesslogic.web;
using Umbraco.Core.Configuration;
using umbraco.interfaces;
using Umbraco.Web.WebApi;
using umbraco.cms.presentation.Trees;
using Package = umbraco.cms.businesslogic.packager.repositories.Package;

namespace CWS.UmbracoDiagnostics.Web.Controllers
{
    public class DiagnosticsAPIController : UmbracoAuthorizedApiController
    {

        public List<PackageInstance> GetPackages()
        {
            var allPackages = new List<PackageInstance>();

            //Get packages
            var packages = InstalledPackage.GetAllInstalledPackages();

            //loop over them
            foreach (var item in packages)
            {
                allPackages.Add(item.Data);
            }

            //Return the list
            return allPackages;
        }        
    }
}

So in this WebAPI controller class I inherit from UmbracoAuthorizedApiController which only allows these requests to be made to the API if you are logged into the Umbraco backoffice to ensure this information is not publicly available.

So in a nutshell that is all the components that makes up this AngularJS Umbraco Diagnostics application.

Any questions or improvements to this then please let me know.

Thanks,
Warren

The new way to do a 404 Umbraco Handler

Hello all,
As you may or may not be aware I have been building a new Umbraco starter kit called CWS Start. In this package I wanted to have a 404 page setup for the site. Currently the way to setup a 404 page is to put a node ID in the umbracosettings.config file. My only concern with this approach is that if you delete the node and recreate the node then the 404 will stop working.

So I decided to ask the Umbraco community how they do 404’s and I got a fantastic response from the community.
http://our.umbraco.org/forum/developers/extending-umbraco/43866-Alternatives-to-404-in-umbracosettingsconfig

Stefan & Lee K gave me some fantastic answers and filled me on the new Request pipeline in Umbraco and a way on how to add a ContentFinder to Umbraco, aka the new way of doing 404 handlers in Umbraco 6.1 and any other type of content finders.

Show me the code!

    public class _404iLastChanceFinder : IContentFinder
    {
        public bool TryFindContent(PublishedContentRequest contentRequest)
        {
            //Check request is a 404
            if (contentRequest.Is404)
            {
                //Get the home node
                var home = contentRequest.RoutingContext.UmbracoContext.ContentCache.GetAtRoot().Single(x => x.DocumentTypeAlias == "CWS-Home");

                //Get the 404 node
                var notFoundNode = home.Children.Single(x => x.DocumentTypeAlias == "CWS-404");

                //Set Response Status to be HTTP 404
                contentRequest.SetResponseStatus(404, "404 Page Not Found");

                //Set the node to be the not found node
                contentRequest.PublishedContent = notFoundNode;
            }

            //Not sure about this line - copied from Lee K's GIST
            //https://gist.github.com/leekelleher/5966488
            return contentRequest.PublishedContent != null;
        }
    }

And then we need to register this in Umbraco on App Startup like so:

        protected override void ApplicationStarting(UmbracoApplicationBase umbracoApplication, ApplicationContext applicationContext)
        {
            //On application starting event...
            //Add to the ContentFinder resolver collection our custom 404 Content Finder resolver
            ContentLastChanceFinderResolver.Current.SetFinder(new _404iLastChanceFinder());
        }

There are other use cases for IContentFinders and Lee K has a great little example he posted to Gist

How I added a Custom Umbraco Member Type for CWS Reboot programmatically

Hello all,
I am currently in the progress of rebuilding and rebooting the CWS Starter Kit project for Umbraco built in MVC on Umbraco 6. For this it will contain a members area and there is no way currently to package up member types and its custom properties.

So read on how to find out how I managed to come up with a solution to this problem.

Continue reading “How I added a Custom Umbraco Member Type for CWS Reboot programmatically”

Don’t make the same mistake as I did when creating a custom Umbraco macro parameter type

In this blog post I will share with you some advice and a code example of a custom Umbraco macro parameter I built for a client Umbraco package.

This needed to be able to exclude document types, but the list shown to them needed to be filtered to begin with. By hiding document types that have no templates and by also excluding a predetermined list of document types such as configuration folders etc…

So read on to find out how I achieved it with some help of my colleague Anthony Dang to help debug an issue with it, which I will discuss later on.

Continue reading “Don’t make the same mistake as I did when creating a custom Umbraco macro parameter type”