如何使用ASP.NET MVC设置多租户应用程序?

时间:2011-11-29 19:56:53

标签: asp.net-mvc dns multi-tenant

multitenancy应用程序是由多个组织(医疗机构,律师事务所......)共享的应用程序,而每个组织又拥有自己的用户。他们都登录了一个集中的环境。

要在应用程序中进行标识,必须在URL中表示组织。有两种主要的URL形式。子域名和文件夹:

  • [tenancy_name].appname.com/projects/view/123
  • www.appname.com/[tenancy_name]/projects/view/123

起初我尝试了第二个,因为此解决方案不涉及处理DNS。但问题是:每次开发人员需要表达网址(@Html.Action@Url.Action)时,都必须明确传递[tenancy_name]。这为开发增加了不必要的开销。可能的解决方法是实现这些HTML帮助程序的自定义版本,这些版本会自动考虑租赁名称。我正在考虑这个选择,但寻找更加明确的东西。我还意识到ASP.NET MVC会自动传递传出URL的路由值,但前提是控制器和操作与当前路由值相同。如果总是传递路线值,那就太好了。

要实现第一个选项,子域名,我想,我需要一些第三方DNS管理器。我听说过DynDNS并看了一眼,但我还不清楚它们是如何工作只是看他们的网站。我是否需要触发网络服务,告诉他们每次创建新租约时都要创建另一个子域?他们是否支持DNS中的通配符?它们是否可以在Windows Azure或共享主机上运行?

我在这里寻找方向。我应该走哪条路?

2 个答案:

答案 0 :(得分:1)

在codeplex上看这个项目,“baseRoute”也许可以帮到你。

http://mvccoderouting.codeplex.com/

问候。

答案 1 :(得分:0)

在我们的应用程序中使View视图解析变得微不足道:

使用方法: 对于您需要为特定租户重载的视图 - 将它们视为与自定义显示模式相同的方式: 以下工作:

Index.cshtml
Index.cust2.mobile.cshtml

Partials/CustomerAgreement.cust1.cshtml
Partials/CustomerAgreement.cust2.cshtml

据我记得,显示/编辑器模板的工作方式也相同

已知问题: 1.您必须为主要+辅助的所有组合创建布局(无论MVC原因是什么) 2.无论重塑者对显示模式的支持是什么 - 它都不支持“。”作为显示模式名称的一部分(这是跟踪进度的问题http://youtrack.jetbrains.com/issue/RSRP-422413

//put in application start --------

DisplayModeProvider.Instance.Modes.Clear();
foreach (var displayMode in GetDisplayModes())
{
    DisplayModeProvider.Instance.Modes.Add(displayMode);
}

private IEnumerable<IDisplayMode> GetDisplayModes()
{
    return new CompoundDisplayModeBuilder()
        .AddPrimaryFilter(_ => dependencyResolver.GetService(typeof(IResolveCustomerFromUrl)).GetName(),
            "cust1",
            "cust2")
        .AddSecondaryFilter(ctx => ctx.Request.Browser.IsMobileDevice, "mobile")
        .BuildDisplayModes();
}

//end of application start part


//and the mode builder implementation:
public class CompoundDisplayModeBuilder
{
    private readonly IList<DefaultDisplayMode> _primaryDisplayModes = new List<DefaultDisplayMode>();
    private readonly IList<DefaultDisplayMode> _secondaryDisplayModes = new List<DefaultDisplayMode>();

    //NOTE: this is just a helper method to make it easier to specify multiple tenants in 1 line in global asax
    //You can as well remove it and add all tenants one by one, especially if resolution delegates are different
    public CompoundDisplayModeBuilder AddPrimaryFilter(Func<HttpContextBase, string> contextEval, params string[] valuesAsSuffixes)
    {
        foreach (var suffix in valuesAsSuffixes)
        {
            var val = suffix;
            AddPrimaryFilter(ctx => string.Equals(contextEval(ctx), val, StringComparison.InvariantCultureIgnoreCase), val);
        }

        return this;
    }

    public CompoundDisplayModeBuilder AddPrimaryFilter(Func<HttpContextBase, bool> contextCondition, string suffix)
    {
        _primaryDisplayModes.Add(new DefaultDisplayMode(suffix) { ContextCondition = contextCondition });
        return this;
    }

    public CompoundDisplayModeBuilder AddSecondaryFilter(Func<HttpContextBase, bool> contextCondition, string suffix)
    {
        _secondaryDisplayModes.Add(new DefaultDisplayMode(suffix) { ContextCondition = contextCondition });
        return this;
    }

    public IEnumerable<IDisplayMode> BuildDisplayModes()
    {
        foreach (var primaryMode in _primaryDisplayModes)
        {
            var primaryCondition = primaryMode.ContextCondition;
            foreach (var secondaryMode in _secondaryDisplayModes)
            {
                var secondaryCondition = secondaryMode.ContextCondition;
                yield return new DefaultDisplayMode(primaryMode.DisplayModeId + "." + secondaryMode.DisplayModeId){
                    ContextCondition = ctx => primaryCondition(ctx) && secondaryCondition(ctx)
                };
            }
        }

        foreach (var primaryFilter in _primaryDisplayModes)
        {
            yield return primaryFilter;
        }

        foreach (var secondaryFilter in _secondaryDisplayModes)
        {
            yield return secondaryFilter;
        }

        yield return new DefaultDisplayMode();
    }
}
相关问题