Home > Blog

Attackmonkey Blog

Posts Tagged: Umbraco

Useful Umbraco Packages - Part 1

There are literally hundreds of packages that are available now on the Umbraco Package Library. For a beginner it can be quite hard to work out which packages still work, which ones are useful and what to use them for. I tend to find that there are a handful of packages that make it onto nearly every website that I build. In this series of posts, I'm going to look at some of my go to Umbraco packages in a bit of detail to show you why they're useful and what you can use it for.

Umbraco Contour

This is one of the commercial packages that you can buy from the HQ. At the time of writing it costs 99 Euros plus VAT, which is a bargain in my opinion. This awesome package allows you to quickly and easily build forms in your browser. You can also assign simple workflow items, like sending confirmation emails and submitting records to web services (such as a CRM for example). If you are using newer versions of Umbraco with Razor, you also get the ability to fully control the markup for the forms. There's also a decent API, so you can create your own custom form field types and worflows. Contour is such a powerful little tool that I just cost it into all my Umbraco projects these days! You can find out more about Contour here.

DocType Mixins

This is another really useful little gem. Out of the box with Umbraco, you can create DocTypes that inherit from a "parent" DocType. The Mixins package allows you to create special "Mixin" DocTypes that can be assigned to multiple DocTypes. If you've ever working with Rails, you'll be familiar with the concept. I find it much less restrictive than the inherited model, as you cn easily tweak the Mixin properties in individual DocTypes without affecting the others that use the same Mixin. One thing I use this for a lot is for things like SEO and Social meta data tabs that I need to include on the majority of DocTypes. It's also handy for things like sidebar tabs. You can find out more about DocType Mixins here. If you're more of a code first kind of guy or gal, you can also check out uSiteBuilder, which lets you do the same thing, but using classes in your Visual Studio project.

Config Tree

This is a handy package that allows you to edit all of the Umbraco config files from within the developers section of the back office (including the web.config file). This is very handy if you need to make quick changes. If you have everything under source control, you probably won't use it, but for any other situation, it's very handy to be able to edit the files without having to use FTP or remote desktop. You can download Config Tree here.

Robots.txt Editor

If you do a lot of SEO work, you may need to edit the robots.txt file occasionally. This handy packaage allows you to do that right in thedevelopers section of the back office, without resorting to FTP/remore desktop. You won't use it loads, but when you do, it's very handy indeed. Grab it here.

FamFamFam Icons

The default content tree icons are OK, but lets face it, they're a bit dull aren't they? Also, it's kind of hard to distinguish different page types by looking at them. So what can you do? You can download some extra icons and use those instead of the default ones. When you install this package, it adds a TON of icons for you to use. Got a news section? Why not use a newspaper icon for it, so that it's super obvious? Got a contact form? Use an envelope! You get the idea. You can download the icon package here. If the FamFamFam icons don't float your boat, you can also try the Fugue icons set too.

That's it for today, stay tuned for part 2 in the not too distant future!

Limiting an Examine Search to the Current Site 2

After some feedback from Jeroen and Shannon about yesterday's blog post, I've had a look at another method for having searches on multiple sites, which works much better for site that use multiple languages.

The issue is that different languages have different stop words, and word stems etc, so using the standard Examine analysers on say French content means that the results won't be as accurate as they would be using a French language specific indexer.

How do we do this? Firstly, we need to set up a specific index for each site, telling each on to start at the root node for the language. Set up the index set as you would normally, and then add the IndexParentId parameter to your declaration, like this:

<IndexSet  SetName="enSiteSearchIndexSet"  IndexPath="~/App_Data/TEMP/ExamineIndexes/enSiteSearch/"  IndexParentId="1090">

Once this is done, the index will ONLY index content beneath the parent node that you specified. You can then create an index for each site, allowing you to use different analyzers for each index if you want to.

If you prefix your searchers/indexes etc with the name of the root node, you can get that in your search code and use it to get the right searcher, so you'll never have to change the search code when adding new language sites (just add the new indexes etc to your Examine config).

Limiting an Examine Search to the Current Site

