能否在运行时创建动态ASP.NET Core Razor视图与控制器文件?
运行时创建动态ASP.NET Core Razor视图与控制器的实现方案
一、直接创建文件能否被框架识别?
不行。ASP.NET Core的控制器发现机制是在应用启动时扫描已加载的程序集,运行时新增的.cs(控制器类)或.cshtml.cs(页面模型)文件不会自动被编译和加载,因此框架无法识别为有效控制器;视图文件虽是实体文件,但没有对应控制器Action的话也无法正常调用。
二、文本模板生成文件+运行时编译的可行方案
通过文本模板生成实体的.cshtml视图和控制器/页面模型代码文件,再配合动态编译加载程序集的方式,可以实现运行时渲染需求,具体步骤如下:
1. 生成实体文件
视图文件:用字符串模板生成
.cshtml内容,保存到项目的Views/[ControllerName]/[ActionName].cshtml路径下(符合默认视图引擎的查找规则)。示例:@{ ViewData["Title"] = "动态页面"; } <h1>动态生成的视图</h1> <p>这是通过文本模板生成的实体视图文件</p>直接将内容写入对应路径即可,默认视图引擎会自动识别。
控制器/页面模型文件:生成C#代码模板,比如基础控制器类:
using Microsoft.AspNetCore.Mvc; namespace YourAppNamespace.Controllers { public class DynamicDemoController : Controller { public IActionResult Index() { return View(); } } }将代码保存到
Controllers/DynamicDemoController.cs(或自定义目录)。
2. 动态编译并加载控制器程序集
新增的控制器代码不会自动被框架识别,需用Roslyn动态编译代码并将生成的程序集注册到应用中:
using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CSharp; using Microsoft.AspNetCore.Mvc.ApplicationParts; using System.Reflection; using System.IO; // 读取生成的控制器代码文件内容 var controllerCode = File.ReadAllText("Controllers/DynamicDemoController.cs"); // 配置编译参数,添加必要依赖引用 var compilation = CSharpCompilation.Create("DynamicControllersAssembly") .WithOptions(new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary)) .AddReferences(MetadataReference.CreateFromFile(typeof(Controller).Assembly.Location)) .AddReferences(MetadataReference.CreateFromFile(typeof(IActionResult).Assembly.Location)) .AddReferences(MetadataReference.CreateFromFile(typeof(Program).Assembly.Location)) // 引用当前应用程序集 .AddSyntaxTrees(CSharpSyntaxTree.ParseText(controllerCode)); // 编译生成程序集 using var ms = new MemoryStream(); var emitResult = compilation.Emit(ms); if (emitResult.Success) { ms.Seek(0, SeekOrigin.Begin); // 加载编译后的程序集 var assembly = AssemblyLoadContext.Default.LoadFromStream(ms); // 将程序集添加到ApplicationPart,让MVC框架发现新控制器 var part = new AssemblyPart(assembly); _applicationPartManager.ApplicationParts.Add(part); // 触发控制器特征重新加载(需注入IControllerFeatureProvider和ApplicationPartManager) var controllerFeature = new ControllerFeature(); _controllerFeatureProvider.PopulateFeature(controllerFeature, _applicationPartManager); }
3. 验证访问
完成上述步骤后,访问/DynamicDemo/Index即可触发新创建的控制器Action,并渲染对应的动态视图。
注意事项
- 权限问题:应用进程需要有写入项目目录和编译代码的权限,生产环境需谨慎配置。
- 依赖引用:编译时要确保添加所有必要的NuGet包引用(如
Microsoft.AspNetCore.Mvc、System.Runtime等),否则会编译失败。 - 性能与安全:运行时编译会带来一定性能开销,且动态生成的代码需做好安全校验,避免注入风险。
- 缓存处理:若多次生成同名控制器,需清理旧的编译缓存或使用唯一程序集名称,避免冲突。
内容的提问来源于stack exchange,提问作者Dev Looper
相关产品推荐
相关产品推荐

