When running unit tests over "complex" data ie. a html, xml or json-file it's sometimes good to keep this data in it's own file and not in the C# code like this:

The example above is from one of our utility projects for Umbraco where we're parsing the grid to remove any empty p-tags from the end of a Rich Text Editor. To really know that this works and also keeps working we've created unit tests for different kinds of grid input.

 

First of, we need to include the files in the project and then set there "Build Action" to "Embedded Resource", right click on the file and choose "Properties" to se this options pane:

 

After this we can read the content of the files like this:

var content = new AssemblyTestData<MyUnitTestClass>(".Files.").ReadString("test-data.json");

Here's the code for the AssemblyTestData-class:

// <summary>
/// Utility to read content of embedded assembly resources
/// </summary>
/// <typeparam name="T">The calling type, used to get the resource namespace</typeparam>
public class AssemblyTestData<T>
{
    private readonly string _additionalNameSpace;

    /// <summary>
    /// 
    /// </summary>
    /// <param name="additionalNameSpace">If the files to read is in another namespace than the calling class, add this here ie ".Files</param>
    public AssemblyTestData(string additionalNameSpace = "")
    {
        _additionalNameSpace = additionalNameSpace;
    }

    public string ReadString(string filename)
    {
        var bytes = ReadBytes(filename);
        
        return Encoding.UTF8.GetString(bytes)
            .Trim(new char[]{'\uFEFF','\u200B'}); // Removes boom-chars

    }

    public byte[] ReadBytes(string filename)
    {
        var type = typeof(T);
        var assembly = type.Assembly;
        var stream = assembly.GetManifestResourceStream(type.Namespace + _additionalNameSpace + filename);

        using (var memoryStream = new MemoryStream())
        {
            stream.CopyTo(memoryStream);
            return memoryStream.ToArray();
        }
    }
}

Happy testing!

 

Umbraco CMS ships with the great MiniProfiler both with Umbraco 7 and 8.

I'm not going to repeat everything from the documentation but today when I wanted to see some profiling for a backoffice API-controller I'm working on I found that it's really easy to show the profiler logs by going to 

 

https://mysite.com/mini-profiler-resources/results-index

I recently played around with Microsoft's new "Windows Terminal", a great new tool for working with different command line tools in Windows.

I use the following setup:

 

My default setup for the Windows Terminal-settings looks like this:

"defaults":
{
    
    // Put settings here that you want to apply to all profiles.
    "colorScheme": "One Half Dark", //"Tango Dark",
    "fontFace": "Cascadia Code PL",

    "useAcrylic" : true,
    "acrylicOpacity" : 0.9,

    "startingDirectory": "." //add this

},

 

 Also if you want the git-bash as one of the options on the dropdown for shells, just add this to the "list"-property in the Windows Terminal-settings:

 {
    "guid" : "{14ad203f-52cc-4110-90d6-d96e0f41b64d}",
    "name" : "Git Bash",
    "historySize" : 9001,
    "commandline" : "C:/Program Files/Git/usr/bin/bash.exe --login",
    "icon" : "C:/Program Files/Git/mingw32/share/git/git-for-windows.ico",
    
    "useAcrylic" : true,
    "acrylicOpacity" : 0.9,
    
    "padding" : "0, 0, 0, 0",
    "snapOnInput" : true

}

Note: The path to git might be different, sometimes something like c:/program files (x86)/

 

I've found myself thinking a lot about a good naming strategy or naming convention for website projects that works with data in several different formats. Before I start to outline my current ideas (might change over time) I would like to set the stage for the project.

Let's say we have a website project with the all of these "features":

  • A rich domain model with domain entities
  • A database to store state of the domain model including repositories
  • A MVC front end
  • A web api aimed for the front end website (not 3rd party integrations)
  • A public web api for 3rd party integration's

Now comes the challenge, all of these different touch points/end points into the system often needs to represent the same thing/entity. We've been taught that for one should not use the domain entity as view model in a MVC-view, we should have a dedicated type that acts as the view model, the problem is that each of these end points probably needs a dedicated type which presents us with a problem that I've had a really hard time to find a perfect solution for:

How should we name all these dedicated types/classes?

First of all, these special representations of the core rich domain model entities are all DTOs (data transfer objects) but since we probably need these DTOs to look different depending on the context we need to name them in a smart and understandable way. The goal would be that a developer should be able to understand what "type of DTO" the code is working with by looking at the type name.

