С Ninject вы можете использовать внедрение зависимостей для каждого запроса, чтобы определить, для какого арендатора запрос.
Я сделал так, чтобы добавить NinjectMVC3
, используя Nuget, в свой проект, который затем добавляет класс App_Start/NinjectMVC3
. Этот класс содержит подпрограмму RegisterServices(IKernel kernel)
, в которой вы можете зарегистрировать свои зависимости.
Я указал для загрузки своих зависимостей внутри модуля, а не напрямую в этой подпрограмме:
private static void RegisterServices(IKernel kernel)
{
kernel.Load(new TenantConfigurationModule());
}
Модуль был указан как:
public class TenantConfigurationModule : NinjectModule
{
public override void Load()
{
IEnumerable<ITenantConfiguration> configuration = //Instantiate a list of configuration classes from where they are stored.
//Initialise a ninject provider to determine what configuration object to bind to on each request.
TenantConfigurationProvider provider = new TenantConfigurationProvider(configuration);
//And then bind to the provider specifying that it is on a per request basis.
Bind<ITenantConfiguration>().ToProvider(provider).InRequestScope();
}
}
Базовые классы конфигурации могут быть указаны как:
public interface ITenantConfiguration
{
string TenantName { get; }
IEnumerable<string> UrlPaths { get; }
//whatever else you need for the tenant configuration
}
public abstract class TenantConfiguration : ITenantConfiguration
{
public string TenantName { get; protected set; }
public IEnumerable<string> UrlPaths { get; protected set; }
}
А затем указывается фактическая конфигурация:
public class TenantOneConfiguration : TenantConfiguration
{
public MVTTenantConfiguration()
{
TenantName = "MVT";
UrlPaths = new string[] { "http://localhost:50094" }; //or whatever the url may be
}
}
public class TenantOneConfiguration : TenantConfiguration
{
public MVTTenantConfiguration()
{
TenantName = "MVT";
UrlPaths = new string[] { "http://localhost:50095" };
}
}
Тогда можно написать провайдеру:
public class TenantConfigurationProvider : Provider<ITenantConfiguration>
{
private IEnumerable<ITenantConfiguration> configuration;
public TenantConfigurationProvider(IEnumerable<ITenantConfiguration> configuration)
{
if (configuration == null || configuration.Count() == 0)
{
throw new ArgumentNullException("configuration");
}
this.configuration = configuration;
}
protected override ITenantConfiguration CreateInstance(IContext context)
{
//Determine the request base url.
string baseUrl = string.Format("{0}://{1}", HttpContext.Current.Request.Url.Scheme, HttpContext.Current.Request.Url.Authority);
//Find the tenant configuration for the given request url.
ITenantConfiguration tenantConfiguration = configuration.Single(c => c.UrlPaths.Any(p => p.Trim().TrimEnd('/').Equals(baseUrl, StringComparison.OrdinalIgnoreCase)));
if (tenantConfiguration == null)
{
throw new TenantNotFoundException(string.Format("A tenant was not found for baseUrl {0}", baseUrl));
}
return tenantConfiguration;
}
}
Затем вы можете добавить конфигурацию в контроллеры, представления, атрибуты и т. Д. По мере необходимости.
Вот несколько полезных ссылок:
Чтобы использовать внедрение зависимостей в ваших представлениях путем наследования от класса представления: см. Ссылку
Чтобы увидеть описание и пример приложения с несколькими арендаторами: см. Ссылку
zowens может привести множество примеров, но реализация многопользовательского режима в asp.net mvc - непростая задача. Этот пример дает несколько хороших идей, но я использовал это как основу для реализации своих собственных. В этом примере каждая конфигурация арендатора сохраняется в отдельном проекте c #, а затем при запуске выполняет поиск конфигураций (вы можете использовать отражение для этого), чтобы найти всех арендаторов, которые будут использоваться. Каждый проект конфигурации арендатора может хранить настройки, представления, переопределенные контроллеры, CSS, изображения, специфичные для этого арендатора JavaScript, не требуя изменений в основном приложении. В этом примере также используется StructureMap для внедрения зависимостей. Я выбрал Ninject, но вы, вероятно, могли бы использовать все, что вам нравится, если он разрешается на основе запроса.
В этом примере также используется движок Spark View, так что представления могут быть легко сохранены в других проектах. Я хотел придерживаться механизма просмотра бритвы, но это немного сложнее, так как представления должны быть предварительно скомпилированы. Для этого я использовал генератор бритвы Дэвида Эббоса, который является отличным компилятором представления, снабженным предварительно скомпилированным механизмом просмотра: см. Ссылку
Примечание. Если вы попытаетесь реализовать свои представления в отдельном проекте, это может быть довольно сложно реализовать правильно. Я должен был реализовать свой собственный движок представлений и фабрику виртуальных путей, чтобы заставить его работать, но это стоило хлопот.
Кроме того, если вы реализуете свои ресурсы в отдельном проекте, то следующая ссылка может быть полезным предложением о том, как извлечь информацию из этих проектов: см. Ссылку
Надеюсь, это также поможет в реализации многопользовательского режима в вашем приложении mvc3. К сожалению, у меня нет примера приложения, которое я мог бы загрузить куда-либо, поскольку моя реализация включена в реализацию в рабочем проекте.