找不到部分视图

时间:2019-03-09 10:52:22

标签: c# asp.net-core razor

问题

我目前正忙于构建一个使用Razor模板系统提供电子邮件模板的电子邮件引擎。我昨天发布了此question,并解决了该问题。

现在的问题似乎是,当我在视图中包含局部视图时,找不到该视图。我试图将局部视图包含在我的视图中,如下所示:

@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都设置为ContentCopy to output directory都设置为Copy always

我不确定还有什么尝试。

您可以在下面看到确切的错误: Error


文件夹结构

类库的文件夹结构如下: Folder structure


代码

我的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);
}

1 个答案:

答案 0 :(得分:0)

您尝试过吗:

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