Issue
В настоящее время я занят созданием механизма электронной почты, который использует систему шаблонов Razor для предоставления шаблонов электронной почты.Я вчера опубликовал этот вопрос , который я решил.
Теперь проблема заключается в том, что когда я включаю частичное представление в свое представление, оно не может быть найдено.Я пытаюсь включить частичное представление в свое представление следующим образом:
@await Html.PartialAsync("~/Views/Shared/EmailButton.cshtml", new EmailButtonViewModel("Confirm Account", "https://google.com"))
Я попытался удалить ~
без эффекта, я использовал отражение, чтобы получить полный путь к частичному виду ипередал это на PartialAsync
, и это тоже не сработало.Я попытался добавить полный путь к папке общих представлений в startup.cs
следующим образом:
services.Configure<RazorViewEngineOptions>(o =>
{
var dir = Path.GetDirectoryName(Assembly.GetEntryAssembly().Location);
o.ViewLocationFormats.Add("~/Views/Shared/{0}" + RazorViewEngine.ViewExtension);
});
В приведенном выше коде я попытался заменить ~
на dir
, чтобы указать все местоположение дляпапка, которая тоже не работала.Мои шаблоны электронной почты находятся в библиотеке классов .NET Core, и у них все Build Action
установлены на Content
и Copy to output directory
на Copy always
Я не уверен, что еще нужно попробовать.
Ниже приведена точная ошибка: ![Error](https://i.stack.imgur.com/rb7D0.png)
Структура папок
Структура папок библиотеки классов выглядит следующим образом: ![Folder structure](https://i.stack.imgur.com/xUl6K.png)
код
My startup.cs
выглядит следующим образом (ради краткости удалены):
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);
});
Код для визуализации представления и преобразования его в строку называется так:
await _razorViewToStringRenderer.RenderViewToStringAsync("Views/Emails/NewOrder/NewOrder.cshtml", newOrderModel);
RenderViewToStringAsync
выглядит следующим образом:
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();
}
}
Мой FindView
кодкак
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);
}