0

I have a single page that has a number of controls configured a certain way depending on some condition (e.g. if it is a user accessing the page or an admin). How I currently achieve this is by having an interface for the settings which are common to all pages, and then extending classes which implement the properties specific to the type of user.

For example:

public interface Display_Type
{
    string backgroundColor { get; }
}

public class AdminPage : Display_Type
{
    string backgroundColor { get { return "orange"; } }
}

public class UserPage : Display_Type
{
    string backgroundColor { get { return "blue"; } }
}

And my page's codebehind:

public partial class MyPage : System.Web.UI.Page
{
    Display_Type pageSettings;

    protected void Page_Load(object sender, EventArgs e)
    {
        if ((bool)Session["Is_Admin"])
        {
            pageSettings = new AdminPage();
        }
        else
        {
            pageSettings = new UserPage();
        }

        // ...

        string backgroundColor = pageSettings.backgroundColor;
        // ... Do stuff with background color
    }
}

This works fine for me, but since these settings are constant across the application, they seem to make more sense as static classes. However, I'm having trouble figuring out how to do this because I can't assign a static class to a variable.

My questions are:

  1. Is there a better way I can accomplish what I'm trying to do here?
  2. Or, if this is okay, how could I accomplish what I'm doing with static classes / members?

It may be worth noting that the user/admin example is not how I'm using this structure in my web application, and in fact has nothing to do with the user themselves but rather other factors such as request parameters.

Andrew Duthie
  • 298
  • 2
  • 5

6 Answers6

2

Put your settings on the BasePage and have other pages derive from it.

You will set the settings only once.

public abstract class MyBasePage : System.Web.UI.Page
{
    protected Display_Type PageSettings { get; private set; };

    protected void Page_Load(object sender, EventArgs e)
    {
        if ((bool)Session["Is_Admin"])
        {
            PageSettings = new AdminPage();
        }
        else
        {
            PageSettings = new UserPage();
        }
    }
}

public partial class MyPage : MyBasePage
{
    protected void Page_Load(object sender, EventArgs e)
    {
        // ...

        string backgroundColor = PageSettings.backgroundColor;
        // ... Do stuff with background color
    }
}
Jakub Konecki
  • 45,581
  • 7
  • 87
  • 126
  • Am I correct in assuming this is more or less how I am currently doing it, except that the logic for determining what page settings be used is assigned to this base page? If it makes any difference, these settings are only being used on a single page, not across many pages. – Andrew Duthie Oct 14 '11 at 14:13
0

This is not how I would do this, but if you are doing it this way, static classes have absolutely nothing to do with and no use in this situation.

You might consider having a single instance of each of the Display_Type classes stored somewhere to be reused, instead of creating a new one each time, though. This might end up being as a static variable... but that's not the same at all as a static class.

Andrew Barber
  • 39,603
  • 20
  • 94
  • 123
  • What do you mean by static classes would serve no purpose here? I'd think that by making them static and thereby global across the application for all users accessing the site, I could make at least a marginal performance impact. Am I wrong in thinking this? – Andrew Duthie Oct 14 '11 at 14:10
  • static classes have *nothing* to do with being "global to the application". They have to do with not having instance members. Static member variables, on the other hand, might be useful here, as I noted. – Andrew Barber Oct 14 '11 at 14:14
  • So making a class static would provide no benefit over declaring several instances of a non-static class that contains only static members? – Andrew Duthie Oct 14 '11 at 14:24
  • You cannot create even a single instance of a static class, making static classes *impossible* to use in this system. Instead, a single instance of each of the derived objects should be created somewhere, perhaps as static member variables, or using Cache or Application. – Andrew Barber Oct 14 '11 at 14:31
  • You can use the Singleton pattern to prevent multiple instantiations of the class containing the static members. It is more useful because it can be injected for testing purposes. – kmkemp Oct 14 '11 at 16:31
0

You can use a singleton to define your AdminPage and UserPage profile and add a static method GetDisplayType() to your implementation.

Massimo Zerbini
  • 3,125
  • 22
  • 22
0
public static class PageTypes {
    public static PageType Admin(/** stuff here */);
    public static PageType User(/** stuff here */);
}

public class PageType {
    readonly string _backgroundColor;
    public PageType (/** stuff here */) {
        _backgroundColor = backgroundColor;
    }