If you have a multi-language or multi site installation in Umbraco where you might want to have a site search using Examine, you'll run into the issue that the indexes contain the reults for ALL of the sites, not just the current site that the user is on.

I've been working on a multi-language site recently and ran into just this issue. Here's how I got round it and made a search that can be included on all of the sites, with no changes needing to be made.

First up, how can we limit the search? Handily, we can use the path variable, which stores the path of the page in the Umbraco content tree, in a format something like: -1,1060,1075,1230, where -1 denotes the content root, and the rest of the numbers are the nodes between the root and page that you're looking at.

In our user control that does the search, we can get the current node, and rather than jumping back up the tree, we can just split the path variable out and get the 2nd item in the array to get the id of the site root node, like this:

var currentPage = umbraco.NodeFactory.Node.GetCurrent();
string parentId = currentPage.Path.Split(',')[1];

Now we know the root node of the current site, how can we use it with our search? Handily, you can just add the path to your index settings file. However, the path gets stored in the index in a comma separated format, which is no good for searching, as Examine treats it as one big string, so searching for the root node on the raw path will return no results. However, if you were to replace the commas with spaces in the index, the numbers in the path would be treated like words, so you could search for your root node on it, and it would return only pages with the root node in their path.

So how to alter the index? Easy! You can plug into the Examine events to alter the index as it's being written. Basically we want to hook into ther event, get the path field, replace the commas with spaces, and then save it as a new field in the Examine index. Here's an example of the code that we used in an AppliactionBase class to hook into the event handler and make the changes:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using umbraco.BusinessLogic;
using Examine;

namespace MySite.UmbracoExtensions.EventHandlers
{
    public class CmsEvents : ApplicationBase
    {
        public CmsEvents()
        {
            //Add event to allow searching by site section
            var indexerSite = ExamineManager.Instance.IndexProviderCollection["SiteSearchIndexer"];
            indexerSite.GatheringNodeData += new EventHandler(SetSiteSearchFields);
        }

        //modifies the index field for the path variable, so that it can be searched properly
        void SetSiteSearchFields(object sender, IndexingNodeDataEventArgs e)
        {
            //grab the current data from the Fields collection
            var path = e.Fields["path"];

            //let's get rid of those commas!
            path = path.Replace(",", " ");

            //add as new field, as path seems to be a reserved word in Lucene
            e.Fields.Add("searchPath", path);
        }
    }
}

Obviously you'd need to change the "SiteSearchIndexer" part to the name of your indexer to get it to work! You'll also need to make sure that the path is included in your index (look at the default indexes in your Examine config files for an example of this).

Now all we need to do is make our Examine search look for the root id in the "searchPath" field. Here's the finished code where we get the root node, and use it in an example Examine search:

//do search
var searcher = ExamineManager.Instance.SearchProviderCollection["SiteSearchSearcher"];

var criteria = searcher.CreateSearchCriteria(UmbracoExamine.IndexTypes.Content);

Examine.SearchCriteria.IBooleanOperation filter = null;

//search on main fields
filter = criteria.GroupedOr(new string[] { "pageHeading", "pageContent", "navigationText" }, Search);

//only show results in the current path
var currentPage = umbraco.NodeFactory.Node.GetCurrent();
string parentId = currentPage.Path.Split(',')[1];

filter.And().Field("searchPath", parentId);

//don't show hidden pages
filter
    .Not()
    .Field("umbracoNaviHide", "1");

var resultsTemp = searcher.Search(filter.Compile());

And now your search should only return results for pages in the current site, not pages from ALL of the sites! Nice and easy to do, and a good example of how easy it is to extend Umbraco with its event model!

You can also use this technique to search a specific area of the site, e.g. have a dropdown to filter the search by the News area, or Events area. You could also have a single index for multiple sites, allowing for a search that spaned all the sites as well.

Version 2.0.3 of AutoFolders Released

Those of you that have been using Umbraco a while are probably familiar with the excellentAutoFolders package, that allows you to have your content automatically sorted into date folders and alpha folders. The version that was up on the site until this morning was only compatible with the old schema.

