Как мне реализовать пользовательский RazorViewEngine для поиска представлений в двух разных расположениях ASP NET Core RazorPages

Как можно переопределить Razor представления? Как я хотел бы сделать: По стандарту все представления хранятся в папке Pages и в зависимости от нужного маршрута при запросе ищется нужная директория от нижнего уровня (например /Pages/Dictionary/Users) до верхнего (до самой папки /Pages). Я хочу, чтобы на одном уровне с папкой Pages была папка OverridePages и при поиске необходимого представления сначала поиск проходил по папке OverridePages/Default (Default может менять на другие директории) по такому же принципу от низа к верху как при поиске в Pages. Если необходимо представление не удалось найти, то поиск делать как по стандарту в папке Pages.

ВАЖНО! Я хочу выбирать именно полноценное представление (в начале представления пишется @page), а не частичное. Идеи с поиском частичного представления в OverridePages/Default не подойдут.

Я пробовал использовать IViewLocationExpander:

public class OverridePageViewLocationExpander : IViewLocationExpander
{
    public IEnumerable<string> ExpandViewLocations(ViewLocationExpanderContext context, IEnumerable<string> viewLocations)
    {
        string rootPageDirectory = OrgFileDirectory.GetOrgDirectory(
            context.ActionContext.HttpContext.Items[ContextItemKey.OrgDirectory]
        );

        var extendedViewLocations = new List<string>(viewLocations);

        extendedViewLocations = extendedViewLocations.Select(location =>
        {
            if (location.Contains("/Pages"))
            {
                return location.Replace("/Pages", $"/OverridePages/{rootPageDirectory}");
            }
            else if (location.Contains("/Views"))
            {
                return location.Replace("/Views", $"/OverrideViews/{rootPageDirectory}");
            }
            else
            {
                return location;
            }
        }).ToList();

        var tmp = extendedViewLocations.Union(viewLocations);

        return extendedViewLocations.Union(viewLocations);
    }

    public void PopulateValues(ViewLocationExpanderContext context) { }

}

в Program подключил OverridePageViewLocationExpander

builder.Services.AddRazorPages();
 
builder.Services.Configure<RazorViewEngineOptions>(options =>
{
    options.ViewLocationExpanders.Add(new OverridePageViewLocationExpander());
});

На выходе получается список:

  • "/OverridePages/Default/{0].cshtml"
  • "/OverridePages/Default/Shared/{0}.cshtml"
  • "/OverrideViews/Default/Shared/[0}.cshtml"
  • "/Pages/{0}.cshtml"
  • "/Pages/Shared/{0}.cshtml"
  • "/Views/Shared/{0}.cshtml"

По сути корень поиска /Pages меняется на /OverridePages/Default (но Default от некоторого условия).

В конечном итоге должно получится своеобразное переопределение страниц Razor. То есть если есть "переопределенная версия" представления в папке /OverridePages/Default то брать его, а иначе взять стандартное (базовое) определение представления.

Хоть файл Index и есть по пути /OverridePages/Default но не берется оттуда представление. Мне кажется нужно каким-то образом реализовать пользовательский RazorViewEngine


Ответы (0 шт):