0

I would like to have an option wherein a user can choose his theme for the site from the dropdown list and the theme applies to that page [atleast].

I want this to be done in ASP.NET MVC 2 without using jquery like frameworks.

How can this be accomplished.

I am using the default webforms viewengine and donot want to go for a custom viewengine for this purpose.

Saravanan
  • 7,637
  • 5
  • 41
  • 72

1 Answers1

3

It seems this is not supported out of the box, but here's what I did to implement theming:

First, I Added the App_Themes folder to my project, and set up a couple of themesenter image description here

I then decided to try and mimic the Web-forms profile provider as close as possible, and added a profile-property to web.config:

<profile>
  <properties>
    <add name="ThemePreference" type="string" defaultValue="Blue" />
  </properties>
</profile>

So, basically what I wanted to do was to be able to load the different css's from the appropriate theme-folder when the theme changed. I did this by implementing a helper method attached to the UrlHelper class so that I could write:

<link href="@Url.Theme("~/Content/Site.css")" rel="stylesheet" type="text/css" />

This should then load the appropriate themed Site.css, and fall back to ~/Content/Site.css if no file was found.

The helper is pretty simple:

public static class UrlHelpers
{
    public static string Theme(this UrlHelper url, string u)
    {
        if (u.StartsWith("~")) u = u.TrimStart('~');
        SettingsProperty settingsProperty = ProfileBase.Properties["ThemePreference"];

        return url.Content("~/App_Themes/"+settingsProperty.DefaultValue + u);
    }
}

Now, in this version of the code it simply gets the default-value, so you'll need to tweak the code slightly. But as you can see, this is not limited to css-files, but works with everything from .master files to images.

Update - Using Session instead of profile

public static class UrlHelpers
{
    public static string Theme(this UrlHelper url, string u)
    {
        if (u.StartsWith("~")) u = u.TrimStart('~');

        object currentThemeName = null;
        if (url.RequestContext.HttpContext.Session != null)
        {
            currentThemeName = url.RequestContext.HttpContext.Session["ThemePreference"];
        }
        return currentThemeName != null ? url.Content(String.Format("~/App_Themes/{0}{1}", currentThemeName, u)) : url.Content("~"+u);
    }
}

The return-line in this method checks if it found a ThemePreference session-value, and then returnes the appropriate URL for the content requested, otherwise it simply returns the content as it was requested with no App_Theme prefix.

In your controlleraction for the DropDown postmethod, you'd simply do:

Session.Add("ThemePreference", whateverValueYouGotFromDropdown);

Update ends

With some tweaking and fixing, this should do the trick.

Hope it helps some, even though it's not a complete walkthrough :)

Yngve B-Nilsen
  • 9,606
  • 2
  • 36
  • 50
  • @Nilsen : As per your idea, it seems that I have to change the theme based on the theme name in the URL. Can't I use a dropdown in a page so that when a theme is selected, i can set the theme name in the viewdata and use this value in the view file so that the theme is changed. Is this a good practice?. As my project does not want to have the theme names in the URL.. – Saravanan Mar 30 '11 at 03:47
  • Well, there are no references to any URLs in my code, except of course for the actual App_Themes urls, but the user will never be presented with those URLS unless they inspect your source. You could store the value of the theme name in session, or on some property for the logged in user (if you are authenticating), and then just retrieve it from there. The key code here is in the UrlHelpers-class where you retrieve the settingsProperty. You can easily change that to use session instead. I'll update my answer with an example. – Yngve B-Nilsen Mar 30 '11 at 06:37
  • there you go. The last updated code was written without running any tests on it, but it should in all sense work as you would expect :) – Yngve B-Nilsen Mar 30 '11 at 06:45