mvc5多租户和自定义视图

时间:2014-07-05 10:34:34

标签: .net asp.net-mvc subdomain multi-tenant virtualpathprovider

我正在尝试使用多租户应用,租户可以获得自己的子域,例如。

  • tenant1.mysite.com
  • tenant2.mysite.com

我尝试过使用自定义routedata,它只能在第一页上工作,不知何故在其他页面上如/ login,/ register等等,总是会抛出错误而且会变得非常神秘。

我放弃并继续使用通配符DNS,让我的HomeController确定如何基于子域呈现视图

ActionFilter

public class SubdomainTenancy : ActionFilterAttribute
{
    public override void OnActionExecuting(ActionExecutingContext filterContext)
    {
        string subdomain = filterContext.RequestContext.HttpContext.Request.Params["subdomain"]; // A subdomain specified as a query parameter takes precedence over the hostname.
        if (subdomain == null)
        {
            string host = filterContext.RequestContext.HttpContext.Request.Headers["Host"];
            int index = host.IndexOf('.');
            if (index >= 0)
                subdomain = host.Substring(0, index);
            filterContext.Controller.ViewBag.Subdomain = subdomain; 
        }    
        base.OnActionExecuting(filterContext);
    }
}

家庭控制器

[SubdomainTenancy]
[AllowAnonymous]
public class HomeController : BaseController
{
    public ActionResult Index()
    {
        string subdomain = ViewBag.Subdomain;
        if (subdomain != "www" && !string.IsNullOrEmpty(subdomain) )
        {
            var db = new tenantdb();
            var store = db.GetBySubdomain(subdomain);
            if (store == null) 
            {
                return Redirect(HttpContext.Request.Url.AbsoluteUri.Replace(subdomain, "www"));
            }
            else //it's a valid tenant, let's see if there's a custom layout
            { 
                //load custom view, (if any?)
            }
        }
        return View();            
    }       
}

所以现在问题出现了,当我尝试使用VirtualPathProvider从数据库加载基于子域的View时,但是我无法访问HttpContext,可能是由于生命周期?现在我卡住了,我也尝试使用RazorEngine加载自定义视图(来自数据库)

我应该如何支持我的网络应用上的多租户,它首先会在数据库中搜索自定义视图并使用数据库中的视图进行渲染,否则如果没有,则回退到默认的/Home/Index.cshtml?

1 个答案:

答案 0 :(得分:1)

我们通过制作自定义ViewEngine并让它了解应用程序的多租户来做类似的事情...... 然后,ViewEngine可以根据子域查找视图(在我们的例子中是物理的,但可能来自数据库)。

我们使ViewEngine继承自RazorViewEngine,然后根据需要覆盖方法(FileExists,FindPartialView,FindView)

一旦我们有了自定义的ViewEngine,我们就清除了其他ViewEngines并在global.asax的application_start中注册了自定义的ViewEngine。

ViewEngines.Engines.Clear()
ViewEngines.Engines.Add(new CustomViewEngine()) 

我没有可以在自定义ViewEngine上分享的示例代码,但希望这会指向正确的方向。