So let's start with some ideas and let's say that the core domain model that we're working here is type called Car.

MVC-view model

This one is quite simple, a very common practice is to suffix the core entity with ViewModel.

Idea: CarViewModel.

Database mapping DTO

In most of my solutions I use a repository that will take in the domain model and store it's state, the repository also returns instances of domain entities. During this process we need to map the domain entity to a model that is suitable for the storage we're using. Let's say a database. So most of the time I would represent the database table as a DTO.

Idea: CarDto

Model for website frontend APIs

Here we're talking about features on the website that make async javascript requests to the backend, something like a filter, a search feature, auto suggest or what ever. These are "ApiModel" but they are used in a context where they've probably will end up as some kind of "view model" when they are rendered into the website. I'm quite sure that this kind of model is different from the model used in public APIs for 3rd parties, so I would like to use a naming convention for them that makes it clear that they are used only for the website.

Idea: CarFrontendModel

Model for public API for 3rd parties

Here we're talking about model types for a external public web api if we're implementing a API that is restful these models could be called a Resource or a ApiModel. I like the idea of calling the "Resource" since a restful api could/shuld have navigation-properties etc. So in this case the "CarResource" might have links to a BrandResource or a "DealerResource". I'm very hesitant about this one but one has to come up with something.

Idea: CarResource


I had two main purposes of writing this blog post, first one is to document and share my ideas and the second is to get input and/or feedback. If you feel that you have other thoughts around this, please share in the comments! 

Note: I might (and almost hope) that I'll change my conclusions above based on more experience and feedback.

 

 

When working with Umbraco Forms there are some scenarios when you want to extend the functionality to perform something custom. Every time a Form is submitted a new Record is created for this Form, this Record is stored in the database and also passed to all Workflows that are configured on the form.

In our case we wanted to implement a HoneyPot to avoid some of the SPAM that comes through the forms so in cases we wanted to be able to remove a record from a custom WorkflowType. I found some solutions for Umbraco 7 but non of these worked on Umbraco 8 so I got my hands dirty and started to implement this. 

I did not find a way to remove the Record from within the Workflows Execute()-method since everything I tried caused exceptions. I managed to solve it by firing of a Task that runs some time after the Record has been created. 

Here's the code that we used:

public class DeleteWorkflow : WorkflowType
{
    public DeleteWorkflow()
    {
        this.Id = new Guid("466BAB6D-ECF1-4BE8-B0E7-6C6ACC495565");
        this.Name = "Delete Record";
        this.Description = "Deletes the record from the Database";
        this.Icon = "icon-delete";
    }
    

    public override WorkflowExecutionStatus Execute(Record record, RecordEventArgs e)
    {
        Task.Run(() => DeleteRecordWithDelay(record.UniqueId.ToString(),record.Form.ToString()));

        return WorkflowExecutionStatus.Completed;
    }


    public override List<Exception> ValidateSettings()
    {
        return new List<Exception>();
    }

    
    public static async Task DeleteRecordWithDelay(string recordId,string formId)
    {
        await Task.Delay(5000);

        try
        {
        
            IRecordService recordService = DependencyResolver.Current.GetService<IRecordService>();
            IRecordStorage recordStorage = DependencyResolver.Current.GetService<IRecordStorage>();
            IFormService formService = DependencyResolver.Current.GetService<IFormService>();
        
            var form = formService.GetForm(Guid.Parse(formId));
            var record = recordStorage.GetRecordByUniqueId(Guid.Parse(recordId), form);
        

            recordService.Delete(record, form);
        }
        catch (Exception e)
        {

            var exception = e.Message;
            throw;
        }
    }
}

When you want to combine and minify your JavaScript and CSS there’s a lot of options out there. Mainly you can either do this in your build process or perform this “on demand” from the server side of your website. When it comes to performance the first option, to actually deploy the processed assets, is probably the most efficient but I often prefer to take the cost of processing this on the server side using something like Microsoft.AspNet.Web.Optimization or ClientDependency Framwork (ships with Umbraco).

In this post I’ll explain the steps needed to use Microsofts Web.Optimization-framework and the 3rd party package System.Web.Optimization.Less to be able to process use .less-files on the server.

Note: The Less-package that I’m using needs at least .NET Framework 4.6.1 to run, so before going further, make sure that you’re project runs on at least .NET Framework 4.6.1.

First of, we need to install the two packages that we’re going to use:

