Admin (Backend) Themes

Topics: Core, Customizing Orchard
May 31, 2015 at 12:18 AM
I was updating my module for selecting admin themes and noticed the latest podcast in which a bootstrap based admin theme was demoed. Will you (The Orchard Team) be creating an admin area for admin themes similar to the themes module or just a new admin theme that comes built into orchard?

I decided to move my admin themes area inside the themes menu as a new tab but ran into a few problems along the way.
  1. How do I remove a menu item? The Navigation builder has a remove() method but I was running into problems getting it to work since it takes an actual MenuItem as a parameter. I would like to remove the "Installed" tab and create two tabs: one for site themes and one for admin themes. For the time being, since I'm doing this in a custom module, I've overridden the view for ThemeEntry so it doesn't show the buttons to activate or preview a theme and am using the Installed tab as a view for all themes that are installed.
  2. Is it possible to specify a controller as an admin controller without naming it "AdminController"? I had to split my module into two separate modules since I wanted to keep admin themes from being seen in the site themes tab without adding the "hidden" tag (so they can be viewed and selected for tenants) . I could have combined everything into one controller but it was getting messy. Thank you.
Jun 2, 2015 at 11:55 AM
For now the talk was mainly about a new admin theme but I think being able to easily select admin themes like frontend themes came up. However you still can write admin themes today.
  1. I did this before with the OrchardSuppressDependency attribute, by overriding the original navigation provider. If Remove() is not working as expected please file a bug.
  2. Alternatively you can add the Admin attribute to the controller, it will have the same effect.
Jun 2, 2015 at 6:48 PM
Thanks for the reply Piedone.

I'll play around and see what I can figure out.
Jun 2, 2015 at 8:47 PM
Edited Jun 2, 2015 at 8:48 PM
I got everything working except settings that are built into themes. For instance the PJS.Bootstrap theme has some theme settings built in as a site settings content part. For some reason my code that introduces the ability to select admin themes breaks pathing for the settings. When my code for admin themes is active Orchard no longer looks within the themes folder for the view specified by the handler in the theme. I can select and enable the theme just fine. I believe the problem is either in the new services I added or in the new site settings part.
  1. I added a settings part that contains the currently selected admin theme - this is the same as the part in the Orchard.Themes module
  2. I added an admin theme service which is a copy of the theme service in the Orchard.Themes module but looks for the "admin" tag in themes
  3. I added a site admin theme service which is a copy of the site theme service from the Orchard.Themes but utilizes the new settings part for admin themes
  4. I added an admin theme selector which is a copy of the theme selector in the Orchard.Themes module but used with the new site admin theme service
  5. I also added a controller that performs all the same operations but on admin themes
Any ideas would be greatly appreciated. Thank you.
Jun 2, 2015 at 9:36 PM
Edited Jun 2, 2015 at 9:50 PM
I've determined that it's a problem with having an admin theme other than TheAdmin that causes the problem. I copied TheAdmin theme, renamed it, and then activated it. As soon as I did so the settings on themes no longer worked. If I re-enable TheAdmin the settings begin to work again. Any ideas what would cause this to happen? It still appears as though Orchard forgets where to search when a different admin theme is active because I get an error saying the view couldn't be found with a list of searched locations, none of which are the actual theme. I believe this may be because I haven't distinguished between the two types of themes fully (when an admin theme other than TheAdmin is active Orchard might distinguish it as the current site theme). Orchard looks in the currently active admin theme for the view and doesn't find it. The only difference is when TheAdmin is active Orchard will continue to look in PJS.Bootstrap for the view whereas with my custom admin theme it doesn't. Any ideas as to what Orchard is doing and why would be appreciated. Thank you.

