2

I would like to change dynamically the page theme in a MVC 2 Application. I found several solutions, but I want to use this method: in the Global.asax, change the current page theme:

   protected void Application_PreRequestHandlerExecute(object sender, System.EventArgs e)
    {
        // cast the current handler to a page object
        Page p = HttpContext.Current.Handler as Page;

        if (p != null)
        {
            string strTheme = "Theme1";
            if (Convert.ToString(HttpContext.Current.Session["THEME"]) != string.Empty)
                strTheme = Convert.ToString(HttpContext.Current.Session["THEME"]);
            p.StyleSheetTheme = strTheme;
        }
    }

But this code always returns null in "p"... I've also tried a similar code using the event PreRequestHandlerExecute in a HttpModule and the PreInit event of a page, but the code

HttpContext.Current.Handler as Page

always returns null.

Can anyone help me? Thank you in advance.

mbp
  • 91
  • 1
  • 9
  • So every code posted in the below links are incorrect? http://forums.asp.net/p/1424103/3168832.aspx http://forums.asp.net/p/1400562/3029482.aspx http://stackoverflow.com/questions/58123/finding-system-web-ui-page-from-httpcontext – mbp Jan 14 '11 at 16:45
  • This technique won't work for MVC. – SLaks Jan 14 '11 at 16:46
  • Can you explain me briefly why, or have you any documentation about this? Thank you. – mbp Jan 14 '11 at 16:50
  • as I understand it the page (it's a ViewPage, but it does derive from Page) doesn't exist until the controller determines which view to render. This would be much later in the pipeline assuming it is ever set on the context at all in MVC. I honestly haven't looked into it in detail, but am just going by how I understand MVC to work. I'm not sure what you expect it to do anyway since you can't use any of the ASP.NET controls that it would affect anyway. – tvanfosson Jan 14 '11 at 16:57

2 Answers2

3

I don't use baked in themes, but I do use jQuery UI themes. The way I handle it is in my master page I have logic that gets the current theme from a common viewmodel. The master page is strongly typed to this view model. The common viewmodel properties are updated from user preferences and other sources in a common base controller that all my controllers inherit. I do this in OnActionExecuted. I check if the result is a ViewResult, then cast the result from ViewData on the ActionExecutedContext.Result property to my common view model and set the property. The master page uses the value of the property to build the url for the CSS file.

Model

public abstract class CommonViewModel
{
    public string Theme { get; set; }
    // ...
}

Controller

public abstract class BaseController : Controller
{
     public override void OnActionExecuted( ActionExecutedContext context )
     {
           if (context.Result is ViewResult)
           {
               var model = ((ViewResult)context.Result).ViewData.Model as CommonViewModel;
               if (model != null)
               {
                    var preferences = ...get from database for current user...
                    model.Theme = preferences.Theme;
               }
           }
    }
}

Master note it uses a custom HtmlHelper to generate the stylesheet link, you could do it by hand.

<%@ Master Language="C#"  Inherits="System.Web.Mvc.ViewMasterPage<...CommonViewModel>" >

<%: Html.Stylesheet( "themes/" + Model.Theme + ".css" ) %>
tvanfosson
  • 490,224
  • 93
  • 683
  • 780
0

The technique you are talking about works for standard asp.net, not asp.net MVC. The reason is that (in general) asp.net MVC does not use the web control model that standard asp.net does, and as such there is nothing to interpret the theme setting.

@tvanfosson has some great advice. Just remember that with MVC, you have much more control over things.. but that also means you have to do more work to get some of the features that standard asp.net provides for free. MVC makes many things easier, but this is not one of them.

Erik Funkenbusch
  • 90,480
  • 27
  • 178
  • 274