Install-Package Microsoft.AspNet.Web.Optimization
and

Install-Package System.Web.Optimization.Less


Note: If you're on Umbraco 7 you need to make sure that you're using the right versions of the packages, I would recommend installtion them in this order:

* Install-Package Microsoft.AspNet.Web.Optimization -version 1.1.3
* Install-Package dotless -version 1.5.2
* Install-Package System.Web.Optimization.Less -version 1.3.4

This is beacure the "dotless" package made breaking changes in version 1.6+ but some NuGet package does not explicity state the dependency to be for dotless < 1.6.

After installing these packages we need to configure our bundle during startup. For a vanilla MVC-project this would be done in Global.asax but when we're running Umbraco we can avoid having to fiddle with Global.asax by creating our own ApplicationEventHandler (for V7) or UserComponent (for V8).

Before we configure our bundles we need to make sure that the path we're using for our bundles is ignored by Umbraco, otherwise we might get issues with 404-responses from the bundle. Make sure the root web.config contains a appSettings that looks something like this: 

<add key="umbracoReservedPaths" value="~/umbraco,~/install/,~/bundles/"/>

 Then we can start to configure our bundle, when running Umbraco 7 it would look something like this

public class UmbracoStartup : ApplicationEventHandler
{
    protected override void ApplicationStarted(UmbracoApplicationBase umbracoApplication, ApplicationContext applicationContext)
    {
        this.RegisterBundles(BundleTable.Bundles);
    }

    public void RegisterBundles(BundleCollection bundles)
    {
        bundles.Add(new ScriptBundle("~/bundles/js") 
            .Include("~/Scripts/site.js")
        );

        bundles.Add(new LessBundle("~/bundles/css")
            .Include("~/Style/site.less")
        );
    }
}

 Then in your views you'll render the bundle links like this:

@Styles.Render("~/bundles/css")

After this the bundle will be rendered on the front end of the website, please note that it behaves differently depending on the system.web -> compilation -> debug setting in the root web.config:

  • Debug = true (for development): Each file in the bundle is referenced with it's own <script>-tag
  • Debug = false (for production): Files and bundles (and minified if configured).

A good practice is to test both these settings in your development environment to make sure that everything works.

A very nice feature in the latest version of Umbraco (8.0+) is that they’ve made it really easy to implement your own CollectionBuilders. This raises two obvious questions:

What is a CollectionBuilder?

A collection builder is used to create a collection of Types, the main purpose being a collection of types that you would like to keep in a certain order. Umbraco uses this to register stuff like ContentFinders, Components and lots of other things.
The syntax looks something like this:

// Append
composition.Components().Append<MyCustomComponent>()
// Insert After
composition.Components().InsertAfter<MyCustomComponent,AnotherComponent>()

By leverage this feature you can create your own collection of types and make sure that the concrete instances in the collection is sorted in the way you want.

How would I implement a custom CollectionBuilder?

We’re basically looking at 3 small pieces that we need to get this in place. Let’s say that we have a type called ITextProcessor with multiple different implementations that we need to store in our custom collection in a given order. We’ll start with the collection it self by creating a new class that inherits from BuilderCollectionBase, all we need to do is to pass the type we want to store in the collection as a type parameter and implement the default constructor: 

public class TextProcessorsCollection : BuilderCollectionBase<ITextProcessor>
{
    public TextProcessorsCollection (IEnumerable< ITextProcessor > items) : base(items)
    {
    }
}

 Next up is the “Collection Builder” it self, here we inherit from “OrderedCollectionBuilderBase” and pass 3 type parameters:
1. The builder type it self
2. The collection type
3. The type of the items in the collection


And also implement one single property, “This”. It should look something like:

public class TextProcessorsCollectionBuilder :
OrderedCollectionBuilderBase< TextProcessorsCollectionBuilder, TextProcessorsCollection,ITextProcessor>
{
    protected override TextProcessorsCollectionBuilder This => this;
}

 The last thing we should do is to implement an extension method so the builder will be easy to use during composition, let’s create one like this:

public static class TextProcessorsCollectionExtensions
{
    public static TextProcessorsCollectionBuilder TextProcessors(this Composition composition)
=> composition.WithCollectionBuilder< TextProcessorsCollectionBuilder >();
}

After this we can work with our list during Composition using the extension method like so:

