移花接木:借助 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 ...
随机推荐
- 9个完整android开源app项目
一.photoup 介绍: photoup 是一款开源的相册类app,主要功能是将本地图片提交到facebook上去,虽然他的功能和facebook的远程服务相关,但是本身是可以被当作一款 相册应用的 ...
- Android中常用的优秀开源框架
Android开源框架库分类,挑选出最常用,最实用的开源项目,本篇主要介绍的是优秀开源框架库和项目,UI个性化控件会独立介绍.UI个性化控件 Index Dependency Injections A ...
- 使用oschina的gitserver
1.概要 事实上oschina的gitserver与github的几乎相同.只是既然是中国的gitserver,那么速度应该更快一些吧 2.注冊 链接https://git.oschina.net/, ...
- 【60.97%】【BZOJ 1925】 [Sdoi2010]地精部落
Time Limit: 10 Sec Memory Limit: 64 MB Submit: 1194 Solved: 728 [Submit][Status][Discuss] Descript ...
- [TypeScript] Using ES6 and ESNext with TypeScript
TypeScript is very particular about what is and isn't allowed in a TS file to protect you from commo ...
- JAVA 安装JDK注意事项
在JAVA jdk安装的时候,文件夹名称最好不要有中文,有逗号,有下划线,空格等问题.这样easy出错,比方以下几个安装路径easy出错 java文件夹/jdk1.6_x86/ 这样的就是 ...
- hdu 1292 "下沙野骆驼"ACM夏令营 (递推)
"下沙野骆驼"ACM夏令营 Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/ ...
- 线程基础:JDK1.5+(9)——线程新特性(中)
(接上文<线程基础:JDK1.5+(8)--线程新特性(上)>) 3.工作在多线程环境下的"计数器": 从这个小节開始,我们将以一个"赛跑"的样例. ...
- INT_MIN与溢出
隔了好久没更新了,由于我在学习PL和编译器/解释器的知识. 挺好奇这方面的,由于没有学过相关的课程.所以学起来有点吃力,进展缓慢.所以导致没啥可写的. 今天看到这么一段话: 32位的int型的取值是2 ...
- NSString与int和float的相互转换
NSString *tempA = @"123"; NSString *tempB = @"456"; 1,字符串拼接 NSString *newString ...