Using media picker in umbraco backend

I've seen many questions on this in the forums, and no good answer. It has even been reported as a bug, but closed. So... when I needed the functionality myself, I took a look at the umbraco sources and figured out what's wrong.

It may not be a bug, but it's definitely a weird quirk. The workaround is simple though. But let's begin at the beginning...

The Problem:

A media picker on a custom editor page doesn't show any value when the page loads, although there is a value and it is set during Page_Load or OnLoad. Or, in more detail:

  • You write a custom section with some kind of data editor that works against a custom database (i.e. doesn't use umbraco documents or other objects).
  • You want to let the user pick media items from umbraco and save their id:s in your database, so that you can render them in your usercontrol (or whatever you use to present the data in the frontend).
  • You read a HOWTO on this and pick a media picker (almost any - most seem to work the same way), for example the mediaChooser.
  • You test it, pick a media item and it works. It gets saved in the database.
  • You return to edit your data, but the media item is GONE. It (the ID) exists in your database, but not in your custom editor. You set it in Page_Load (as you would normally do with control values), and you've triple-checked that. Still doesn't work.

The Cause:

The mediaChooser (and - from what I have seen - most other media pickers as well) handles its value in an unexpected way. More detail:

The mediaChooser behaves like this (or actually the BaseTreePickerEditor, which mediaChooser inherits from - and I suspect most other media pickers do that as well):

  • In OnInit, if an IData object was presented by the constructor, its "Value" property is saved in a private variable. If IData is null, the value will be -1.
  • In OnLoad, the Value property of the control (which is defined by a base class) is overwritten by the value in the private variable.
  • In all the following stages, the Value property is used (as it would normally be).

This is a bit weird, as you usually create your controls in OnInit and populate them with data in OnLoad. There are other ways and other events that serve to make the process even more granular, but that is the most common pattern in examples and so on. The mediaChooser, on the other hand, assumes the data will be present in the extractor already upon initialization.

This may be an umbraco convention (I haven't looked at the source for other data editors), but in any case, it is unusual, and probably quite unexpected for most people.

The Workaround:

Set the value of the media picker in OnPreRender instead (or any other event that occurs after OnLoad but before rendering) of OnLoad or Page_Load. If the data is only available during OnLoad, stash it away in a private variable then, and stick it in yourPicker.Value during OnPreRender.

Works like a charm.

Oh, and one more thing:

You don't need a value extractor (an object of a class that implements the IData interface). Just pass null for that parameter of the mediaChooser constructor, and use the Value property instead. It should be "" when no media item is selected - otherwise, it should be the media ID as a string.

Further reading:

ASP.NET Page Life Cycle Overview (a must-read for all ASP.NET developers)

mediaChooser.cs source

BaseTreePickerEditor.cs source (inherited by mediaChooser)

BaseTreePicker.cs source (inherited by BaseTreePickerEditor)

Posted by Peter Josefson at 22:45

Post a comment