我有一个Orchard CMS安装,启用了多租户模块,并设置了2个租户。两个租户都使用相同的主题。
我想要的是能够创建视图交替来定位每个租户,例如:
~/Themes/MyTheme/Views/Content.Tenant1.cshtml
会针对租户1和
~/Themes/MyTheme/Views/Content.Tenant2.cshtml
将以租户2为目标。
我意识到我可以用2个不同(但非常相似)的主题来做,但这感觉就像不必要的重复。
答案 0 :(得分:1)
答案当然是从ShapeDisplayEvents
继承并绑定到context.ShapeMetadata.OnDisplaying
事件:
public class MultiTenancyAlternatesFactory : ShapeDisplayEvents
{
private readonly ShellSettings _shellSettings;
public MultiTenancyAlternatesFactory(ShellSettings shellSettings)
{
_shellSettings = shellSettings;
}
public override void Displaying(ShapeDisplayingContext context)
{
context.ShapeMetadata.OnDisplaying(displayingContext =>
{
var tenant = _shellSettings.Name;
// look for ContentItem property
ContentItem contentItem = displayingContext.Shape.ContentItem;
// if not, check for ContentPart
if (contentItem == null)
{
ContentPart contentPart = displayingContext.Shape.ContentPart;
if (contentPart != null)
{
contentItem = contentPart.ContentItem;
}
}
var shapeName = displayingContext.ShapeMetadata.Type;
if (contentItem != null)
{
var contentTypeName = contentItem.ContentType;
displayingContext.ShapeMetadata.Alternates.Add(shapeName + "__" + contentTypeName + "__tenant__" + tenant);
}
displayingContext.ShapeMetadata.Alternates.Add(shapeName + "__tenant__" + tenant);
});
}
}
答案 1 :(得分:1)
我尝试在上面实现您的代码,但它仅适用于形状。
我希望有一个Index-tennant- [TenantName] .cshtml的视图来覆盖Index.cshtml
要做到这一点,我必须覆盖RazorViewEngineProvider,然后添加额外的路径供ViewEngine查找。我使用了[OrchardSuppressDependency ...],因为我不想对实际的Orchard CMS代码进行更改,因为这样会使任何未来的升级变得更加痛苦。
我希望这可以帮助那些在果园中提出多租户相同问题的人。
[UsedImplicitly]
[OrchardSuppressDependency("Orchard.Mvc.ViewEngines.Razor.RazorViewEngineProvider")]
public class RazorViewEngineProvider : Orchard.Mvc.ViewEngines.Razor.RazorViewEngineProvider, IViewEngineProvider, IShapeTemplateViewEngine
{
private readonly string _tenant;
public RazorViewEngineProvider(ShellSettings shellSettings)
{
_tenant = shellSettings.Name;
}
public new IViewEngine CreateThemeViewEngine(CreateThemeViewEngineParams parameters)
{
var viewEngine = base.CreateThemeViewEngine(parameters);
if (!string.IsNullOrWhiteSpace(_tenant))
{
var razorView = viewEngine as RazorViewEngine;
if (razorView != null)
{
razorView.PartialViewLocationFormats = addTenant(razorView.PartialViewLocationFormats);
razorView.AreaPartialViewLocationFormats = addTenant(razorView.AreaPartialViewLocationFormats);
}
}
return viewEngine;
}
public new IViewEngine CreateModulesViewEngine(CreateModulesViewEngineParams parameters)
{
var viewEngine = base.CreateModulesViewEngine(parameters);
if (!string.IsNullOrWhiteSpace(_tenant))
{
var razorView = viewEngine as RazorViewEngine;
if (razorView != null)
{
razorView.ViewLocationFormats = addTenant(razorView.ViewLocationFormats);
razorView.PartialViewLocationFormats = addTenant(razorView.PartialViewLocationFormats);
razorView.AreaViewLocationFormats = addTenant(razorView.AreaViewLocationFormats);
razorView.AreaPartialViewLocationFormats = addTenant(razorView.AreaPartialViewLocationFormats);
}
}
return viewEngine;
}
private string[] addTenant(string[] views)
{
var tenantedView = new List<string>();
foreach (var view in views)
{
if (view.EndsWith(".cshtml",StringComparison.OrdinalIgnoreCase))
tenantedView.Add(string.Format ("{0}-tenant-{1}.cshtml", view.Substring(0,view.Length - 7) ,_tenant));
tenantedView.Add(view);
}
return tenantedView.ToArray();
}
}