Trying Sitefinity
I’ve been on some Sitefinity training this week, I’ve only got Umbraco to contrast it with. Here are some thoughts!
Umbraco doesn’t come out of the box with any concepts, whereas Sitefinity has Pages, Comments, Blogs, etc. built in. That could be positive or negative. These features are all ‘Modules’ and you could spend as long switching them all off as you would creating just the DocTypes you need in Umbraco.
SF has a strong emphasis on convention-over-configuration which generally serves it quite well. As long as you know the secret file paths to override something, you can change anything.
Sitefinity custom components can be written with MVC or Webforms but I’m not going to make any further mention of Webforms.
Module Builder
- Modules are managers for custom data types. There is a Module Builder which is just like Umbraco Document Type creation journey.
- You might call the resulting modules “Dynamic Modules” as their underlying types are user-defined, and on a technical note, the API to pull them out of Sitefinity is called the
DynamicModuleManager
- When you’ve built a custom data type with the Module builder, each entity could be referred to as a ‘Module Item’ or a ‘Content Item’ (as they all appear in the backend under a menu marked ‘Content’)
- Sitefinity creates a database table for your Module types, so they’re properly normalised, unlike in Umbraco where the definitions are crammed in some other table.
Overriding a Dynamic Module’s Detail and List views
When you build a custom module, it will display by default as though it’s some kind of blog post; a list view with title, comments, and publish data, and a detail view. I’m not sure this is so useful but it gets you started.
Firstly, in the widget editor, on ‘List settings’, notice the ‘List template’ dropdown. If there’s more than one option for a renderer, they’ll appear here.
I can override the renderer template in either the Mvc directory or nested under a ResourcePack:
- In
SitefinityWebApp/Mvc/Views
, make a directory with the singular name of your Module Item i.e. ‘Employee’ or ‘Question’ - Make files beginning with ‘Detail.’ and ‘List.’ - the second word will fill in the ‘List template’ dropdown we saw earlier. To override the default renderer, use the singular name of your Module Item again, i.e.
List.Question.cshtml
- Examples are on the feather widgets github repo
- Docs for creating widget templates… not super clear
You can also override back office editors and behaviours by writing AngularJS files - just like Umbraco. I won’t go into how it’s done. But it’s funny that both Umbraco and SF rebuilt their backends in AngularJS at the same time… now both have 14 months (at time of writing) until AJS reaches end of LTS!
Pulling Module Items out of the API
The DynamicModuleManager
is a little clunky. Your Module Items have whatever custom props you designed, and to query these with a Lambda, SF makes you write the expression as a string(!!) and then presumably it evaluates it with reflection somewhere in the deep.
@{
DynamicModuleManager dynamicModuleManager = DynamicModuleManager.GetManager();
Type questionType = TypeResolutionService.ResolveType("Telerik.Sitefinity.DynamicTypes.Model.Questions.Question");
var filteredQuestions = dynamicModuleManager
.GetDataItems(questionType)
.Where(q => q.Visible)
.Where("InterfaceKey = \"Applicant1DoB\"");
}
Above, Visible
is a built-in SF concept, whereas InterfaceKey
is a custom prop of my Question object. So you can’t mix these in one Where statement, which is also a pain point.
This feature is really done a lot better in Umbraco, where ModelBuilder re-generates strongly-typed models for each of your Doc Types on rebuild (or app start, depending on config… I think this is called PureLive or something). The upshot is that you can always query your objects like proper objects.
Come to think of it, you can tell from the code Telerik.Sitefinity.DynamicTypes.Model.Questions.Question
that SF generates a Type for me… so why can’t they query it with a real lambda?
There’s a Fluent API alternative to the Manager API above, but I’m told it doesn’t quite have feature parity.
Widgets
- A Widget is a custom control, backed by an MVC controller. A widget appears in the toolbox when you’re adding blocks to a page.
- The “Widget designer” is when you click Edit on a Widget that you’ve added to a page. Any public fields of the Controller appear as editable fields of the widget. This is pretty cool.
Ordering Module Items
SF has some clever built-in sorting and ordering for your module items. When you add a List to a page, you can specify the items and their ordering. Then, by magic, they are provided to your rendering component in the correct order so that you don’t have to do any sorting in your views. No ‘SortOrder’ property necessary. Sorting and ordering in Umb has always been a little painful, I don’t know if it’s quicker in 8.2+
- In the widget editor (editing the block on the page)
- Instead of choosing ‘All items’, choose ‘Selected Items’
- In the next modal, select the items you want, then go to the second tab (‘Selected n’) and drag to reorder
- When you’re done with that window, go to the ‘List settings’ tab
- Set ‘Sort questions’ to ‘As set manually’
Variants of Widget Views
I don’t know what to call this feature but it’s fairly neat.
- One controller can only present one toolbox item
- But, each view from the controller (e.g. ‘/Index’, ‘/Other’, ‘/Gold’) can be accessed by slash after any page that deploys that widget!
- This is more magic than it sounds
- All of your widgets could have a ‘/Gold’ variant, and when you go to ‘AnyPage/Gold’, all the widgets will load their ‘Gold’ version
- You need to hook them up in the Controller and by creating Views.
The Good, the Bad, and the samesies
Good things
- The drag-and-drop grid editor is more mature than Umbraco’s
- You get paging for free on all entities
- Convention over configuration
- Don’t need to add ‘Surface’ in your controller names
- Makes tables for custom entities! Umbraco lumps everything in generic denormalised tables
- Doesn’t log you out all the time like Umb (tho Umb is probably configurable)
- Sorting items in a list is easier than Umb
Bad things
- Pulling down the NuGet is more than 100MB… compare to Umb which is less than 10MB. Our trainer said to go and make a coffee because adding SF takes 10-15 mins… wow
- Feels big and slow.
- Concepts feel overly fragmented compared to Umbraco where everything is a DocumentType. Once you grok Umbraco DocumentTypes, you acheive Galaxy Brain and can do everything, but in Sitefinity, these are subdivided into Modules, Templates, Widgets, Content Items, Module Editors… feels complicated.
- The lambda filtering on custom entities is not as good as Umbraco, in that you have to write string predicates instead of real lambdas.
- On Module Items, you have to use
.GetValue()
to read properties, which sucks. - SF keeps media file binary content in the
sf_chunks
table. Probably a pain during migration (Umb keeps it in the file system) - It feels like there are more footguns in SF. Like Revision History is unlimited by default, and even when you configure it to be limited, the deletion is a scheduled job rather than on-write??
- It’s hard to find developer docs for Sitefinity. You also find with non-free tech that people keep their knowledge closer to their chest so there are fewer SO answers and blog posts.
Same things (as Umbraco 8+)
- The MVC override system is basically the same
- SurfaceControllers in Umbraco are basically the same as SF Controllers
- Previewing is unreliable in both
- Create -> Cancel -> Delete -> Refresh is unreliable in both
- If I’ve got unsaved CMS content and I edit the source code, both CMSs screw me up
- Migrating and synchronising code with data (and developer data with live data) is still a massive pain
- Feels like, if you’re going to pay a boatload of money, this is the one thing that should be fixed. It’s fixed in Umbraco Cloud, for example.
Remember the cost
All of this needs to be taken in the light that Umbraco is free-as-in-speech. A teenager in the loft can use, extend, modify, and redistribute it for free.
Sitefinity costs exactly “if you have to ask you can’t afford it” pounds. There is no public pricing. The only blog post I found discussed how U of I gets a fabulous grandfathered rate of merely $7000 annually, whereas newly licensing their estate would cost over $100,000. Ouch.
And there’s no great chasm separating their features! They are so similar as to be uncanny at times. So I don’t know really why you’d pay for Sitefinity.
Fundamentally, a non-free technology has zero hobbyist audience because I’m not going to pay to build my personal site on this. So nobody learns to love it.
Other links
Make an MVC widget: https://www.progress.com/documentation/sitefinity-cms/112/create-widgets-mvc
Dynamic Modules API (string lambdas): https://www.progress.com/documentation/sitefinity-cms/example-filter-dynamic-content-items-by-dynamic-field
DevMagazine sample site https://github.com/Sitefinity/AdvancedDevCert/tree/master/DevMagazineHtml
Wrap up
Thanks for stopping by! Hopefully this is useful if you’re trying to pick a CMS or get to grips with some Sitefinity concepts from an outside perspective…
Build culture, stay humble 🌿