1

When rendering a RazorPage in ASP.NET Core 2.2 works perfectly fine until I add a partial tag which works fine when I open it in the browser but fails when I call it using RazorPageToStringRenderer with the following error:

InvalidOperationException: The partial view '_EmailButton' was not found. The following locations were searched:
/Views/Home/_EmailButton.cshtml
/Views/Shared/_EmailButton.cshtml
/Pages/Shared/_EmailButton.cshtml

Here's my RazorPageToStringRenderer:

public async Task<string> RenderToStringAsync<T>(string pageName, T model) where T : PageModel
{
    var context = new ActionContext(
        httpContext.HttpContext,
        httpContext.HttpContext.GetRouteData(),
        actionContext.ActionContext.ActionDescriptor
    );

    using (var sw = new StringWriter())
    {
        var result = razorViewEngine.GetPage(null, pageName);

        if (result.Page == null)
            throw new ArgumentNullException($"The page {pageName} cannot be found.");

        var view = new RazorView(razorViewEngine,
            activator,
            new List<IRazorPage>(),
            result.Page,
            HtmlEncoder.Default,
            new DiagnosticListener("ViewRenderService"));

        var viewContext = new ViewContext(
            context,
            view,
            new ViewDataDictionary<T>(new EmptyModelMetadataProvider(), new ModelStateDictionary())
            {
                Model = model
            },
            new TempDataDictionary(
                httpContext.HttpContext,
                tempDataProvider
            ),
            sw,
            new HtmlHelperOptions()
        );
        viewContext.ExecutingFilePath = pageName;

        var page = (Page) result.Page;

        page.PageContext = new PageContext
        {
            ViewData = viewContext.ViewData
        };
        page.ViewContext = viewContext;

        activator.Activate(page, viewContext);
        await page.ExecuteAsync();

        return sw.ToString();
    }
}

The key part of the issue is the fact that my RazorPage is in a RazorClassLibrary and it's path is Areas/Email/Pages/ConfirmEmail.cshtml. I do have a ViewImports.cshtml there too but I don't think it's loading it correctly.

I've tried setting the ExecutingFilePath property of the ViewContext but that didn't make any difference.

Facts: Page: RCL\Areas\Email\Pages\ConfirmEmail.cshtml I render the partial page using this line:

<partial name="_EmailButton" model="Model.ButtonModel"/>

Partial: RCL\Areas\Email\Pages\Shared_EmailButton.cshtml

I've pushed a sample project which reproduces the issue over here: https://github.com/paulcsiki/TestRCLToString.

Paul
  • 42
  • 5
  • 19
  • 1
    Looks like your test repo is gone, I was thinking of seeing if the approach I used in https://stackoverflow.com/questions/62584735/how-to-render-full-razorpage-to-string/62588337#62588337 would work – jmoreno Aug 05 '21 at 17:21

1 Answers1

0

A working workaround is to use the full path to the partial page in the RCL\Areas\Email\Pages\ConfirmEmail.cshtml.

From:

<partial name="_EmailButton" model="Model.ButtonModel"/>

To:

<partial name="/Areas/Email/Pages/Shared/_EmailButton.cshtml" model="Model.ButtonModel"/>
Paul
  • 42
  • 5
  • 19