如何从 Razor Pages 应用程序中的插件动态加载页面?

2024-02-15

我正在尝试使用 Razor Pages 应用程序处理插件。

解决方案由 3 个项目组成:一个 Razor Pages 应用程序和两个 Razor 类库 (RCL)。应用must not静态引用 RCL 项目,它们必须作为插件加载:

内页没有什么特别的。功能页面仅生成简单的 HTML。索引页构建了一种菜单。

索引页模型:

public class IndexModel : PageModel
{
    public IEnumerable<MenuItem> MenuItems { get; private set; }

    public void OnGet()
    {
        MenuItems = new List<MenuItem>
        {
            new MenuItem { Route = "FeatureA", Title = "Feature A" },
            new MenuItem { Route = "FeatureB", Title = "Feature B" }
        };
    }
}

索引页:

@page
@model IndexModel
@{
    ViewData["Title"] = "Home page";
}

<div class="text-center">
    <div class="navbar-collapse collapse d-sm-inline-flex flex-sm-row-reverse">
        <ul class="navbar-nav flex-grow-1">
            @foreach (var item in Model.MenuItems)
            {
                <li class="nav-item">
                    <a class="nav-link text-dark" asp-area="" asp-page="/@item.Route">@item.Title</a>
                </li>
            }
        </ul>
    </div>
</div>

当我运行该应用程序时,有菜单项,但它们的hrefs 为空:

<div class="text-center">
    <div class="navbar-collapse collapse d-sm-inline-flex flex-sm-row-reverse">
        <ul class="navbar-nav flex-grow-1">
                <li class="nav-item">
                    <a class="nav-link text-dark" href="">Feature A</a>
                </li>
                <li class="nav-item">
                    <a class="nav-link text-dark" href="">Feature B</a>
                </li>
        </ul>
    </div>
</div>

当然,所有程序集(应用程序和功能程序集)都位于同一目录中。

菜单在以下两种情况下起作用:

  • 如果我在 App 项目中引用 RCL 项目,这会扼杀插件的想法;
  • 或者如果我把App.deps.json with FeatureLib_A and FeatureLib_B作为依赖项(只需保存第一种情况下的 deps 文件,删除引用,重建全部,复制保存的 deps 文件)。

另外,我尝试在中加载 RCL 程序集Startup班级。 正在加载程序集,但是Index页面行为相同。

有没有办法告诉 ASP 基础结构使用 RCL 程序集而不修改 deps 文件?我缺少什么?


我已经弄清楚了。

基本思想是给予ApplicationPartManager适当的应用部分。
需要注意的是:

  • “代码”程序集(例如FeatureLib_A.dll) 必须添加为AssemblyPart;
  • “查看”程序集(例如FeatureLib_A.Views.dll) 必须添加为CompiledRazorAssemblyPart.

示例代码:

public class Startup
{
    // ...

    public void ConfigureServices(IServiceCollection services)
    {
        var assemblyLoader = new DotNetCoreAssemblyLoader(searchPattern: "FeatureLib*.dll");

        services.AddMvc()
            .ConfigureApplicationPartManager(_ =>
            {
                foreach (var assembly in assemblyLoader.Assemblies)
                {
                    if (assembly.FullName.Contains("Views"))
                    {
                        _.ApplicationParts.Add(new CompiledRazorAssemblyPart(assembly));
                    }
                    else
                    {
                        _.ApplicationParts.Add(new AssemblyPart(assembly));
                    }
                }
            })
            .SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
    }

    // ...
}

DotNetCoreAssemblyLoader是一个自定义类,它使用给定的搜索模式查找程序集文件,并通过AssemblyLoadContext.Default.LoadFromAssemblyPath.

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何从 Razor Pages 应用程序中的插件动态加载页面? 的相关文章