RazorViewEngine in console app cannot find View
I have the following
- dotnet core 6 console app
- dotnet core 6 Razor Class Libary (with .cshtml)
I'm doing a View Engine RenderAsync() that works just fine in web api. When running in a console app cannot find the template, template is there in the dll.
First question, what is the relative/absolute path to that cshtml? I'm using: @"Templates/Pdf/LevelsEmail.cshtml"
Console App startup
IServiceCollection serviceCollection = new ServiceCollection();
services.AddScoped<ITemplateBuilder, TemplateBuilder>();
var listener = new DiagnosticListener("Microsoft.AspNetCore");
services.AddSingleton(listener);
services.AddSingleton<DiagnosticSource>(listener);
services.AddRazorPages();
// rest of deps
var scope = provider.CreateScope();
await scope.ServiceProvider.GetRequiredService<Runner>().ProcessAsync();
in RCL csproj
<Project Sdk="Microsoft.NET.Sdk.Razor">
<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<AddRazorSupportForMvc>true</AddRazorSupportForMvc>
</PropertyGroup>
<ItemGroup>
<FrameworkReference Include="Microsoft.AspNetCore.App" />
</ItemGroup>
</Project>
Trying to GetView or FindView
var httpContext = new DefaultHttpContext
{
RequestServices = _serviceProvider
};
var actionContext = new ActionContext(httpContext, new RouteData(), new ActionDescriptor());
Searching the ViewEngineResult
var viewResult = _viewEngine.GetView(executingFilePath: viewPath, viewPath: viewPath, isMainPage);
if (getViewResult.Success)
{
return getViewResult;
}
var findViewResult = _viewEngine.FindView(actionContext, viewPath, isMainPage);
if (findViewResult.Success)
{
return findViewResult;
}
Then rendering (this is just an example, problem is at fetching the View)
var viewContext = new ViewContext(actionContext,
viewResult.View,
viewDictionary,
new TempDataDictionary(httpContext, _tempDataProvider),
outputWriter,
new HtmlHelperOptions());
await viewResult.View.RenderAsync(viewContext);
Second question: is this possible to use RazorViewEngine in a console app (not a web app)?
Solution 1:
Found one workaround, it is not the answer to the question, so I will keep it open, but it does the trick for me.
So:
Changed console app to web
<Project Sdk="Microsoft.NET.Sdk">
to
<Project Sdk="Microsoft.NET.Sdk.Web">
Program looks like:
var builder = WebApplication.CreateBuilder();
builder.Configuration.AddJsonFile("appsettings.json", optional: true);
builder.Services.AddModules(builder.Configuration);
var app = builder.Build();
ITemplateService myBuilder = app.Services.GetRequiredService<ITemplateBuilder>();
MyModel email = new MyModel{ Data = InitData() };
string compiled = await myBuilder.RenderAsync(MyModel.Template, email, true);
Mandatory to have on services collection
.AddRazorPages();
rest of the dependencies required in console app DiagnosticListener and DiagnosticSource no longer needed to be explicit injected, web project takes care of that.
For me this is a good solution because this console apps runs in docker containers, I did not tested if this can run in a durable azure function or aws lambda function, I have a feeling is not, but it must to be tested.