【发布时间】:2020-03-28 17:27:23
【问题描述】:
我告诉你,我有一个带有 netcore mvc 的应用程序,它从主项目的不同区域加载插件。
这很好用,但是在执行该区域时会引发以下错误:
处理请求时发生未处理的异常。
InvalidOperationException:未找到视图“索引”。搜索了以下位置: /Views/TestHome/Index.cshtml /Views/Shared/Index.cshtml /Pages/Shared/Index.cshtml
里面的区域叫做TestArea,但是并没有提升我的插件区的视图。
我的插件结构如下:
我的主项目结构如下:
在 Areas/Extensions/TestArea 文件夹中放置程序集,在 Areas/TestArea 文件夹中放置视图。
正如我提到的,加载插件并运行控制器,但执行它会抛出我之前暴露的错误。
我使用的代码如下:
PluginExtensions.cs
public static class PluginExtensions
{
public static IMvcBuilder AddExtensions(this IMvcBuilder mvc)
{
List<string> extensionAssemblies = new List<string>();
var serviceProvider = mvc.Services.BuildServiceProvider();
var configuration = serviceProvider.GetService<IConfiguration>();
var hostingEnvironment = serviceProvider.GetService<IWebHostEnvironment>();
var logger = serviceProvider.GetService<ILoggerFactory>().CreateLogger<Startup>();
List<string> extensionDirectories = EnumerateExtensionDirectories(serviceProvider).ToList();
List<string> searchPatternList = new List<string>
{
"*Extension.Mvc.dll"
};
mvc.ConfigureApplicationPartManager(apm =>
{
foreach(var extensionDirectory in extensionDirectories)
{
for (int i = 0; i < searchPatternList.Count; i++)
{
List<string> tempList = EnumerateExtensionAssemblies(extensionDirectory, searchPatternList[i]).ToList();
if (tempList != null && tempList.Count > 0)
extensionAssemblies.AddRange(tempList);
}//for(int i=0;i< searchPatternList.Count; i++)
foreach (var extensionPath in extensionAssemblies)
{
var pluginAssembly = AssemblyLoadContext.Default.LoadFromAssemblyPath(extensionPath);
var partFactory = ApplicationPartFactory.GetApplicationPartFactory(pluginAssembly);
foreach (var part in partFactory.GetApplicationParts(pluginAssembly))
{
apm.ApplicationParts.Add(part);
}
var relatedAssemblies = RelatedAssemblyAttribute.GetRelatedAssemblies(pluginAssembly, throwOnError: true);
foreach (var assembly in relatedAssemblies)
{
if (assembly.FullName.ToLower().IndexOf("extension.mvc.views") >= 0)
{
**var compiledRazorAssemblyApplicationParts = new CompiledRazorAssemblyApplicationPartFactory().GetApplicationParts(AssemblyLoadContext.Default.LoadFromAssemblyPath(assembly.Location));**
foreach (var craapf in compiledRazorAssemblyApplicationParts)
apm.ApplicationParts.Add(craapf);
}
else
{
partFactory = ApplicationPartFactory.GetApplicationPartFactory(assembly);
foreach (var part in partFactory.GetApplicationParts(assembly))
{
apm.ApplicationParts.Add(part);
}
}
}
}
}
});
return mvc;
}}
Startup.cs
public void ConfigureServices(IServiceCollection services)
{
services.AddSession(options =>
{
options.Cookie.Name = ".Matios.Session";
options.IdleTimeout = TimeSpan.FromMinutes(30);
options.Cookie.IsEssential = true;
});
services.AddControllersWithViews();
services.AddResponseCaching();
services.AddRazorPages();
services.AddAntiforgery(options =>
{
options.Cookie.Name = ".Matios.Antiforgery";
});
var iMvc= services.AddMvc(options =>
{
options.Filters.Add(new SessionExpireAttribute());
options.EnableEndpointRouting = true;
})**.AddExtensions()**;
services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();
}
最后我执行的 url 如下:http://localhost:5000/TestArea/TestHome/Index
你能帮帮我吗?
【问题讨论】:
-
几件事....您在“插件”中定义了两次TestArea/TestHome/Index.cshtml,一次在您的网站中定义...。我不确定这是否可行。 .. 其次,据我所知,搜索位置是相对于当前工作目录的。因此,当您将内容放入“扩展”时,它将如何找到所需的内容?我会首先从网站中删除 TestArea 并将这些“参考”放在项目的根目录中,而不是放在任何文件夹中。
-
另外你为什么要动态加载“插件”?我的意思是你已经将它们添加到主网站上......那么有什么意义呢?您不妨添加一个参考并省去自己的麻烦
-
重点是动态加载程序集,否则我会直接引用而不是动态加载。
-
是的,但是您将它们添加到主项目中......所以它违背了动态加载它们的目的......
-
问题你能显示你的Test.ModuleExtension.Mvc项目中所有文件的图像吗?
标签: c# asp.net-core asp.net-core-mvc