Themes for MVC Views

If you have a MVC application and you wish to be able to configure it to use different views or .css, here is how.

Create the configuration

First things first. You’ll need to set somewhere the configuration which defines which of your themes to use. This part is dependent on what you are trying to achieve. When I used this method, my intentions where to provide some slightly different looking pages to be used when the application was deployed in an iFrame as opposed to when it ran on its own. So, for this purpose I just stuck a setting in the application’s web.config file. Like, so

<appSettings>
<add key="Theme" value="Default_Theme"/>
</appSettings>

Place your themed views into folders

The Next thing to do will be to place your views into sub-folders that are categorised by their theme. Here you will require one folder for “Default” views. In this folder you will need a full set of views (i.e. it has all pages required for the application). All subsequent theme folders will only need a page where it requires a different from the default. By which I mean, if your controller looks up a view and can’t find the file in your configured theme it will fall back and use the related default theme.

ThemeViewFolders

Create your custom RazorViewEngine

The next step is to use your configuration to display the set of views you want.

The standard RazorViewEngine will Get your razor views from the folder structure of “Views/Subfolder/page.cshtml”. However, now we have placed our views a layer down in the folder structure. We could, of course, explicitly define our path as “Views/Theme1/Subfolder.page.cshtml” everywhere but for obvious reasons this can get messy! There is another way, and that is to create a custom RazorViewEngine class. To do this you’ll need to add the following code to your application:


public class ThemedRazorViewEngine : RazorViewEngine
{
   public ThemedRazorViewEngine(string themeName)
   {
       const string defaultThemeName = "Default_Theme";

       MasterLocationFormats = new string[]
       {
        "~/Views/" + themeName + "/Shared/{0}.cshtml",
        "~/Views/" + defaultThemeName + "/Shared/{0}.cshtml",
       };

       PartialViewLocationFormats = new string[]
       {
         "~/Views/" + themeName + "/{1}/{0}.cshtml",
         "~/Views/" + themeName + "/Shared/{0}.cshtml",
         "~/Views/" + defaultThemeName + "/{1}/{0}.cshtml",
         "~/Views/" + defaultThemeName + "/Shared/{0}.cshtml"
       };

       ViewLocationFormats = new string[]
       {
         "~/Views/" + themeName + "/{1}/{0}.cshtml",
         "~/Views/" + themeName + "/Shared/{0}.cshtml",
         "~/Views/" + defaultThemeName + "/{1}/{0}.cshtml",
         "~/Views/" + defaultThemeName + "/Shared/{0}.cshtml"
       };
    }
}

And then add the following two statements in your global.asax in the Applicaton_Start() method to register your custom view engine:


// Gets the theme name from the web.config
string themeName = ConfigurationManager.AppSettings["Theme"];
ViewEngines.Engines.Clear();
ViewEngines.Engines.Add(new ThemedRazorViewEngine(themeName));

Using a seperate CSS file

As well as altering the layout of your views, you may also wish to apply alternate CSS to your themed views. The infrastructure for doing this is almost there, using the above. All you’ll have to do is create a new _Layout.cshtml file in the folder for your new theme, which renders the desired CSS.

The layout can look almost the same as what you had in your default theme (unless you desire otherwise), except you will need to choose which style you render. For example , by default your _Layout.cshtml will have the following line:

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

If you have placed your alternate CSS file in a seperate folder then you will need to replace this with something like:

@Styles.Render("~/Content/Themes/New_Theme/css")

Or if you wish to re-use the existing CSS but add some extra/specific stuff to it you can just choose to render the additional file, like:

 @Styles.Render("~/Content/css")
 @Styles.Render("~/Content/Themes/New_Theme/style.css")

I hope this helps!

Leave a Reply

Please log in using one of these methods to post your comment:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s