IViewLocationExpander 不适用于部分视图(MVC 核心)

gri*_*ohn 1 c# model-view-controller asp.net-core

我定义了一个自定义IViewLocationExpander来检查多租户 Web 应用程序中特定于站点的视图。

想象一下有两个租户 WebsiteA 和 WebsiteB 以及HomeControllerIndex View的以下文件结构

  • 意见
      • 网站A
        • 索引.cshtml
      • 索引.cshtml

我的 IViewLocationExpander 将为 WebsiteA 呈现Views/Home/WebSiteA/Index.cshtml ,为 WebsiteB 呈现Views/Home/Index.cshtml - 因为没有特定于 WebsiteB 的索引视图,因此它使用默认视图。

我还在视图中设置了一个名为“Common”的文件夹来保存任何部分视图 - 这个想法是我可以以相同的方式呈现自定义部分视图(例如标题)。

  • 意见
    • 常见的
      • 网站A
        • _Header.cshtml
      • _Header.cshtml

这是我的IViewLocationExpander的代码

public sealed class TenantViewLocationExpander : IViewLocationExpander
{
    private ITenantService _tenantService;
    private string _tenant;

    public IEnumerable<string> ExpandViewLocations(ViewLocationExpanderContext context, IEnumerable<string> viewLocations)
    {
        string[] locations =
        {
            "/Views/{1}/" + _tenant + "/{0}.cshtml",
            "/Views/Common/" + _tenant + "/{0}.cshtml",
            "/Views/Shared/" + _tenant + "/{0}.cshtml",
            "/Pages/Shared/" + _tenant + "/{0}.cshtml",
            "/Views/{1}/{0}.cshtml",
            "/Views/Common/{0}.cshtml",
            "/Views/Shared/{0}.cshtml",
            "/Pages/Shared/{0}.cshtml"
        };
        return locations;
    }

    public void PopulateValues(ViewLocationExpanderContext context)
    {
        _tenantService = context.ActionContext.HttpContext.RequestServices.GetRequiredService<ITenantService>();
        _tenant = _tenantService.GetCurrentTenant();
    }
}
Run Code Online (Sandbox Code Playgroud)

一切都适用于标准视图,但是当我尝试渲染部分视图时,我总是得到默认返回(例如上面示例中的Views/Common/_Header.cshtml )

我在我的布局中渲染部分,就像这样......

<partial name="_Header.cshtml" />
Run Code Online (Sandbox Code Playgroud)

如果我删除Views/Common/_Header.cshtml文件 - 只留下特定于站点的文件 - 我会收到一个异常,指出无法找到该视图

InvalidOperationException: The partial view '_Header.cshtml' was not found. The following locations were searched:
/Views/Shared/_Header.cshtml
Run Code Online (Sandbox Code Playgroud)

扩展器似乎没有添加部分视图的额外位置。所以我的问题是,如何配置IViewLocationExpander来与 Partials 一起使用?

在旧版本的 MVC 中,我发现您可以通过设置ViewLocationFormatsPartialViewLocationFormats来专门定义它们,但在 MVC Core 中我在任何地方都看不到该选项?

如果这已在其他地方被掩盖,我深表歉意 - 我在任何地方都找不到答案。

提前致谢!

gri*_*ohn 5

对于任何可能遇到同样问题的阅读本文的人 - 似乎您需要从部分标记中省略“.cshtml”。

<!--- Works with all ViewLocations defined in IViewLocationExpander --->
<partial name="_Header" />
Run Code Online (Sandbox Code Playgroud)

而如果您包含如下所示的“.cshtml”,它似乎只搜索默认的部分视图位置 -“Views/Shared”

<!--- Only looks in 'Views/Shared' --->
<partial name="_Header.cshtml" />
Run Code Online (Sandbox Code Playgroud)

不确定这是否是故意的,但对我来说,这绝对是 MVC 中的一个奇怪的错误。