Part of Umbraco’s amazing yearly CodeGarden festival is the Umbraco Awards; an afternoon dedicated to recognising the very best Umbraco solutions from around the world.
There are 4 categories that people can submit their work under, these are Best Technical Solution, Best Editorial Experience, Best Designed Site and the Umbraco Package Award.
In addition to these submission categories, there is the highly prestigious Jury’s Choice Award.
The Jury’s Choice Award is defined as follows, "…all submissions to the Umbraco Awards are automatically entered in this category, however, the jury can also choose projects that have not been submitted. The secret jury rewards the solution they think is best utilizing the full potential of Umbraco and thus, sets an example of just how much value can be squeezed out of Umbraco".
The jury in question were able to choose from not only all 120 Umbraco sites entered into the awards themselves but all the tens of thousands of other sites globally that weren’t even entered but were still known about. For those of us who were present at the awards ceremony, it was incredible to see the high quality of the work people we’re doing with Umbraco, as the nominees and winners were being presented one after another.
It was when they reached this Umbraco Jury’s Choice Award that we were hit with a wonderful surprise; we had been nominated in the top 3 for our work on the RunTogether website. In particular, the jury were impressed with the how we were able to bring a high degree of technical customisation and sophistication to the Umbraco platform, and deliver high quality design visuals and UX. You can view the nomination video at https://vimeo.com/221872305.
Some of the more advanced technical elements
of the website included:
1. Geospatial search
Geospatial search; we used a combination of in-browser geolocation support, Bings Maps API, Umbraco Examine, as well as raw Lucence.NET and the Lucene.NET Spatial library (part of the Lucene.Net.Contrib application library) to create a super fast, super performant (i.e. heavily cached) geospatial search provider to find local running groups and run routes based on a user’s location.
Seamless integration and Single Sign-On; with our partners at ClubSpark, the CRM providers, we integrated single sign-on into the Umbraco website seamlessly using the ASP.NET Identity Framework and a 3rd party IdentityServer, and created a unified look and feel for the end users as they traversed both the CRM web interface and the Umbraco website.
3. Free text site search
Multifaceted free text site search; we created a free text, keyword-based, faceted search page which searched across content held within both the Umbraco site and the CRM / booking engine application.
4. User-generated content
Cross platform user-generated content; we shared user preference data across both platforms seamlessly by using UmbracoApiControllers and employing custom authentication controller action filters based on an OAuth architecture of a shared authentication token, to secure the API calls programmatically. Similarly, we enabled users from within the CRM to be able to create / submit content into Umbraco directly for approval, prior to publishing (submitting their own suggested run route), using Umbraco’s awesome API and application services framework.
What we did
Looking closer at the geospatial search work we implemented...
First of all, we hooked into the OnApplicationStarted event of Umbraco’s IApplicationEventHandler in order to create and load into memory a cartesian plotter object which flattens 3-dimensional geospatial objects onto a 2-dimensional grid which can be stored in a Lucene index and logically searched across, relative to any given lat / long coordinate.
All content which we wanted to be returned as part of a geospatial search (content we called “geo-enabled”) was then added to this cartesian grid by hooking into the DocumentWriting event handler for the LuceneIndexer as it’s called during normal content management activities within Umbraco (i.e. each time the index is updated by Umbraco).
The search mechanism itself used the Lucene Spatial LatLongDistanceFilter and an appropriate bounding area based on how far we wanted to search out from the user’s position (e.g. 1 mile, 5 miles, 10 miles, away, etc.).
In order to get the user’s position if they didn’t use the built-in geolocation function of their browser, we also hooked into the Bing Maps API to provide simple and easy address lookup function as they entered their home town or city. Combined with a prefilled, heavily optimised, database of English addresses and known lat / long combinations (complete with SQL Server index catalogs), we ended up with a lightning fast, highly accurate, geospatial search mechanism, all within Umbraco.
As a final nice touch, we hooked into the Saved event handler of the ContentService such that if a content editor added a postcode address to a piece geo-enabled content, Umbraco would use the same address lookup provider we built above to auto-populate that content’s geo-coordinates and add it to the geospatial Lucene index automatically.
In this scenario, Umbraco did exactly what Umbraco does best - it acted as a framework to build highly bespoke .NET code on top of, providing hooks into the key events associated with content management and the application lifecycle.
Alongside the geospatial search work that was accomplished, we also made use of the UmbracoApiController, ContentService, ContentTypeService , DataTypeService, and MediaService to create a highly functional API that was used by the CRM application to allow users with an appropriate access level to create content on the Umbraco site.
Using a combination of the ContentTypeService and DataTypeService we were able to produce a model based on a specific DocumentType that could be used by the CRM to render a form containing the latest data from Umbraco. For example, one of the form options included a dropdown list of names that were matched to content nodes in Umbraco, which needed to be updated whenever they are changed on the Umbraco site.
Having parity between the generated model and DocumentType that was to be created made it creating and updating content via the ContentService a piece of cake.
The type of content that a CMS user could make also had the option to upload a GPX file that was used on the Umbraco site to render out a route on a map. After receiving the GPX data as raw XML we were able to generate a new GPX file on the file system and add it to the media library using the MediaService whilst also assigning it to the created node.
We also used the ContentService in order to display the page in a preview state (to display saved but not published data), without a user having to be logged into the Umbraco admin, instead using the authentication provided by the single sign-on framework.
If you would like to know more about this project or how Yoyo can help you get the most out of your own website, then please do get in touch.
Written by Mike Masey