After going through the code on a recent project, I came across a lot of boiler-plate code. The site was built in web forms and used dynamic model binding directly in code that looked like this:
Personally, I think there is a lot wrong with this line of code:
Not strongly-typed As I work with a number of different platforms, I will always highly recommend using strongly-typed model binding for a host of reasons. In Umbraco, you have several options, the strongest being GlassMapper or uSiteBuilder. If, like me, you find yourself working on a legacy system and you can't easily switch from dynamic model binding to a strongly-typed system, then it's not a good idea to write code that won't work
Not Testable As the code is using a static helper, the class cannot be unit tested
Not Flexible For Upgrades This was the main reason I started to look at this code. After an upgrade from 6.1.2, to 7.5, the site started to blow up. Having code in this manner really tightly couples your code with your Umbraco instance.
If Umbraco introduces a new better API, you have to go through your whole project to update it. On the other hand, if you wrap all your calls up into a string method that returns a string. If the API updates, you can change one method and the whole of your website will update. This benefit alone can save months of development and refactor down the line.
No Null Checks
I'm hoping my arguments have convinced you that wrapping up all calls to GetProperty() is beneficial to your codebase. If you are still a little unsure about how to implement this type of change, I'll walk you through it.
Writing Safe Code
The problem with the code in the example above is that if node.GetProperty("contentTitle")is empty PropertyValue() will throw an object reference exception. My personal preference when dealing with content is a fail slow approach, if a few bits of content on a page don't kill the whole page.
Instead, render as much of it as possible and log/alert over email, or, log files that your site needs some configuration. To do this, a much better approach is to write defensive code that will do the null checks for you, this code would look something like this:
You can get a property from Umbraco like this:
Just adding a simple static class that wraps up your dynamic Umbraco calls gives you a lot more flexibility compared to directly accessing the Umbraco API. Now you can pass in any node and a string and know that your web page won't blow-up if a property doesn't exist.
If you wanted to build on this further, instead of returning 'null' you could do some additional logging, or, email so you can have visibility of the problem. Over the years I've found emailing an error to the team is better than writing to a log file. When errors get written to log files they seem to get forgotten about.
We have stage one of a solution, but our code still isn't testable, which is sad. If you want to have a super flexible testable solution, I wouldn't create a static class, you should inject the helper method into your class from the constructor (or maybe a property with web forms).
To change the code about to be more testable, remove the static references and add an interface to the class. I won't cover IoC in this tutorial as it's too big a subject. The theory is on application start-up, you register an IoC container like StructureMap, or, SimpleInjector.
Whenever a class is loaded with a property, the Ioc container will check if a mapping has been registered and if it has injected it. Ioc Is pretty simple but it can be a bit daunting for a beginner. The code would now look like this:
With the interface looking like this:
You would then inject the interface through your codes constructor and call the helper as follows:
The aim of this guide is to try and help people new to Umbraco learn the best ways to architect your project so that updating and maintaining it throughout its lifetime isn't a complete nightmare. By taking the time and wrapping up some Umbraco calls you will de-couple a lot of your system, making it more flexible and testable.