Я делаю нечто подобное с некоторым программным обеспечением, которое я написал, и которое я размещаю на общем сервере. В зависимости от входящего домена, у меня может быть другой скин и некоторые параметры конфигурации.
В корне находится класс «Сайт», который имеет название сайта, описание и некоторую другую основную информацию. Затем он также хранит список атрибутов.
Таблицы выглядят так:
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)
)
Я использую Guids, потому что я хотел иметь возможность прикреплять атрибуты к различным объектам и искать их по идентификатору объекта. OwnerMask должен определить, для каких объектов допустимы различные атрибуты. Это было бы необязательно для вас.
Каждый класс, который может иметь атрибуты, реализует этот интерфейс:
public interface IPropertyContainer
{
void AddProperty(Property property);
string FindPropertyValue(string name);
Property FindProperty(string name);
void SetPropertyValue(string name, string value);
}
Я сожалею о разнице в именах (Атрибут и Свойство), но стало раздражающим иметь дело с тем фактом, что Атрибут также является предопределенным классом в .NET Framework. Класс Site реализует этот интерфейс.
Затем у меня есть служба, которая проверяет домен, на который поступает запрос, и проверяет базу данных, чтобы узнать, какой идентификатор сайта тоже отображается. Затем я загружаю объект сайта в HttpContext, используя HttpModule. Я включу код ниже, но, возможно, он не понятен вне контекста:
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;
}
Система атрибутов позволяет вам прикреплять любые произвольные данные к вашему сайту, что приятно, но она опирается на «Волшебные строки», которые некоторым могут не нравиться, но в этом случае это меня не слишком беспокоит.
Пример того, как я использую это, в базовом классе для каждого объекта Page, я задаю тему так:
protected override void OnPreInit(EventArgs e)
{
Page.Theme = ActiveContext.Current.Site.Theme;
base.OnPreInit(e);
}
Свойство Theme
заключает вызов одного из методов в интерфейсе IPropertyContainer
.
public string Theme
{
get { return FindPropertyValue("Theme") ?? "default"; }
}
Надеюсь, этот длинный пример дает вам отправную точку.
UPDATE
Я понимаю, что вы, возможно, не знакомы с HttpContext
или с тем, что я делаю с классом ActiveContext
. В основном я использую класс ActiveContext
, чтобы обеспечить строго типизированную оболочку для коллекций HttpContext.Items
и HttpContext.Sessio
n.
Данные сеанса сохраняются от одного вызова к другому, но могут вызвать проблемы в ситуациях с балансировкой нагрузки. HttpContext.Items
существует только на время текущего запроса. Вот код для моего ActiveContext
класса, который можно было бы получить с любой страницы aspx, вызвав статический метод ActiveContext.Current
открытый класс ActiveContext: IActiveContext
{
частный сайт _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;
}
}
}