Skip to main content


Showing posts from 2022

Handling Umbraco Events After Deploy Operations

I had a question from an partner Umbraco raised for me this week, that's available at this forum topic . They had some code running in a notification handler running when dictionary items were saved, and found this wasn't firing when the item was saved following an Umbraco Deploy operation. I responded that this is actually expected behaviour - as Deploy supresses events being fired on individual save and publish events when transferring items. This implementation decision was made I understand for performance reasons. In the back-office, the usual case for a save of an item is one-at-a-time, but with a deployment, there could be hundreds of updates within an operation. However, what if you do want to run some code on the save of some Umbraco data, even if this is happening as part of a Deploy operation? There's an option here using cache refresher notifications. Not all events are suppressed by Umbraco Deploy - some that are batched up and fired after the deploy o

What Content Broke My Restore?

Just something I want to keep track of... From a support issue with Umbraco Deploy on Umbraco 8, a customer was getting a failure when restoring, which stemmed from a JSON serialization failure when generating the Umbraco Deploy artifact. It was a bulk restore though, so tricky to figure out which content was causing the problem. And as this serialization is happening in the upstream environment being restored from, a local instance and debugging doesn't help. This hacky code dumped in a view was useful to find out:

Cache Busting Back-Office Client-Side Assets With Umbraco 9+

Since I started at Umbraco the link I've shared the most when helping with support issues has been a blog post article by Dennis Adofi titled "Bumping The Client Dependency Version" . It describes the method used to ensure caches are cleared for client-side assets in the back-office for Umbraco versions up to 8. There's a similar setting for Umbraco 9+ which I've recently had to look up a few times. The configuration setting is at: Umbraco : CMS : RuntimeMinification: Version and is set to a numeric value. It's documented here and, as described, uses a similar version number that can be increment manually or via a build process to ensure the same cache busting behaviour. When upgrading Umbraco to a new version of the CMS you don't need to worry about this, as the version running is already used in the hash that is generated for the cache key. But this doesn't take into account package installs, or your own custom extensions to the back-office.

A quick post on view model mapping

I had a question about options for mapping Umbraco content to view models come up today, and given my response in Slack was getting a bit long and I'm sure I'll need to refer to it again, decided to create a post instead. So what follows is a quick summary of the history and options for adopting a pattern of mapping Umbraco content to a strongly typed view model. It's not intended to be fully comprehensive... am just saving my keystrokes . Around the time of Umbraco 6 or 7, some colleagues and I from Zone released Umbraco Mapper , which used a combination of convention and configuration to allow for these mapping operations to be made in code. We used it in a fair few projects and liked the approach, and, judging from some feedback, a number of others from the Umbraco community did too. Just after, though likely in use or development concurrently, was Ditto released by Lee Kelleher and Matt Brailsford. This did a similar job, and it gained a fair bit of traction in

Using SQL Profiler To Identify Repeated SQL Calls

This week I've been looking into some optimisations for a long-running process that chats to the database. Within the operation, the data isn't expected to change, so it would be reasonable that, where we make repeated calls, we cache the values and re-use them for the duration of the operation. I've been using SQL Profiler to identify them and wanted to blog the method for reference. First, start up SQL Profiler and create a new trace. Connect to the database and define the Events Selection. I kept most things related to data reads and writes: I then ran the application, set a break-point in the code at the point where afterward I was interested in the results, and attached the debugger. On hitting the breakpoint, I started the trace and continued the code execution. When the operation was complete I could stop the trace. To analyse the data, I saved it to a new table in a database I created to store the results in, via File > Save As... > Trace Table

Customising the Umbraco Pipeline

The excuse for today's post is I need somewhere to write up some findings from an Umbraco support case I've been looking into. A customer was using an external library that provided middleware that needed to be configured between UseRouting() and UseEndpoints() . Which isn't a problem if you have full control over the contents of the StartUp.cs class, but it's not so easy when Umbraco is doing some of this setup for you. Thanks to Benjamin Carleski from the Umbraco community who figured this out and shared it in this forum conversation . Nothing is really different from his answer on setting up CORS, but in this post I can more easily and permanently share the sample code. Assuming we have a library that requires a typical "Add..." addition in the ConfigureServices method and "Use..." in the Configure method of Startup.cs . First we need a pipeline filter class: Then a class responsible for inserting this filter in the pipeline: An

Pushing Updates to a PR

This is unashamedly a "note to self" post... something I occasionally need to do, and always need to ask about or look-up. As a maintainer of an open-source project on GitHub, an incoming PR from a contributor's fork that needs some minor changes before merging can be dealt with by committing changes directly to the branch on the fork, if the contributor has allowed edits from maintainers . To checkout the branch locally: git fetch origin pull/[pr id]/head:[branch name] git checkout [branch name After making changes, to push them back to the branch on the fork: git remote add [remote name] addremote [fork url] git push [remote name] [branch name]

Getting Submitted Form Data in Umbraco Forms

With Umbraco Forms, you can configure a page to redirect the user to once a form has been submitted. A question came to me about how on that page we can get information about the form just submitted, as well as details of the record created from submission. I'll share the answer here for future reference. We can make use of a couple of TempData values that are set automatically by Umbraco Forms (documentation here ). UmbracoFormSubmitted - The Guid of the Form Forms_Current_Record_id - The Guid of the Record created from the form submission The following code example, valid for Umbraco 8, shows how this data can be retrieved. For illustration purposes, I've implemented it directly in the template for the page the user is presented with after the form is submitted. For production code, likely this would be better in the controller of a hijacked route .

Service Location in Umbraco 9

I should probably start this post with a caveat saying, "don't do this... unless you really, really have to!" With Umbraco 9, built on .NET 5, we have support for the dependency injection design pattern , and where possible, the recommedation is to use that, to promote testability and other best practices. Within the Umbraco CMS source code though, and also in the add-on products Forms and Deploy, we have found it necessary to use service location in a couple of instances. Primarily, to avoid breaking changes. For example, when a public class requires a new dependency, we don't just add it to the constructor as that would potentially break integrations that are already using it. Instead we obsolete the existing constructor, create a new one with the additional parameter, and have the original constructor delegate to the new one - using service location to provide the parameter for the added dependency. In code it looks like this: To use, you need to be ref