Edit: I ran into some more weird happenings so I decided to try installing the PJS.Bootstrap theme on a clean install of Orchard 1.9. There is some kind of problem either in the theme or in Orchard but as soon as the theme has been activated the settings menu item for the theme is displayed in the site settings (as expected). However if I reactivate the TheThemeMachine theme the settings for PJS.Bootstrap remain in place and work if clicked on. It seems they should disappear when the module is no longer active.
Jun 2, 2015 at 11:08 PM
Edited Jun 2, 2015 at 11:27 PM
I figured out the problem I believe. Orchard by default only looks in the two highest priority themes for the view so it ends up looking in both of the admin themes since Orchard has hard-coded TheAdmin as having a priority of 100. How would I go about removing this without altering the core. I tried putting a OrchardSupressDependency attribute on my AdminThemeSelector class but it doesn't seem to be working. I need a way to remove TheAdmin from being selected or at least a method of lowering it's priority. Once again I would prefer not to mess with the core. Thank you.

Edit: here is my code
    public class AdminThemeSelector : IThemeSelector {
        private readonly ISiteAdminThemeService _siteThemeService;
        public AdminThemeSelector(ISiteAdminThemeService siteThemeService) {
            _siteThemeService = siteThemeService;

        public ThemeSelectorResult GetTheme(RequestContext context) {
            string currentThemeName = _siteThemeService.GetCurrentAdminThemeName();
            if (AdminFilter.IsApplied(context))
                return String.IsNullOrEmpty(currentThemeName) ? null : new ThemeSelectorResult { Priority = 110, ThemeName = currentThemeName };
            return null;
Edit: It's possible I'm barking up the wrong tree here....
Jun 2, 2015 at 11:35 PM
Edited Jun 2, 2015 at 11:55 PM
I'm successfully overriding the AdminThemeSelector in Orchard.UI.Admin but whatever handles deciding where to look for the view is still looking only in themes/MyAdmin and themes/TheAdmin it skips right over the other themes (including PJS.Bootstrap which is the theme that contains the view). How does Orchard decide where to look for the view and can I override it to look in the right places?

Edit: I believe I have finally found the real problem. Somewhere while setting my custom admin theme as the admin theme to use, orchard set it as the current theme in its workcontext. How does orchard decide what the current theme is and can I avoid it assigning custom admin themes? It would appear orchard knows how to not include TheAdmin as the current theme because everything works fine when I set that as the current admin theme. Thank you.

I believe the problem lies in this bit of code which is setting the current admin theme
namespace ExtendedThemes.Themes.Services {
    public interface ISiteAdminThemeService : IDependency {
        ExtensionDescriptor GetSiteAdminTheme();
        void SetSiteAdminTheme(string themeName);
        string GetCurrentAdminThemeName();

    public class SiteAdminThemeService : ISiteAdminThemeService {
        public const string CurrentAdminThemeSignal = "SiteCurrentAdminTheme";

        private readonly IExtensionManager _extensionManager;
        private readonly ICacheManager _cacheManager;
        private readonly ISignals _signals;
        private readonly IOrchardServices _orchardServices;

        public SiteAdminThemeService(
            IOrchardServices orchardServices,
            IExtensionManager extensionManager,
            ICacheManager cacheManager,
            ISignals signals) {

            _orchardServices = orchardServices;
            _extensionManager = extensionManager;
            _cacheManager = cacheManager;
            _signals = signals;

        public ExtensionDescriptor GetSiteAdminTheme() {
            string currentAdminThemeName = GetCurrentAdminThemeName();
            return string.IsNullOrEmpty(currentAdminThemeName) ? null : _extensionManager.GetExtension(GetCurrentAdminThemeName());

        public void SetSiteAdminTheme(string adminThemeName) {
            var site = _orchardServices.WorkContext.CurrentSite;
            site.As<AdminThemeSiteSettingsPart>().CurrentAdminThemeName = adminThemeName;


        public string GetCurrentAdminThemeName() {
            return _cacheManager.Get("CurrentAdminThemeName", ctx => {
                return _orchardServices.WorkContext.CurrentSite.As<AdminThemeSiteSettingsPart>().CurrentAdminThemeName;
Jun 3, 2015 at 12:33 AM
After a whole lot of head thrashing nastiness I think I figured it out and it appears to be working. I had to override one of the theme aware view engines
Marked as answer by emeraldarcher on 6/2/2015 at 5:33 PM