    public string BackgroundColor {
        get {
            return _backgroundColor;
        }
}

So now, you can access them like this in your method:

if ((bool)Session["Is_Admin"])           
{               
    PageSettings = PageTypes.Admin;    
}           
else           
{               
    PageSettings = PageTypes.User;
}

I agree with Jakub about using the base class to prevent code duplication.

kmkemp
  • 1,656
  • 3
  • 18
  • 21
  • Could this still be applied if my settings included a method? For example, in my application I'm using a method for `getDataSource()` in my page settings which, depending on the PageType, returns a result set which is then bound to a GridView. – Andrew Duthie Oct 14 '11 at 14:19
  • Sure. Not knowing how exactly that method looks, you could easily just pass in a delegate to PageType. – kmkemp Oct 14 '11 at 14:28
0

1. Is there a better way I can accomplish what I'm trying to do here?

Microsoft .NET has a built-in application settings implementation: setting files. Just use them if your settings aren't configurable by each user.

Application settings can be defined in a satellite assembly and overridden in the app.config or web.config of your application.

That's I find better to define such settings using setting files, which is a built-in, understandable and well-implemented solution and you've it out-of-the-box.

How to accomplish your goal using setting files?

You can use configuration by convention, and your background color settings will look like this:

  • AdminPage_BackgroundColor => #000000
  • UserPage_BackgroundColor => #FFFFFF
  • and so on

In your case, you've two background color settings for both pages, but if you'd need to configure background color for any of pages, you'd do this in your Page-derived class instance:

Properties.PagesStyle.Default[GetType().Name + '_' + "BackgroundColor"]

And you'll be able to get background color by page and from your settings file.

Let's implement this in your page class:

public partial class MyPage : System.Web.UI.Page
{
    Color backgroundColor = null;

    protected void Page_Load(object sender, EventArgs e)
    {
        if ((bool)Session["Is_Admin"])
        {
            backgroundColor = Properties.PagesStyle.Default.AdminPage_BackgroundColor;
        }
        else
        {
            backgroundColor = Properties.PagesStyle.Default.UserPage_BackgroundColor;
        }

        // ... Do stuff with background color
    }
}

Note settings files allow you to define strongly-typed values. Let's say you typed "UserPage_BackgroundColor" as System.Drawing.Color, designer will edit color by using a color picker, and when you access to this setting, you'll get a System.Color instead.

Before begin with another approach, check these useful links:


Recommended approach

There's a solid, stable and valuable way of styling Web sites: CSS.

Instead of creating your own styling approach, just play with CSS classes.

For example, in some CSS stylesheet you define both background colors for admin page and user page:

body.UserPage
{
    background-color: #000;
}

body.AdminPage
{
    background-color: #FFF;
}

Just imagine you've this ASP.NET page (I'll include standard XHTML markup only):

<html>
  <head></head>
  <body id="body" runat="server"></body>
</html>

In your code-behind code perhaps you can do this:

public partial class MyPage : System.Web.UI.Page
{
    protected void Page_Load(object sender, EventArgs e)
    {
        if ((bool)Session["Is_Admin"])
        {
            body.Attributes["class"] = "AdminPage";
        }
        else
        {
            body.Attributes["class"] = "UserPage";
        }
    }
}

This way you avoid:

  • Creating redundant settings since you use CSS as styling mechanism (don't reinvent the wheel!).
  • Compiling styling values: it's a client-side thing, because it's CSS.
Community
  • 1
  • 1
Matías Fidemraizer
  • 63,804
  • 18
  • 124
  • 206
  • I appreciate the effort you put into this response. In my application however, there are many settings, many page types, not all are simple strings, and not all are related to styles. I realize I should emphasized this more clearly in my original question. – Andrew Duthie Oct 14 '11 at 14:49
  • @AndrewD That's why I started by giving you a more solid idea to implement settings in your application, and later I recommended you CSS approach, which can be achieved combining both first and second approaches :) – Matías Fidemraizer Oct 14 '11 at 14:50
-1

To answer your second question, a implementation of a static solution:

public interface IDisplayType
{
    string backgroundColor { get; }
}

public class AdminPage : IDisplayType
{
    public string backgroundColor { get { return "orange"; } }
}

public class UserPage : IDisplayType
{
    public string backgroundColor { get { return "blue"; } }
}

public static class PageProperties
{
    private static AdminPage _adminPage = new AdminPage();
    private static UserPage _userPage = new UserPage();

    public static IDisplayType DisplayType { get
    {
        if ((bool)HttpContext.Current.Session["Is_Admin"])
         {
            return _adminPage;
         }

        return _userPage;
    }
 }

I also changed the type Display_Type to IDisplayType which gives a beter description of what it is.

You could then use the following code in your page.

string backgroundColor = PageProperties.DisplayType.backgroundColor;
Martijn B
  • 4,065
  • 2
  • 29
  • 41
  • While I found the other answers very helpful, I think this solution is most applicable to my scenario. Thanks! – Andrew Duthie Oct 14 '11 at 14:45
  • Not in general. Yes this code is harder to unit test because of the dependency on HttpContext.Current.Session but this is no different then unit testing your example. Making your code beter testable is a subject on his own and involves other subjects like depency injection which is far to heavy for what the solution needs. I just answered the question to his needs. Don't agree with the downvote! – Martijn B Oct 14 '11 at 15:28