Tachyon
Tachyon

Reputation: 2411

The partial view was not found

Issue

I am currently busy building an email engine that uses the Razor templating system to provide the email templates. I posted this question yesterday which I solved.

Now the problem seems to be that when I include a partial view inside of my view it cannot be found. I am trying to include the partial view inside of my view as follows:

@await Html.PartialAsync("~/Views/Shared/EmailButton.cshtml", new EmailButtonViewModel("Confirm Account", "https://google.com"))

I have tried removing the ~ with no effect, I have used reflection to get the entire path to the partial view and passed that onto the PartialAsync and that didn't work either. I have tried adding the entire path to the shared views folder in the startup.cs as follows:

services.Configure<RazorViewEngineOptions>(o =>
{
    var dir = Path.GetDirectoryName(Assembly.GetEntryAssembly().Location);
    o.ViewLocationFormats.Add("~/Views/Shared/{0}" + RazorViewEngine.ViewExtension);
});

In the above code I have tried replacing ~ with dir to specify the entire location to the folder which didn't work either. My email templates are inside of a .NET Core class library and they have all their Build Action set to Content and Copy to output directory to Copy always

I am unsure of what still to try.

You can see the exact error below: Error


Folder Structure

The folder structure of the class library is as follows: Folder structure


Code

My startup.cs looks as follows (removed unnecessary parts for the sake of brevity):

services.AddScoped<IRazorViewToStringRenderer, RazorViewToStringRenderer>();
services.AddScoped<Email>();

services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
services.Configure<RazorViewEngineOptions>(o =>
{
    var dir = Path.GetDirectoryName(Assembly.GetEntryAssembly().Location);
    o.ViewLocationFormats.Add("~/Views/Shared/{0}" + RazorViewEngine.ViewExtension);
});

The code to render the view and convert it to a string is called like this:

await _razorViewToStringRenderer.RenderViewToStringAsync("Views/Emails/NewOrder/NewOrder.cshtml", newOrderModel);

The RenderViewToStringAsync is as follows:

public async Task<string> RenderViewToStringAsync<TModel>(string viewName, TModel model)
{
    var actionContext = GetActionContext();
    var view = FindView(actionContext, viewName);

    using (var output = new StringWriter())
    {
        var viewContext = new ViewContext(
            actionContext,
            view,
            new ViewDataDictionary<TModel>(
                metadataProvider: new EmptyModelMetadataProvider(),
                modelState: new ModelStateDictionary())
            {
                Model = model
            },
            new TempDataDictionary(
                actionContext.HttpContext,
                _tempDataProvider),
            output,
            new HtmlHelperOptions());

        await view.RenderAsync(viewContext);

        return output.ToString();
    }
}

My FindView code is as

private IView FindView(ActionContext actionContext, string viewName)
{
    var dir = Path.GetDirectoryName(Assembly.GetEntryAssembly().Location);
    var getViewResult = _viewEngine.GetView(executingFilePath: dir, viewPath: viewName, isMainPage: true);
    if (getViewResult.Success)
    {
        return getViewResult.View;
    }

    var findViewResult = _viewEngine.FindView(actionContext, viewName, isMainPage: true);
    if (findViewResult.Success)
    {
        return findViewResult.View;
    }

    var searchedLocations = getViewResult.SearchedLocations.Concat(findViewResult.SearchedLocations);
    var errorMessage = string.Join(
        Environment.NewLine,
        new[] {$"Unable to find view '{viewName}'. The following locations were searched:"}.Concat(
            searchedLocations));

    throw new InvalidOperationException(errorMessage);
}

Upvotes: 1

Views: 1803

Answers (1)

Dimitri
Dimitri

Reputation: 1271

Have you tried:

@await Html.PartialAsync("EmailButton", new EmailButtonViewModel("Confirm Account", "https://google.com"))

Upvotes: 1

Related Questions