A while back I persuaded the project owner Chris to let me contribute to the project so that I could update it to use the new schema and make it compatible with 4.5+.

I did that a while ago and we've been running it on a few sites for a few months now without issues so I've finally released it back into the wild for everyone else to use.

In addition to updating the code to work with the new schema, I also tweaked a few other things:

The content tree updates to reflect moves - the content tree on the left reloads to show the correct position of the content once it's been moved.

Problems with XML cache - there were a few minor issues introduced by some of the changes in 4.5 that caused the XML cache not to be correctly updated, these have been fixed.

Super exciting new folder provider - courtesy of Andrew Brigham, we now have a third default provider, the PropertyFolder provider. This allows you to specify a property of a document type, and have AutoFolders create folder structure based on that property. Say for example you have houses with a dropdown called "area", you can set the provider to group by the area property creating a site structure of /area/house. Example code is included in the config file that ships with 2.0.3!

The new version will ONLY work with the new schema, if you want to use AutoFolders on older sites, use version 2.0.2 instead! The DLL is built for .Net 3.5 so it should work on sites that aren't running 4.7 as well (we've tested it on 4.5, 4.5.2, 4.7 and 4.7.1).

I hope you guys like the update and that it allows you to use this excellent package on your newer sites!

:)

Head on over to Our and grab yourself a copy now!

 

Tips For Umbraco Developers

I've been working with Umbraco for a while now, and I've done a fair bit of work that's involved creating some quite complex extensions for the Umbraco back office, from DataTypes, through to whole new sections.

I've learnt a lot as I've gone along, and thought I'd share some of the tips for writing extensions for Umbraco! Hopefully some of these will help others avoid some of the mistakes I've made, or save them hours of research.

1. Don't Customize the Core Unless You Have To

Only modify the core if you absolutely have to. Early on I extended Umbraco by modifying the core code itself rather than using the event models etc. This was great, until I had to perform an upgrade. At which point I had to re-apply my updates to the new source, rebuild and re-test. Ouch.

Using the event models and the API, you can code extensions that are easy to re-use and that should carry on working, even after an Umbraco upgrade!

2. When Coding Datatypes, Don't Rely on the HttpContext

DataTypes can be called by events that don't have an HttpContext, like the timed publisher. In these cases they'll throw a null reference error, as the HttpContext is not available. Use non context versions of functions wherever possible!

3. When Coding Publish Event Handlers, Don't Rely on the HttpContext

Publish events can occur outside of the HttpContext. If your publish event handler relies on the HttpContext, it will fail when you try and use the timed publish feature of Umbraco. The biggest culprit I've seen for this is using HttpContext.Current.Server.MapPath, which will be null when called through the timed publisher.

You can map the path using HostingEnvironment.MapPath instead. For other code that relies on HttpContext, put in null checks and default values in case there is no HttpContext, and your handlers should work on normal and timed publish!

4. When Creating New CMS Pages, Inherit From UmbracoEnsuredPage

If you're creating new pages for the back office, you want to make sure that those pages are only visisble to users who have logged in through the CMS. The easiest way to do this, is to make sure that your pages inherit from umbraco.BasePages.UmbracoEnsuredPage instead of the usual System.Web.UI.Page.

This will make your page unavailable to non-logged in users, and will also enable you to hook into your page using the Umbraco event model!

5. Don't Be Afraid To Grub Through Code

One of the biggest ways I learnt was to grub through other people's code. Want to make CMS pages that look like the Umbraco ones, but not sure how to do it? Easy, grabthe source from codeplex and have a look at how it's done! Want to know how your favourite uComponents DataType works? Go look at the source and find out. The more you look, the more you'll learn about how the core works, and the ways that you can interact with it.

Hopefully (time permitting) I'm going to start a series of step by step tutorials on how to do some common stuff with the Umbraco Event models and API, concentrating particularly on the back office! Some of the things I'm hoping to cover are creating back office pages, using Umbraco UI elements, working with DataTypes, and using the event model to interact with the back office!