因此,在深入研究 aspnetcore 存储库一个小时后,我发现该组件的搜索路径是硬编码的 https://github.com/aspnet/AspNetCore/blob/master/src/Mvc/Mvc.ViewFeatures/src/ViewComponents/ViewViewComponentResult.cs然后与普通视图搜索路径结合。
// {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/Components/Cart/Default.cshtml
Views/Home/Components/Cart/Default.cshtml
Areas/Blog/Views/Shared/Components/Cart/Default.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());
});