移花接木:借助 IViewLocationExpander 更换 ASP.NET Core View Component 视图路径
端午节在家将一个 asp.net 项目向 asp.net core 迁移时遇到了一个问题,用 view component 取代 Html.RenderAction 之后,运行时 view component 找不到视图文件。
System.InvalidOperationException: The view 'Components/AggSitePostList/PostList' was not found. The following locations were searched:
/Views/AggSite/Components/AggSitePostList/PostList.cshtml
/Views/Shared/Components/AggSitePostList/PostList.cshtml
/Pages/Shared/Components/AggSitePostList/PostList.cshtml
at Microsoft.AspNetCore.Mvc.ViewEngines.ViewEngineResult.EnsureSuccessful(IEnumerable`1 originalLocations)
at Microsoft.AspNetCore.Mvc.ViewComponents.ViewViewComponentResult.ExecuteAsync(ViewComponentContext context)
at Microsoft.AspNetCore.Mvc.ViewComponents.DefaultViewComponentInvoker.InvokeAsync(ViewComponentContext context)
原先用的是 Html.RenderAction ,视图都放在 Controller 对应的视图路径,对于 AggSiteController ,Html.RenderAction 的视图都放在 /Views/AggSite/ 文件夹中,换成 view component 之后,在 AggSiteController 中运行的 view component 却把 /Views/AggSite/ 置之度外,不把这个路径列为视图文件查找范围。由于视图文件比较多,一个一个创建文件夹并移动视图文件比较麻烦,view compoent 这种不够大度的特性让迁移进程受阻。
有没有什么方法可以让将 /Views/AggSite/ 纳入 view component 搜索视图的范围,让其变得更加宽容呢?
网上搜索后得知原来 ASP.NET Core 料事如神,早已料到这种情况,通过 IViewLocationExpander 提供了对应的扩展能力。
对于这里遇到的问题,只需实现 IViewLocationExpander 接口,在 ExpandViewLocations 方法中添加新的视图路径。
public class ComponentViewLocationExpander : IViewLocationExpander
{
public IEnumerable<string> ExpandViewLocations(ViewLocationExpanderContext context, IEnumerable<string> viewLocations)
{
if (context.ControllerName + "Controller" == nameof(AggSiteController)
&& viewLocations.Any(l=>l.Contains("Components/")))
{
var vcLocation = "/Views/AggSite/{0}" + RazorViewEngine.ViewExtension;
viewLocations.ToList().Add(vcLocation);
return viewLocations;
} return viewLocations;
} public void PopulateValues(ViewLocationExpanderContext context) { }
}
然后在 Startup.ConfigureServices 在注册一下
services.Configure<RazorViewEngineOptions>(o =>
{
o.ViewLocationExpanders.Add(new ComponentViewLocationExpander());
});
原以为这种临时铺路的变通方法可以轻松搞定问题,但实际运行时发现问题依旧,此路不通。
被迫在 ComponentViewLocationExpander 中埋点排查问题,埋点日志打印出来后立马发现了其中的蹊跷。
ViewName: Components/AggSitePostList/PostList
viewLocations: /Views/{}/{}.cshtml;/Views/Shared/{}.cshtml;/Pages/Shared/{}.cshtml
原来 view component 的路径信息包含在 ViewName 中,并没有包含在 viewLocations 中,难怪之前的临时铺路不管用。
ViewName 中竟然包含视图文件的路径信息,这种偷懒、投机取巧造成的名不符实,很容易误导人。
知道了问题的真正原因后解决起来就不难了。临时铺路行不通,移花接木任我行,直接修改 ViewName 生成新的 viewLocations 即可。
public class ComponentViewLocationExpander : IViewLocationExpander
{
public IEnumerable<string> ExpandViewLocations(ViewLocationExpanderContext context, IEnumerable<string> viewLocations)
{
if (context.ControllerName + "Controller" == nameof(AggSiteController)
&& context.ViewName.Contains("Components/"))
{
var viewName = context.ViewName.Substring(context.ViewName.LastIndexOf("/") + );
return new string[] { "/Views/AggSite/" + viewName + RazorViewEngine.ViewExtension };
} return viewLocations;
} public void PopulateValues(ViewLocationExpanderContext context) { }
}
移花接木:借助 IViewLocationExpander 更换 ASP.NET Core View Component 视图路径的更多相关文章
- ASP.NET Core Razor 布局视图 - ASP.NET Core 基础教程 - 简单教程,简单编程
原文:ASP.NET Core Razor 布局视图 - ASP.NET Core 基础教程 - 简单教程,简单编程 ASP.NET Core Razor 布局视图 上一章节中我们学习了如何使用 EF ...
- 在Asp.Net Core中取得物理路径
在Asp.Net Core中取得物理路径: 从ASP.NET Core RC2开始,可以通过注入 IHostingEnvironment 服务对象来取得Web根目录和内容根目录的物理路径,如下所示: ...
- ASP.NET Core MVC 之视图组件(View Component)
1.视图组件介绍 视图组件是 ASP.NET Core MVC 的新特性,类似于局部视图,但它更强大.视图组件不使用模型绑定,并且仅依赖于调用它时所提供的数据. 视图组件特点: 呈块状,而不是整个响应 ...
- #asp.net core mvc 的视图注入
View injection is the most useful feature introduced in ASP.NET Core. 1.添加一个FruitsService public cla ...
- [译]ASP.NET Core 2.0 视图引擎
问题 如何在ASP.NET Core 2.0中使用Razor引擎来创建视图? 答案 新建一个空项目,修改Startup.cs,添加MVC服务和请求中间件: public void ConfigureS ...
- [译]ASP.NET Core 2.0 视图组件
问题 如何在ASP.NET Core 2.0中使用视图组件? 答案 新建一个空项目,修改Startup类并添加MVC服务和中间件: public void ConfigureServices(ISer ...
- ASP.NET Core 入门教程 7、ASP.NET Core MVC 分部视图入门
一.前言 1.本教程主要内容 ASP.NET Core MVC (Razor)分部视图简介 ASP.NET Core MVC (Razor)分部视图基础教程 ASP.NET Core MVC (Raz ...
- ASP.NET Core MVC 之视图(Views)
ASP.NET Core MVC 控制器可以使用视图返回格式化的结果. 1.什么是视图 在 MVC 中,视图封装了用户与应用交互呈现细节.视图是具有生成要发送到客户端内容的,包含嵌入代码的HTML模板 ...
- ASP.NET Core 入门笔记8,ASP.NET Core MVC 分部视图入门
一.前言 1.本教程主要内容 ASP.NET Core MVC (Razor)分部视图简介 ASP.NET Core MVC (Razor)分部视图基础教程 ASP.NET Core MVC (Raz ...
随机推荐
- iOS开发Quartz2D之八:图形上下文状态栈
#import "DrawView.h" @implementation DrawView - (void)drawRect:(CGRect)rect { // Drawing c ...
- [Now] Configure secrets and environment variables with Zeit’s Now
Often your project will require some secret keys or tokens - for instance, API keys or database auth ...
- [React] Test friendly approach
Add functional function such as change state, this should have tests covered. For example, in a comp ...
- Android的NDK开发(1)————Android JNI简介与调用流程
1.JNI简介 JNI全称为Java Native Interface(Java本地调用).从Java1.1开始,JNI成为java平台的一部分,它允许Java代码和其他语言写的代码(如C&C ...
- android WebView总 结
浏览器控件是每个开发环境都具备的,这为马甲神功提供了用武之地,windows的有webbrowser,android和ios都有webview.只是其引擎不同,相对于微软的webbrowser,and ...
- 【hdu 2176】取(m堆)石子游戏
Time Limit: 3000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Total Submission(s) ...
- bootstrap, boosting, bagging
介绍boosting算法的资源: 视频讲义.介绍boosting算法,主要介绍AdaBoosing http://videolectures.net/mlss05us_schapire_b/ 在这个站 ...
- 输入框改变placeholder字体颜色
::-webkit-input-placeholder { color: red;}:-moz-placeholder { color: red;}::-moz-placeholder{color ...
- 表达式树Expression
Expression表达式树动态查询 在进行数据列表的查询中,我们通常会使用两种方式进行查询: linq查询 数据库sql语句查询 这样固然可以实现查询,本人之前也都是这么做的,因为查询的条件很少.使 ...
- lucene 7.x 排序
一.创建索引 @Test public void indexCreate() throws IOException { //创建分词器 Analyzer analyzer = new Standard ...