端午节在家将一个 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. 第一次使用docker for windows 遇到的坑

    原文:第一次使用docker for windows 遇到的坑 1. 目前win10安装docker, 不需要安装其他工具,可直接到官网下载 2. 此版本的docker可同时运行Windows con ...

  2. Visual Stdio 环境下使用 GSL (GNU Scientific Library)

    Visual Stdio 环境下使用 GSL (GNU Scientific Library) 经測试.这里的方法不适用于VS2015. * 这篇文章有点过时了.建议从以下网址下载能够在 vs 环境下 ...

  3. php如何实现把多平台文件中所有的行合成一行?

    php如何实现把多平台文件中所有的行合成一行? 一.总结 1.str_replace中的数组替换:str_replace(array("/r","/n",&qu ...

  4. 集群搭建Solr

    Solr集群搭建 SolrCloud需要solr基于zookeeper部署,zookeeper是一个集群管理软件,由于SolrCloud需要由多台服务器组成.由zookeeper来进行协调管理.Zoo ...

  5. 使用jsp,tomcat实现用户登录注册留言的代码

    以下jsp中,未使用样式表对网页进行排版和表单的验证(每个jsp的表单填写的时候应该进行空值与空格的验证,防止提交时出错) 所有错误,链接到error.jsp <%@ page language ...

  6. Java泛型解析(02):通配符限定

    Java泛型解析(02):通配符限定      考虑一个这种场景.计算数组中的最大元素. [code01] public class ArrayUtil { public static <T&g ...

  7. Windows消息:WM_USER与WM_APP的区别

    Windows消息范围及意义 #define WM_USER 0x0400 #define WM_APP 0x8000 0到WM_USER-1 Messages reserved for use by ...

  8. Delphi中预编译指令

    本文转自 http://www.cnblogs.com/JackSun/archive/2010/12/20/1911250.html <Delphi下深入Windows核心编程>(附录A ...

  9. Java 开源博客——B3log Solo 0.6.5 正式版发布了!

    Java 开源博客 -- B3log Solo 0.6.5 正式版发布了!欢迎大家下载. 该版本主要是改善细节体验,也是 B3log Solo 的最后一个大版本. 这个版本发布后,B3log Solo ...

  10. 机器学习编程接口(api)设计(oop 设计)

    fit: 对于 kmeans 来说,fit 的过程,就是训练,自然所需的参数,主要是数据集和聚类中心数, 1. classification(分类) def train(train_images, t ...