Рендеринг нескольких страниц Razor в HTML - PullRequest
1 голос
/ 24 октября 2019

У меня есть приложение, которое использует Markdown в Razor Pages (скомпилировано с использованием пользовательского TagHelper) для отображения статического содержимого. Имеется около 300 страниц.

Я пытаюсь отобразить эти страницы Razor в html, чтобы можно было проиндексировать содержимое с помощью Lucene.net, чтобы обеспечить полнотекстовый поиск.

Мне удалось создать некоторый код (см. Ниже), который работает , но добавляет предварительно визуализированный контент всякий раз, когда отображаются следующие страницы. То есть, когда я отображаю первую страницу, она работает отлично, но когда я отображаю другую страницу, содержимое первой страницы также включается, и когда я отображаю третью страницу, включаются первые две страницы.

У меня естьпопытался создать зависимости вручную в методе, и я попытался создать новый экземпляр этого класса для каждой страницы, но всегда с тем же результатом.

Чего мне не хватает?

public class RazorPageRenderer
{
    private readonly IRazorViewEngine razorViewEngine;
    private readonly ITempDataProvider tempDataProvider;
    private readonly IHttpContextAccessor httpContextAccessor;
    private readonly IActionContextAccessor actionContextAccessor;
    private readonly IRazorPageActivator razorPageActivator;
    private readonly ILogger logger;

    public RazorPageRenderer(
        IRazorViewEngine razorViewEngine,
        ITempDataProvider tempDataProvider,
        IHttpContextAccessor httpContextAccessor,
        IActionContextAccessor actionContextAccessor,
        IRazorPageActivator razorPageActivator,
        ILogger<RazorPageRenderer> logger)
    {
        this.razorViewEngine = razorViewEngine;
        this.tempDataProvider = tempDataProvider;
        this.httpContextAccessor = httpContextAccessor;
        this.actionContextAccessor = actionContextAccessor;
        this.razorPageActivator = razorPageActivator;
        this.logger = logger;
    }

    public async Task<string> RenderAsync(IRazorPage razorPage) => await RenderAsync<object>(razorPage, null);

    public async Task<string> RenderAsync<T>(IRazorPage razorPage, T model)
    {
        try
        {
            var viewDataDictionary = CreateViewDataDictionary(razorPage.GetType(), model);

            await using var writer = new StringWriter();
            var view = new RazorView(
                razorViewEngine,
                razorPageActivator,
                Array.Empty<IRazorPage>(),
                razorPage,
                HtmlEncoder.Default,
                new DiagnosticListener(nameof(RazorPageRenderer)));

            var viewContext = new ViewContext(
                actionContextAccessor.ActionContext,
                view,
                viewDataDictionary,
                new TempDataDictionary(
                    httpContextAccessor.HttpContext,
                    tempDataProvider),
                writer,
                new HtmlHelperOptions());

            if (razorPage is Page page)
            {
                page.PageContext = new PageContext(actionContextAccessor.ActionContext)
                {
                    ViewData = viewContext.ViewData
                };
            }

            razorPage.ViewContext = viewContext;

            razorPageActivator.Activate(razorPage, viewContext);

            await razorPage.ExecuteAsync();

            return writer.ToString();
        }
        catch (Exception exception)
        {
            logger.LogError(
                "An exception occured while rendering page: {Page}. Exception: {Exception}", 
                razorPage.Path, 
                exception);
        }
        return null;
    }

    private static ViewDataDictionary CreateViewDataDictionary(Type pageType, object model)
    {
        var dictionaryType = typeof(ViewDataDictionary<>)
            .MakeGenericType(pageType);
        var ctor = dictionaryType.GetConstructor(new[]
            {typeof(IModelMetadataProvider), typeof(ModelStateDictionary)});
        var viewDataDictionary = (ViewDataDictionary)ctor?.Invoke(
            new object[] {new EmptyModelMetadataProvider(), new ModelStateDictionary()});
        if (model != null && viewDataDictionary != null)
        {
            viewDataDictionary.Model = model;
        }
        return viewDataDictionary;
    }
}
...