且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

ASP.NET Core MVC视图组件搜索路径

更新时间:2023-02-16 12:30:30

因此,在一个小时内深入aspnetcore存储库后,我发现该组件的搜索路径为

So after an hour digging into the aspnetcore repository, I found the component's search path is hardcoded and then combined with normal view search paths.

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

然后将此路径发送到视图引擎

This path is then sent into the view engine

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

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

The view engine then produces the full path, using the configurable view paths.

  • 视图/共享/组件/购物车/默认 .cshtml
  • 视图/主页/组件/购物车/默认 .cshtml
  • 区域/博客/视图/共享/组件/购物车/默认 .cshtml
  • Views/Shared/Components/Cart/Default.cshtml
  • Views/Home/Components/Cart/Default.cshtml
  • Areas/Blog/Views/Shared/Components/Cart/Default.cshtml

如果要根据需要将视图组件放置到名为"Components"的根文件夹中,则可以执行以下操作.

If you want to place your view components into a root folder named "Components" as I wanted, you can do something like this.

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);        
});

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

That's kind of ugly in my opinion. But it works.

您也可以这样编写自己的扩展器.

You can also write your own expander like this.

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中

And in Startup.cs

services.Configure<RazorViewEngineOptions>(o =>
{
    o.ViewLocationExpanders.Add(new ComponentViewLocationExpander());   
});