My solution consist of 2 projects:
- MyApp.Rest
- MyApp.Core
Core uses Razor templating to generate emails and reports. Rest is a WebAPI only and references Core. Rest has the startup file, where Razor configuration takes place. Core will also be used by other projects in the future.
The problem is I am not able to make the view engine to locate view files even though I have added the output directory as a FileProvider for razor and the template has been copied to the output directory.
Output Directory:
MyApp.Code.dll
MyApp.Rest.dll
RazorTemplates
-> Template1.cshtml
Startup.cs
services.AddMvc()
.AddApplicationPart(typeof(MyApp.Core.RazorViewRenderer).GetTypeInfo().Assembly)
.AddViewLocalization(LanguageViewLocationExpanderFormat.Suffix)
.AddDataAnnotationsLocalization();
services.Configure<RazorViewEngineOptions>(o => {
o.ViewLocationFormats.Add("/RazorTemplates/{0}" + RazorViewEngine.ViewExtension);
o.FileProviders.Add(new PhysicalFileProvider(AppContext.BaseDirectory));
});
RazorViewRenderer.cs:
public async Task<string> RenderAsync<TModel>(string name, TModel model) {
var actionContext = GetDefaultActionContext();
var viewEngineResult = _viewEngine.FindView(actionContext, "Template1", true);
if (!viewEngineResult.Success) {
throw new InvalidOperationException($"View '{name}' cannot be found."); //Craches here.
}
var view = viewEngineResult.View;
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();
}
}
Note: RazorLight is not an option. It does not support Html helpers and it does not support localization at all.