插件中的ASP .NET Core MVC 2.1 mvc视图 [英] ASP .NET Core MVC 2.1 mvc Views in plugin
问题描述
我有一个困扰我几天的问题.
I have a problem that has tormented me for several days.
就像我在ASP .NET Core MVC中的插件中所做的那样,通过插件为我带来视图
As I do in a plugin in ASP .NET Core MVC to bring me views with the plugin
我有这种情况
解决方案:EVS
- 控制器
- ...
- Controllers
- ...
- ...
- 此文件夹包含一个插件dll
文件IPlugin.cs
file IPlugin.cs
... using McMaster.NETCore.Plugins; namespace EVS { public interface IPlugin { string Name { get; } void Do(); void BootReg(); void BootExecute(); void PluginConfigure(IApplicationBuilder app, IHostingEnvironment env); void PluginConfigureServices(IServiceCollection services); } public class PluginsManager { public List<PluginLoader> PluginLoaders; public Dictionary<string, IPlugin> Plugins; public Dictionary<string, Assembly> Views; public List<String> dllFileNames; public PluginsManager() { PluginLoaders = new List<PluginLoader>(); Plugins = new Dictionary<string, IPlugin>(); dllFileNames = new List<string>(); string PloginDirectory= Path.Combine(AppContext.BaseDirectory, "Plugins"); if (Directory.Exists(PloginDirectory)) dllFileNames.AddRange(Directory.GetFiles(PloginDirectory+"\\", "*.dll")); foreach (string dllFile in dllFileNames) { if (!dllFile.Contains(".Views.dll")) { var loader = PluginLoader.CreateFromAssemblyFile(dllFile,sharedTypes: new[] { typeof(IPlugin) }); PluginLoaders.Add(loader); } else { // // } } foreach (var loader in PluginLoaders) { foreach (IPlugin plugin in loader.LoadDefaultAssembly().GetTypes().Where(t => typeof(IPlugin).IsAssignableFrom(t) && !t.IsAbstract).Select((x)=> (IPlugin)Activator.CreateInstance(x))) if (!Plugins.ContainsKey(plugin.Name)) Plugins.Add(plugin.Name, plugin); } } } }
文件Program.cs
file Program.cs
namespace EVS { public class Program { public static void Main(string[] args) { foreach (IPlugin plugin in Global.Static.PluginsManager.Plugins.Select((x) => x.Value)) plugin.BootReg(); CreateWebHostBuilder(args).Build().Run(); } public static IWebHostBuilder CreateWebHostBuilder(string[] args) => WebHost.CreateDefaultBuilder(args) .UseStartup<Startup>(); } }
文件Startup.cs
file Startup.cs
namespace EVS { public class Startup { public Startup(IConfiguration configuration) { Configuration = configuration; } public IConfiguration Configuration { get; } public void ConfigureServices(IServiceCollection services) { services.Configure<CookiePolicyOptions>(options => { options.CheckConsentNeeded = context => true; options.MinimumSameSitePolicy = SameSiteMode.None; }); services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1); foreach (IPlugin plugin in Global.Static.PluginsManager.Plugins.Select((x) => x.Value)) { plugin.PluginConfigureServices(services); } } public void Configure(IApplicationBuilder app, IHostingEnvironment env) { if (env.IsDevelopment()) { app.UseDeveloperExceptionPage(); } else { app.UseExceptionHandler("/Home/Error"); } app.UseStaticFiles(); app.UseCookiePolicy(); foreach (IPlugin plugin in Global.Static.PluginsManager.Plugins.Select((x) => x.Value)) { plugin.PluginConfigure(app,env); } app.UseMvc(routes => { routes.MapRoute( name: "default", template: "{controller=Home}/{action=Index}/{id?}"); }); } } }
现在让我们以插件为例
solution:EVS.TestPlugin
solution:EVS.TestPlugin
- 控制器
- TestPluginController.cs
- Controllers
- TestPluginController.cs
- test.cshtml
文件:TestPlugin.cs
file: TestPlugin.cs
namespace EVS.TestPlugin { internal class TestPlugin : IPlugin { public string Name { get { return "TestPlugin"; } } public void BootReg() { ... } public void BootExecute() { ... } public void Do() { } public void PluginConfigure(IApplicationBuilder app, IHostingEnvironment env) { app.UseMvc(routes => { routes.MapRoute("TestPlugin", "TestPlugin/", new { controller = "TestPlugin", action = "index" }); routes.MapRoute("TestPlugint1", "TestPlugin/t1", new { controller = "TestPlugin", action = "t1" }); }); } public void PluginConfigureServices(IServiceCollection services) { services.AddMvc().AddApplicationPart(typeof(TestPluginController).GetTypeInfo().Assembly).AddControllersAsServices(); } } }
文件:Controllers/TestPluginController.cs
file: Controllers/TestPluginController.cs
namespace EVS.TestPlugin.Controllers { public class TestPluginController : Controller { public IActionResult Index() { return Content("<h1>TestPluginController</h1>"); } public IActionResult t1() { return View("test"); } } }
文件:Views/test.cshtml
file : Views/test.cshtml
@{ Layout = null; } `.cshtml` test view
解决方案中不包含插件,但是会根据它们是否庄重地位于文件夹中来动态加载它们.
Plugins are not included in the solution, but they are loaded dynamically depending whether they are in a folder solemnly for them.
问题: 我可以相应地添加控制器为
(EVS.TestPlugin.PluginConfigureServices (...))
和MapRoute (EVS.TestPlugin.PluginConfigure (...))
但是,如何添加视图的上下文呢? 因此它将打开:~/PluginName/Views/ViewName.cshatml
The problem: I can accordingly add controllers as
(EVS.TestPlugin.PluginConfigureServices (...))
andMapRoute (EVS.TestPlugin.PluginConfigure (...))
However, how could I also add the context of the views? Therefore it would be on:~/PluginName/Views/ViewName.cshatml
编辑
我找到了这个(链接),但这并不是我真正需要的.它部分解决了该问题,因为它仅在视图被编译时才起作用.
I found this (link), but it's not really what I need. It partially solve the problem, because it only work if the view are compiled.
编辑2
我立即解决了它,将视图引用添加到插件csproj上,如下所示:
Momentarily I solved it adding the views reference on to the plugins csproj, as follows:
<ItemGroup> <EmbeddedResource Include="Views\**\*.cshtml"/> <Content Remove="Views\**\*.cshtml" /> </ItemGroup> <PropertyGroup> <RazorCompileOnBuild>false</RazorCompileOnBuild> </PropertyGroup>
在源项目上:
// p is a Instance of plugin foreach(IPlugin p in Plugins.Select((x) => x.Value)) services.Configure<RazorViewEngineOptions>(options => { options.FileProviders.Add( new EmbeddedFileProvider(p.GetType().GetTypeInfo().Assembly)); });
这不能解决我的问题,因为
.cshtml
文件在插件文件中清晰可见,我需要的是能够从程序集pluginname.views.dll
或其他方式添加视图,这一点很重要视图已编译This does not solve my problem because the
.cshtml
files come in clear in the plugin file, what I need is to be able to add the views from the assemblypluginname.views.dll
or in some other way, the important that the views are compiled编辑3
好消息,我使用ILSpy解析了
PluginName.Views.dll
文件,发现它实现了RazorPage<object>
Good news, using ILSpy I parsed a
PluginName.Views.dll
file and I discovered that it implementsRazorPage<object>
使用以下代码,我验证了我可以初始化所有cono
RazorPage<object>
的缓存,这使我可以拥有创建视图的对象的实例With the following code I verified that I could initialize all the caches that cono
RazorPage<object>
which allows me to have the instances of the objects that create the viewforeach (string dllview in Views.Select((x) => x.Key)) { PluginLoader loader = PluginLoader.CreateFromAssemblyFile(dllview, sharedTypes: new[] { typeof(RazorPage<object>) }); foreach (RazorPage<object> RazorP in loader.LoadDefaultAssembly().GetTypes().Where(t => typeof(RazorPage<object>).IsAssignableFrom(t)).Select((x) => (RazorPage<object>)Activator.CreateInstance(x))) { // i need a code for add a RazorPagein the in RazorViewEngine, or anywhere else that allows register in the context System.Diagnostics.Debug.WriteLine(RazorP.GetType().ToString()); /* - output AspNetCore.Views_test AspNetCore.Views_TestFolder_htmlpage as you can see is the folder structure - folder tree: Project plugin folder Views test.cshtml TestFolder htmlpage.cshtml */ } }
已解决
感谢我所解决的所有问题,
Solved
thanks to all I solved, there seems to be a problem with
var assembly = ...; services.AddMvc() .AddApplicationPart(assembly)
有人甚至忘了把爵士乐零件工厂放进去
someone forgot to even put the razzor part factory
CompiledRazorAssemblyApplicationPartFactory
我解决了
services.AddMvc().ConfigureApplicationPartManager(apm => { foreach (var b in new CompiledRazorAssemblyApplicationPartFactory().GetApplicationParts(AssemblyLoadContext.Default.LoadFromAssemblyPath(".../ViewAssembypath/file.Views.dll"))) apm.ApplicationParts.Add(b); });
此外,我发布了一个库,该库可以高效地完成所有工作
in addition I published a library that does everything efficiently
推荐答案
感谢我所解决的所有问题,
thanks to all I solved, there seems to be a problem with
var assembly = ...; services.AddMvc() .AddApplicationPart(assembly)
有人甚至忘了把爵士乐零件工厂放进去
someone forgot to even put the razzor part factory
CompiledRazorAssemblyApplicationPartFactory
我解决了
services.AddMvc().ConfigureApplicationPartManager(apm => { foreach (var b in new CompiledRazorAssemblyApplicationPartFactory().GetApplicationParts(AssemblyLoadContext.Default.LoadFromAssemblyPath(".../ViewAssembypath/file.Views.dll"))) apm.ApplicationParts.Add(b); });
此外,我发布了一个库,该库可以高效地完成所有工作
in addition I published a library that does everything efficiently
这篇关于插件中的ASP .NET Core MVC 2.1 mvc视图的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!