public class MySiteComposer : IUserComposer
{
    public void Compose(Composition composition)
    {
    composition.TextProcessors().Append<RemoveSpaceTextProcessor>();
    composition.TextProcessors().Append<AddLineBreaksTextProcessor>();
    }
}

 When we want to use the list in our code, we can get it from the IOC-container, prefferebly using consrtructor injection

public class MyController : SurfaceController
{
    public void MyController(TextProcessorsCollection textProcessors)
    {
        // Save as local variable
    }
}

Here's a summery of major features and improvements with each major/minor release of Umbraco CMS, you can see this as an overview of the great detailed release information that Umbraco HQ provides with each release.

 

Umbraco 7.0

Released: 2013-11-21

A major release that introduced the new AngularJS-based backoffice, new "property editors" for data types and a lot of improvements in the editor experience.

Release details on our

 

Umbraco 7.1

Released: 2014-04-03

This release was mainly a "polish"-release that fixed bugs and brought features that did not make it into 7.0.

  • Image Cropper in the core
  • Breadcrumbs and warnings (discard changed-dialog when leaving a view without saving)
  • Change document type
  • API: MemberService introduced.

Release details on our

 

Umbraco 7.2

Released: 2014-12-04

  • Grid property editor was added
  • Responsive preview mode (switch between desktop, mobile and tablet)

Release details on our

 

Umbraco 7.3

Released: 2015-09-29

  • Improved load balancing
  • Upgrade to MVC5 & WebApi2

Release details on our

 

Umbraco 7.4

Released: 2016-02-11

  • New Content Type (Document Type) editor
  • Models Builder

Release details on our

 

Umbraco 7.5

Released: 2014-08-17

  • Health Check dashboard introduced
  • 301 redirect manager
  • Image Processor security improvements
  • Password recovery for backoffice
  • Package Installer UI updated and "target version" for packages.
  • Sortable property types in list views

Release details on our

 

Umbraco 7.6

Released: 2017-05-02

  • New editor for scripts and templates
  • Content/media/members-pickers (property editors) was improved
  • Color-changes to backoffice UI
  • List View Pickers
  • UDIs was introduced

Release details on our

 

Umbraco 7.7

Released: 2017-09-19

This release introduced the new "User Management" and also changed some of the details around how users and passwords are stored. This version is "milestone" when upgrading old sites, I've had to install this specific version to the things right.

  • New User Management, more focus on settings on User Groups
    • Invite Users
    • Multiple Start Nodes
    • Big UI-improvements
  • Introduced "Content Templates"
  • New starterkit
  • Scheduled Health Checks
  • Includes Nested Content in the core
  • ISerachableTree-interface for custom search in the tree

Release details on our

 

Umbraco 7.8

Released: 2018-02-06

  • Backoffice Tours introduced (Step-by-step introductions/support)
  • The "Info"-tab replaced the "Generic Properties"-tab
  • Improvements to Load Balancing

Release details on our

 

Umbraco 7.9

Released: 2018-02-27

This released was called the "GDPR-release" and introduced some tooling around "consent" from visitors.

  • The ConsentService API was introduced
  • Logging of User actions in the backoffice was improved
  • Member properties can be marked as "Sensitive Data" and hidden from some backoffice User Groups.
  • Export Member data to a file

Release details on our

 

Umbraco 7.10

Released: 2018-03-27

This release does not contains a lots of features and was probably release to be able to ship the breaking change with TypedContent and Guids.

  • Improved performance for querying UmbracoHelper.TypedContent with Guids
  • Dropdown property editor was improved

Release details on our

 

Umbraco 7.11

Released: 2018-06-19

  • See where Composition Content Types are being used
  • Dictionary Tree modernized (aka moved from WebForms to AngularJS)
  • Multilingual tours
  • Cancel-events from ContentService-event handlers now shown to the user.

Release details on our

 

Umbraco 7.12

Released: 2018-08-14

  • Folders for Content Types (aka Document Types)
  • Nested Content filtering content types
  • Visual Color Picker for content type colors

Release details on our

 

Umbraco 7.13

Released: 2019-01-08

The "Community-release" with 172 improvements, bug fixes and so on.

  • SVG-support for media / media pickers
  • Better image search
  • Media item deletion detection (the "Trashed"-alert on media that has been deleted)
  • Media file type indicators (icons for doc,pdf etc)
  • Performance improvements, site-startup
  • UX: Color pickers improvements

Release details on our

 

Umbraco 7.14

