我正在尝试使用Razor Pages应用程序处理插件。
解决方案包含3个项目:一个Razor Pages应用程序和两个Razor类库(RCL)。应用程序一定不能静态引用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>
当我运行该应用程序时,有一些菜单项,但是它们的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.deps.json
与FeatureLib_A
和FeatureLib_B
作为从属关系(只需从第一种情况保存deps文件,删除引用,全部重建,复制保存的deps文件)。此外,我试图在Startup
类中急切地加载RCL程序集。
程序集正在加载,但是Index
页面的行为相同。
有没有办法告诉ASP基础结构使用RCL程序集而不修改deps文件?我想念什么?
答案 0 :(得分:2)
我知道了。
基本思想是为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
加载程序集。
答案 1 :(得分:0)
public class Startup
{
public Startup( IHostingEnvironment hostingEnvironment)
{
_hostingEnvironment = hostingEnvironment;
}
private readonly IHostingEnvironment _hostingEnvironment;
public void ConfigureServices(IServiceCollection services)
{
...
services.AddMvc()
.SetCompatibilityVersion(CompatibilityVersion.Version_2_2)
.ConfigureApplicationPartManager(ConfigureApplicationParts); ;
}
private void ConfigureApplicationParts(ApplicationPartManager apm)
{
string rootPath = _hostingEnvironment.ContentRootPath;
var pluginsPath = Path.Combine(rootPath, "Plugins");
var assemblyFiles = Directory.GetFiles(pluginsPath, "Plugin*.dll", SearchOption.AllDirectories);
foreach (var assemblyFile in assemblyFiles)
{
try
{
var assembly = Assembly.LoadFrom(assemblyFile);
if (assemblyFile.EndsWith(".Views.dll"))
apm.ApplicationParts.Add(new
CompiledRazorAssemblyPart(assembly));
else
apm.ApplicationParts.Add(new AssemblyPart(assembly));
}
catch (Exception e) { }
}
}
}