.NET Core如何从ViewLocationExpanderContext获取Controller实例或全名
在.NET Core中通过IViewLocationExpander获取控制器类型实现动态视图位置
没问题,我来帮你把MVC5里的这个逻辑完美迁移到.NET Core的IViewLocationExpander中。核心思路是从ViewLocationExpanderContext里的Action上下文拿到控制器的类型信息,具体步骤和代码如下:
实现自定义IViewLocationExpander
你需要创建一个实现IViewLocationExpander的类,通过ControllerActionDescriptor获取控制器的类型和程序集信息,和你原来MVC5里的逻辑完全对应:
public class CustomAssemblyViewLocationExpander : IViewLocationExpander { // PopulateValues用于缓存需要复用的参数,这里我们暂时不需要,留空即可 public void PopulateValues(ViewLocationExpanderContext context) { } public IEnumerable<string> ExpandViewLocations(ViewLocationExpanderContext context, IEnumerable<string> viewLocations) { // 确保当前Action是控制器的Action,拿到ControllerActionDescriptor if (context.ActionContext.ActionDescriptor is not ControllerActionDescriptor controllerActionDescriptor) { return viewLocations; } // 获取控制器的实际类型,对应你原来的controllerContext.Controller.GetType() Type controllerType = controllerActionDescriptor.ControllerTypeInfo.AsType(); // 获取程序集全名,和你MVC5里的controllerAssemblyName完全一致 string controllerAssemblyName = controllerType.Assembly.FullName; // 这里根据你的业务需求构造自定义视图位置,下面是示例,你可以替换成自己的路径规则 var customViewLocations = new List<string> { // 示例:把程序集名称作为视图路径的一部分 $"/Views/{controllerAssemblyName}/{context.ControllerName}/{context.ViewName}.cshtml", $"/Views/{controllerAssemblyName}/Shared/{context.ViewName}.cshtml" }; // 将自定义位置和默认视图位置合并,顺序决定查找优先级(自定义在前,默认在后) return customViewLocations.Concat(viewLocations); } }
注册自定义Expander
在Startup.cs(或者.NET 6+的Program.cs)里,把这个自定义的Expander注册到MVC服务中:
// .NET 6+ Program.cs写法 builder.Services.AddControllersWithViews() .AddViewLocationExpander<CustomAssemblyViewLocationExpander>(); // 老版本Startup.cs的ConfigureServices方法写法 services.AddControllersWithViews() .AddViewLocationExpander<CustomAssemblyViewLocationExpander>();
关键说明
- 核心逻辑对应:.NET Core的
IViewLocationExpander不像MVC5的VirtualPathProviderViewEngine直接提供ControllerContext,但通过ViewLocationExpanderContext.ActionContext.ActionDescriptor可以拿到ControllerActionDescriptor,它包含了控制器的完整类型信息(ControllerTypeInfo),完全能替代你原来的获取方式。 - 类型准确性:
ControllerTypeInfo.AsType()获取的是控制器的实际运行类型,即使你的控制器继承了基类,也能正确拿到子类的类型,和你原来controllerContext.Controller.GetType()的效果完全一致。 - 查找优先级控制:自定义的视图位置放在前面,视图引擎会先查找这些路径,找不到再去默认的视图位置查找,你可以根据需求调整顺序。
内容的提问来源于stack exchange,提问作者Matt
相关产品推荐
相关产品推荐