Released: 2019-03-12

  • Multi Url Picker added to Core
  • Helth Check for TLS 1.2
  • UX-improvements to Image Cropper, SVG, Toggles and more

 

Release details on our

 

Umbraco 7.15

Released: 2019-07-09

The final Umbraco version 7 minor release. NOTE! This version was patched with 7.15.1 due to a bug in the media tree.

  • .NET Framework update to 4.5.2
  • New Preview engine
  • Updates to EntityService (breaking)
  • Pickers: "Ignore User Start Nodes"-setting
  • Bugfixes for CPU usage when not running the backoffice on the /umbraco-route

 

Release details on our

 

Umbraco 8.0

Released: 2019-02-26

A new major-version of Umbraco with lot's of updates and breaking changes. A cleaned up code base where all legacy code (aka WebForms) has been removed.

  • New backoffice UI
  • Introduced "Infinite Editing" - edit doctypes, media and content in a "modal" and not switch context.
  • Language Variants - Native support for 1:1-translations in the core
  • Removed all dynamics, UmbracoTemplatePage etc
  • Introduced "NuCache", no more XML (umbraco.config)
  • Introduced Composition and Components for startup and Dependency Injection

 

Release details on our

 

Umbraco 8.1

Released: 2019-07-09

  • Improved editor experiance
  • Nested Content - Copy & Paste
  • Easier access to MiniProfiler by a Settings-dashboard switch.
  • Ignore User Start Nodes
  • Accessibility improvements
  • Models Builder updates
  • Introduces IPublishedPropertyType, breaking change for PropertyValueConverters

 

Release details on our

 

Umbraco 8.2

Released: 2019-10-15

A total of 91 features and fixes in this release.

 

  • Rich Text Editor enhancements
    • Performance / loading time improved
    • Drag and drop images
    • Copy/paste from Word improved
  • Improved cache performance and stability

 

Release details on our

Umbraco 8.3

Released: 2019-11-12

A small minor release with a major feature added.

 

  • Allowing to change the culture of a language (ie. dialects English UK to English US) 
  • Disable renaming for built in User Groups

 

Release details on our

 

Umbraco 8.4

Released: 2019-12-10

A maintenance-release with dataType-tracking added, improved backoffice search and around 180 community contributions.

 

  • Fixes issue with outdates results from Content Service
  • Fixes redirects for moved content nodes
  • Allow to search by Content Guid

 

Release details on our

 

Umbraco 8.5

Released: 2020-01-14

The "Models Builder" in Core-release, note that there was some fast bug fix-releases after this was release.

 

  • Added a slime down version of Models Builder in the the Umbraco Core, used to be an external package.

 

Release details on our

 

Umbraco 8.6

Released: 2020-03-31

Contains a lot of accessibility fixes and also bug and stability fixes and also:

  • Custom validation messages for Content Types
  • Media Tracking (shows where media is used)

 

Release details on our
Umbraco HQ-blog about the release

 

Umbraco 8.7

Released: 2020-09-10

The "Block List Editor"-release contains ie:

  • The new Block List Editor property editor
  • Segments-support at API-level
  • Content Apps for Document Types
  • Complex validation in property editors

Release details on our

Umbraco HQ-blog about the release

 

Umbraco 8.8

Released: 2020-10-01

Mainly the "Image Cropper in Grid" and "List view for media"-release. Includes:

  • Cropping-improvements to image control in the grid
  • List view's for media
  • Improved support for Guid and Udi-references to content/media
  • Icons as SVG
  • JSON-editor for gris style/settings-configuration

Release details on our

Umbraco HQ-blog about the release

 

Umbraco 8.9

Released: 2020-10-26

The "OAuth"-release that expands extensibility points for 3rd party login providers ie. Open Id Connect.

  • Extensibility-points to login using Open Id Connect ie. Facebook or Azure Active Directory

Release details on our

Umbraco HQ-blog about the release

 

Umbraco 8.10

Released: 2020-12-28

A "maintenance"-release that includes many contributions from the "Hacktoberfest 2020".

  • Updates to Block List Editor
  • Popups when entering preview mode in new browser tab
  • Property editor "full width" editor
  • Checkbox-list-editor for grid settings
  • Faster content query and reduced memory consumption

Release details on our

Umbraco HQ-blog about the release

 

Umbraco 8.11

Released: 2021-01-28

A "maintenance"-release UX and accessibility

  • Unattended installs
  • "Remove all"-option for Multi Node Tree Picker

