ASP.NET Core MVC 查看组件搜索路径

Posted

技术标签:

【中文标题】ASP.NET Core MVC 查看组件搜索路径【英文标题】:ASP.NET Core MVC View Component search path 【发布时间】:2019-09-07 07:45:34 【问题描述】:

在此处的文档中: https://docs.microsoft.com/en-us/aspnet/core/mvc/views/view-components?view=aspnetcore-2.2

运行时在以下路径中搜索视图:

/Views/Controller Name/Components/View Component Name/View Name
/Views/Shared/Components/View Component Name/View Name
/Pages/Shared/Components/View Component Name/View Name

如何在此处添加另一条路径?

我想将我的视图组件及其各自的控制器放在一个名为 components 的项目文件夹中。

/Components/View Component Name/View Name

我的动机:

我发现我的视图组件有自己的 JS 和 CSS 文件。我将所有 JS 捆绑并最小化在一个 site.min.js 中,并将所有 CSS 捆绑并最小化在它们的 site.min.css 中。 JS 总是类似于$(function() ... ),而 CSS 总是以一种顺序无关紧要的方式编写,因此在不知道顺序的情况下捆绑所有内容不是问题。

其中一些视图组件有 javascripts 可以改变它们在服务器上的状态,例如对控制器操作的 AJAX 调用,该操作返回一些 JSON 或整个视图组件的 html

由于控制器只是一个 C# 类,它们可以位于任何文件夹中,但将具有相关 AJAX 操作的控制器移动到“Views”文件夹感觉很愚蠢。

最后我想要一个像这样的“组件”(不是真正的“视图组件”):

/Components/SomeViewComponent/Default.cshtml
/Components/SomeViewComponent/SomeViewComponentController.cs
/Components/SomeViewComponent/SomeViewComponent.cs
/Components/SomeViewComponent/SomeViewComponent.css
/Components/SomeViewComponent/SomeViewComponent.js
/Components/SomeViewComponent/SomeViewComponent.en.resx
/Components/SomeViewComponent/SomeViewComponent.cs-CZ.resx

【问题讨论】:

【参考方案1】:

您可以向RazorViewEngineOptions 添加其他查看位置格式。例如,要添加满足您要求的路径,您可以使用以下内容:

services
    .AddMvc()
    .AddRazorOptions(o =>
    
        // /Components/View Component Name/View Name.cshtml
        o.ViewLocationFormats.Add("/0.cshtml");
        o.PageViewLocationFormats.Add("/0.cshtml");
    );

如上所示,views(使用控制器和操作时)和 页面视图(使用 Razor 页面时)有不同的属性。还有一个区域属性,但我在此示例中将其省略以使其略短。

这种方法的缺点是视图位置格式不能应用于视图组件。例如,当在Home 中查找Index 视图时,Razor 现在还将查找位于项目根目录的Index.cshtml。这可能没问题,因为它是最后搜索的位置,我希望您不会有任何视图位于项目的根部,但这当然值得关注。

【讨论】:

【参考方案2】:

于是在aspnetcore仓库挖了一个小时后,发现组件的搜索路径是hardcoded,然后结合普通视图搜索路径。

// 0 is the component name, 1 is the view name.
private const string ViewPathFormat = "Components/0/1";

这个路径然后被发送到视图引擎

result = viewEngine.FindView(viewContext, qualifiedViewName, isMainPage: false);

然后,视图引擎使用可配置的视图路径生成完整路径。

Views/Shared/<strong>Components/Cart/Default</strong>.cshtml Views/Home/<strong>Components/Cart/Default</strong>.cshtml Areas/Blog/Views/Shared/<strong>Components/Cart/Default</strong>.cshtml

如果您想按照我的意愿将视图组件放入名为“Components”的根文件夹中,您可以执行以下操作。

services.Configure<RazorViewEngineOptions>(o =>

    // 2 is area, 1 is controller,0 is the action
    // the component's path "Components/ViewComponentName/ViewComponentViewName" is in the action 0
    o.ViewLocationFormats.Add("/0" + RazorViewEngine.ViewExtension);        
);

在我看来,这有点丑陋。但它有效。

你也可以像这样编写自己的扩展器。

namespace TestMvc

    using Microsoft.AspNetCore.Mvc.Razor;
    using System.Collections.Generic;

    public class ComponentViewLocationExpander : IViewLocationExpander
    
        public IEnumerable<string> ExpandViewLocations(ViewLocationExpanderContext context, IEnumerable<string> viewLocations)
        
            // this also feels ugly
            // I could not find another way to detect
            // whether the view name is related to a component
            // but it's somewhat better than adding the path globally
            if (context.ViewName.StartsWith("Components"))
                return new string[]  "/0" + RazorViewEngine.ViewExtension ;

            return viewLocations;
        

        public void PopulateValues(ViewLocationExpanderContext context) 
    

在 Startup.cs 中

services.Configure<RazorViewEngineOptions>(o =>

    o.ViewLocationExpanders.Add(new ComponentViewLocationExpander());   
);

【讨论】:

我遇到了同样的问题,我使用了你的解决方案,但它对区域不起作用,看看我的问题:***.com/questions/66782605/…

以上是关于ASP.NET Core MVC 查看组件搜索路径的主要内容,如果未能解决你的问题,请参考以下文章

使用 Kendo UI Asp.net mvc core 未显示图表组件

ASP.NET Core MVC返回数据配置为json格式化组件为NewtonsoftJson

ASP.NET / MVC 1.0 组件和 Ajax 控件 - 网格 - 日历 - 搜索?

使用标签助手调用控制器,包括来自 asp.net core mvc 中搜索栏的数据

ASP.NET Core MVC,用户登录后限制查看

要在 ASP .NET Core MVC 中查看的 JavaScript 中的对象数组