tags:

views:

118

answers:

2

Hi, I have a site where provide pseudo subdomain based sites. Each subdomain has a set of settings (ie. String name, string css, string title) that I need to access on all pages. What would be the best way of storing them for easy access?

I can't use webconfig because different subdomains have their own settings collection so I store settings on sql server. I thought of caching all settings with different cache name but I am worried about the memory hog. Regardless using cache I understand I need to write some sort of class where I expose each setting as property.

Any ideas?

+2  A: 

Why don't you subclass the Page or MasterPage to then expose your properties?

In a C# file...

class MyPage : System.Web.UI.Page
{
    string PropertyName { get; set; }
}

In the all the ASPX files...

<%@ Page Language="C#" Inherits="MyNamespace.MyPage" %>
Daniel A. White
im not realy fan of masterpages with my 2 months .net exprince. how can i sub class (or extends Page class?) with those properties?
nLL
In the code behind file for a page, you can tell it to use a "MyPage" instead of the "System.Web.UI.Page" class and that will give you the properties in "MyPage" easily enough. If you need a reference, look up the concept of Inheritance.
JB King
class PageExtented : Page{ // your properties here...}
Rorschach
+2  A: 

I do something similar with some software I wrote that I host on a shared server. Depending on the domain coming in, I end up with a different skin and some configuration options.

At the root is the "Site" class that has the site title, description, and some other basic information. Then it also keeps a list of attributes.

The tables look like this:

Create Table [Site](
    [Id]          uniqueidentifier default newSequentialId(),
    [Name]        nvarchar(128),
    [Description] nvarchar(512),
    Constraint pk_Site Primary Key (Id)
)

Create Table [Attribute](
    [Id]        int identity(1,1),
    [Key]       varchar(128),
    [Type]      varchar(16),
    [OwnerMask] int,
    Constraint pk_AttributeId Primary Key (Id),
    Constraint uq_AttributeKey Unique ([Key])
)

Create Table [AttributeValue](
    [OwnerId]     uniqueidentifier,
    [AttributeId] int,
    [Value]       nvarchar(512),
    Constraint pk_Owner_Attrib Primary Key (OwnerId, AttributeId)
)

I'm using Guids because I wanted to be able to attach the attributes to different objects, and be able to look them up by the object id. The OwnerMask is to determine which objects the different attributes are valid for. This would be optional for you.

Every class that can have Attributes implements this interface:

public interface IPropertyContainer
{
    void AddProperty(Property property);
    string FindPropertyValue(string name);
    Property FindProperty(string name);
    void SetPropertyValue(string name, string value);
}

I regret the name difference (Attribute vs. Property) but it became annoying to deal with the fact that Attribute is also a predefined class in the .NET Framework. The Site class implements this interface.

I then have a service that checks the domain the request is coming in on and checks the database to see which Site Id that maps too. I then load the site object into the HttpContext using an HttpModule. I'll include the code below, but it's maybe not clear out of context:

private static void AuthenticateRequestHandler(object sender, EventArgs e)
{
    HttpApplication app = sender as HttpApplication;

    if(app == null) return;

    Uri url = app.Request.Url;
    string domain = url.Host;
    string path = url.AbsolutePath.ToLower().Replace("default.aspx", "");

    IInjectionWrapper wrapper = new WindsorWrapper();
    ISiteProvider provider = wrapper.Resolve<ISiteProvider>();
    Site site = provider.FindSiteByDomain(domain);

    if (site == null)
        return;

    ActiveContext.Current.Site = site;
}

The attribute system allows you to attach any arbitrary data to your site, which is nice, but it does rely on "Magic Strings" which some may not like, but in this case it doesn't bother me too much.

An example of how I use this, is in a base class for each Page object, I set the theme like so:

protected override void OnPreInit(EventArgs e)
{
    Page.Theme = ActiveContext.Current.Site.Theme;

    base.OnPreInit(e);
}

The Theme property is wrapping a call to one of the methods on the IPropertyContainer interface.

public string Theme
{
    get { return FindPropertyValue("Theme") ?? "default"; }
}

Hopefully this long winded example gives you a jumping off point.

UPDATE

I realize you might not be familiar with the HttpContext or what I'm doing with the ActiveContext class. Basically I'm using the ActiveContext class to provide a strongly typed wrapper around the HttpContext.Items and HttpContext.Session collections.

Session data is persisted from one call to the next, but can cause problems in load balanced situations. HttpContext.Items only exist for the duration of the current request. Here is the code for my ActiveContext class which would be available from any aspx page by calling the static method ActiveContext.Current

public class ActiveContext : IActiveContext { private Site _site;

public static IActiveContext Current
{
    get
    {
        IActiveContext activeContext;

        activeContext = Context.Items["ActiveContext"] as ActiveContext;
        if (activeContext == null)
        {
            activeContext = new ActiveContext();
            Context.Items["ActiveContext"] = activeContext;
        }

        return activeContext;
    }
}

public Person AuthenticatedUser
{
    get
    {
        Person person = Context.Session["AuthenticatedUser"] as Person;
        return person;
    }
    set { Context.Session["AuthenticatedUser"] = value; }
}

public Site Site
{
    get { return Context.Items["CurrentSite"] as Site; }
    set { Context.Items["CurrentSite"] = value; }
}

private static HttpContext Context
{
    get
    {
        HttpContext context = HttpContext.Current;
        if (context == null)
            throw new Exception("HttpContext is null");

        return context;
    }
}

}

NerdFury