Release details on our

Umbraco HQ-blog about the release

 

This blog post came out of my work with packages for Umbraco CMS, but it's totally applicable even if you're not working with Umbraco. When building packages for Umbraco that works with custom tables you have to keep in mind that CMS supports different databases. We need to make sure that our queries works on both the standard SQL Server and with SQLCE.

I've decided to try to create a list of queries and map out what does and what doesn't work depending on the database type.

 

Description

Query-example

SQL Serv.

SQLCE

Regular SELECT

SELECT * FROM umbracoNode

x

x

SELECT with Subquery in select-statement

SELECT id
(SELECT COUNT(pk) from cmsDataType) as Test
FROM umbracoNode

x

 

SELECT with Subquery in WHERE-statement

SELECT id, [text]
FROM umbracoNode
WHERE Id IN (SELECT nodeId from cmsDataType)

x

x

SELECT with Subquery (scalar1) in WHERE

SELECT id, [text]
FROM umbracoNode
WHERE Id = (SELECT TOP 1 nodeId from cmsDataType)

x

 

SELECT with Inner Join

SELECT n.id, n.[text]
FROM umbracoNode n
INNER JOIN cmsDataType d ON d.nodeId = n.id

x

x

SELECT with STUFF-function

SELECT id,[text], STUFF([text],1,1, '')
FROM umbracoNode

x

x

SELECT TOP 

SELECT TOP 5 * FROM cmsContentType

x

x

SELECT with “FOR XML PATH”.
Will format as a scalar XML-payload

SELECT TOP 10 id,[text]
FROM umbracoNode
ORDER By [text]
FOR XML Path('node')

x

 

Row_Number() / Paging with
SELECT with ROW_NUMBER()

SELECT id,[text],
ROW_NUMBER() OVER (ORDER BY [text]) AS RowNumber
FROM umbracoNode
ORDER By [text]

x

 

Paging with
SELECT WITH OFFSET AND FETCH 2

SELECT id,[text]
FROM umbracoNode
ORDER BY id
OFFSET 0 ROWS
FETCH NEXT 10 ROWS ONLY

x

x

SELECT DISTINCT-feature

SELECT DISTINCT ContentId from cmsContentVersion ORDER BY ContentId

x

x

SELECT COUNT with DISTINCT3

SELECT COUNT(DISTINCT thumbnail) FROM cmsContentType

x

 

SELECT with LIKE in Where

SELECT *
FROM umbracoNode WHERE [text] LIKE '%st%'

x

x

SELECT with Subquery in FROM-statement.

SELECT count(contentId)
FROM (SELECT DISTINCT contentId FROM cmsContentVersion) cmsContentVersion

x

x

SELECT with LEFT OUTER JOIN

SELECT n.id, n.[text], d.dbType, d.pk FROM umbracoNode as n
LEFT OUTER JOIN cmsDataType as d ON n.id = d.nodeId

x

x

Parameter Alias declared as string

SELECT id as 'foo' FROM bar

x

 

Parameter Alias declared inline

SELECT id as foo FROM bar

X

X

SELECT with INNER JOIN Subquery in FROM

SELECT * FROM cmsTemplate as t
INNER JOIN (SELECT templateId, count(id) as total
FROM umbracoDocumentVersion WHERE published = 1
GROUP by templateId) as dv ON dv.templateId = t.nodeId

X

X

CROSS APPLY

SELECT id,userName,ugr.Roles FROM umbracoUser u
CROSS APPLY (SELECT COUNT(ug.userId) as Roles FROM umbracoUser2UserGroup AS ug WHERE ug.userId = u.id) as ugr
ORDER BY ugr.Roles DESC

X

X

 

1. A scalar query is a query that returns one row consisting of one column.
2. Works on SQL Server 2012+, older versions need the ROW_NUMBER()
3. Another version of the query with a join in the FROM-caluse works on SQL CE: SELECT COUNT(thumbs.total) as Total FROM (SELECT DISTINCT thumbnail as total FROM cmsContentType) as thumbs

I hope that this little table is useful and please, feel free to drop a comment if you have any feedback or suggestions on things I've missed.

 

 

The yearly Umbraco festival in Sweden was hosted today in Gothenburg and I was one of the speakers. My subject was “The first Umbraco V8-site” and I tried to share some of my learnings from trying to implement a new site with the current “version” of Umbraco v8.

Presentation Usf 2018

 

You can download the slides here