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

标签 c# asp.net-core razor-pages

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

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

enter image description here

内页没有什么特别之处。专题页面只生成简单的 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>

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

<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.jsonFeatureLib_AFeatureLib_B 作为依赖项(只需保存第一种情况下的 deps 文件,删除引用,重建所有,复制保存的 deps 文件)。

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

有什么方法可以告诉 ASP 基础结构在不修改 deps 文件的情况下使用 RCL 程序集?我错过了什么?

最佳答案

我想通了。

基本思想是给 ApplicationPartManager 适当的应用程序部分。
重要的是要注意:

  • “代码”程序集(例如 FeatureLib_A.dll)必须作为 AssemblyPart 添加;
  • “ View ”程序集(例如 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 加载程序集。

关于c# - 如何从 Razor Pages 应用程序中的插件动态加载页面?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53954850/

相关文章:

c# - 如何使用 PerformanceCounter 类计算 CPU 使用率百分比?

c# - ODP.net 将 UDT 作为表传递给 C# 中的存储过程

angular - StaticInjectorError - 填充下拉列表

c# - 将ASP.NET Core(使用NAudio)部署到Kubernetes时获取System.DllNotFoundException

c# - UserManager 在创建用户时不初始化属性

c# - Razor Pages - 由于多个对象共享参数,模型验证失败

c# - asp.net 核心 Razor 页面 'loading indicator'

c# - 从 CGI 脚本调用时 Mono 挂起

c# - 如何在 ASP.NET Core 中下载文件?

entity-framework - 使用 Entity Framework Core 执行原始 sql