端午节在家将一个 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 视图路径的更多相关文章

  1. ASP.NET Core Razor 布局视图 - ASP.NET Core 基础教程 - 简单教程,简单编程

    原文:ASP.NET Core Razor 布局视图 - ASP.NET Core 基础教程 - 简单教程,简单编程 ASP.NET Core Razor 布局视图 上一章节中我们学习了如何使用 EF ...

  2. 在Asp.Net Core中取得物理路径

    在Asp.Net Core中取得物理路径: 从ASP.NET Core RC2开始,可以通过注入 IHostingEnvironment 服务对象来取得Web根目录和内容根目录的物理路径,如下所示: ...

  3. ASP.NET Core MVC 之视图组件(View Component)

    1.视图组件介绍 视图组件是 ASP.NET Core MVC 的新特性,类似于局部视图,但它更强大.视图组件不使用模型绑定,并且仅依赖于调用它时所提供的数据. 视图组件特点: 呈块状,而不是整个响应 ...

  4. #asp.net core mvc 的视图注入

    View injection is the most useful feature introduced in ASP.NET Core. 1.添加一个FruitsService public cla ...

  5. [译]ASP.NET Core 2.0 视图引擎

    问题 如何在ASP.NET Core 2.0中使用Razor引擎来创建视图? 答案 新建一个空项目,修改Startup.cs,添加MVC服务和请求中间件: public void ConfigureS ...

  6. [译]ASP.NET Core 2.0 视图组件

    问题 如何在ASP.NET Core 2.0中使用视图组件? 答案 新建一个空项目,修改Startup类并添加MVC服务和中间件: public void ConfigureServices(ISer ...

  7. ASP.NET Core 入门教程 7、ASP.NET Core MVC 分部视图入门

    一.前言 1.本教程主要内容 ASP.NET Core MVC (Razor)分部视图简介 ASP.NET Core MVC (Razor)分部视图基础教程 ASP.NET Core MVC (Raz ...

  8. ASP.NET Core MVC 之视图(Views)

    ASP.NET Core MVC 控制器可以使用视图返回格式化的结果. 1.什么是视图 在 MVC 中,视图封装了用户与应用交互呈现细节.视图是具有生成要发送到客户端内容的,包含嵌入代码的HTML模板 ...

  9. ASP.NET Core 入门笔记8,ASP.NET Core MVC 分部视图入门

    一.前言 1.本教程主要内容 ASP.NET Core MVC (Razor)分部视图简介 ASP.NET Core MVC (Razor)分部视图基础教程 ASP.NET Core MVC (Raz ...

随机推荐

  1. Nutch+Hadoop集群搭建 分类: H3_NUTCH 2015-01-18 10:55 362人阅读 评论(0) 收藏

    转载自:http://www.open-open.com/lib/view/open1328670771405.html 1.Apache Nutch    Apache Nutch是一个用于网络搜索 ...

  2. DI:依赖注入详解

    DI(依赖注入) 依赖注入的理解: 一般写程序的时候service层都需要用到dao层,所以一般都是在service层里面new  dao ,而现在利用依赖注入的方式,直接把dao给了service层 ...

  3. 如何查看一个网页特定效果的js代码(动画效果可js和css)(页面可以看到js的源代码)

    如何查看一个网页特定效果的js代码(动画效果可js和css)(页面可以看到js的源代码) 一.总结 1.动画效果可能是 CSS 实现的,也可能是 JS 实现的. 2.直接Chrome的F12调试即可, ...

  4. oracle 复制表数据,复制表结构

    1.不同用户之间的表数据复制 对于在一个数据库上的两个用户A和B,假如需要把A下表old的数据复制到B下的new,请使用权限足够的用户登入sqlplus:insert into B.new(selec ...

  5. 【翻译自mos文章】当使用原地升级的方法将db升级到11.2.0.4之后,windows注冊表丢失autostart属性

    来源于: Windows Registry Missing Autostart Attribute after In-Place Upgrade of Oracle Database from 11. ...

  6. iOS 通讯录基础

    iOS  6 之后应用訪问通讯录须要获得用户授权,而且仅仅授权一次,即使卸载了之后再安装.也不用再次授权. 开发通讯录应用须要两个框架: 1.ABAddressBook    主要用于提供訪问通讯录中 ...

  7. 孔雀翎----《Programming C# 》中国版 文章4版

    孔雀翎----<Programming C# >中国版 文章4版 页:http://blog.csdn.net/21aspnet/           时间:2007.8.7 电子工业出版 ...

  8. erlang判断模块导出函数问题

    erlang本身提供一个接口,可以用来检查模块是否有导出函数,这个接口是erlang:function_exported/3,但是很多时候这个接口无法正常使用. 下面重现一下这个问题: 1> e ...

  9. 【BZOJ 1030】[JSOI2007]文本生成器

    [题目链接]:http://www.lydsy.com:808/JudgeOnline/problem.php?id=1030 [题意] [题解] /* 先把AC自动机搞出来; 然后利用AC自动机,把 ...

  10. 【BZOJ 1028】[JSOI2007]麻将

    [题目链接]:http://www.lydsy.com/JudgeOnline/problem.php?id=1028 [题意] [题解] /* 枚举新加入的一张牌是哪一张牌; 然后尝试把它加进去; ...