IRazorViewEngine.FindView 与 GetView 找不到视图

Kai*_*ite 5 razorengine asp.net-core-mvc asp.net-core

在我的 asp.net core 项目中,我尝试使用以下方法查找 Razor 视图:

private IView FindView(ActionContext actionContext, string viewName)
{
    var getViewResult = _viewEngine.GetView(executingFilePath: null, 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);
}
Run Code Online (Sandbox Code Playgroud)

在哪里

viewName = "Views/Email/ResetPassword.cshtml"
Run Code Online (Sandbox Code Playgroud)

_viewEngineIRazorViewEngine但没有找到任何。

我的项目结构:

项目结构

IView.FindView方法是从 Business 调用的。

我还有另一个项目,它具有项目结构并使用相同的方法来检索视图,更重要的是,它找到了这个视图,但它使用 netcoreapp2.2,而我当前的项目使用 netcoreapp3.1 (Microsoft.AspNetCore.Mvc .Razor 版本相同 - 2.2.0)。

为什么这个方法找不到.net core 3.1上的视图?


更新

两个项目都会将此 Views 文件夹复制到Api\bin\Debug\netcoreapp{version}构建时的文件夹中。

Rob*_*obC 1

虽然我是在 Core 3.1 中从头开始构建的,并且没有从早期版本升级,但我遇到了同样的问题。我通过执行以下操作使事情正常进行:

我创建了一个实现IWebHostEnvironment(我称之为我的DummyWebHostEnvironment.cs)。我将接口的除一个属性之外的所有属性都保留为默认实现;对于该属性,我使用了包含视图的项目的名称。(为了简洁起见,我只是将其硬编码到下面的示例中;显然有更灵活的方法来获取它。)

 public class DummyWebHostEnvironment : IWebHostEnvironment
    {
        public IFileProvider WebRootFileProvider { get => throw new System.NotImplementedException(); set => throw new System.NotImplementedException(); }
        public string WebRootPath { get => throw new System.NotImplementedException(); set => throw new System.NotImplementedException(); }
        public string ApplicationName { get => "TheProjectContainingMyViews.RazorClassLibrary"; set => throw new System.NotImplementedException(); }
        public IFileProvider ContentRootFileProvider { get => throw new System.NotImplementedException(); set => throw new System.NotImplementedException(); }
        public string ContentRootPath { get => throw new System.NotImplementedException(); set => throw new System.NotImplementedException(); }
        public string EnvironmentName { get => throw new System.NotImplementedException(); set => throw new System.NotImplementedException(); }
}
Run Code Online (Sandbox Code Playgroud)

注意:从上面的代码可以明显看出,包含视图的项目是一个 RazorClassLibrary。(我使用这个这个作为让 RazorViewEngine 在控制台应用程序中工作的指南。)

我有上面的实现,我将它与其他一些好东西一起添加到我的服务集合中:

private static RazorViewToStringRenderer GetRenderer()
        {
            var services = new ServiceCollection();
            var applicationEnvironment = PlatformServices.Default.Application;
            services.AddSingleton(applicationEnvironment);

            var appDirectory = Directory.GetCurrentDirectory();
    
            var environment = new DummyWebHostEnvironment();
            services.AddSingleton<IWebHostEnvironment>(environment);

            services.AddSingleton<ObjectPoolProvider, DefaultObjectPoolProvider>();

            var diagnosticSource = new DiagnosticListener("Microsoft.AspNetCore");
            services.AddSingleton<DiagnosticSource>(diagnosticSource);
            services.AddSingleton<DiagnosticListener>(diagnosticSource);

            services.AddLogging();
            services.AddMvc();
            services.AddSingleton<RazorViewToStringRenderer>();
            var provider = services.BuildServiceProvider();
            return provider.GetRequiredService<RazorViewToStringRenderer>();
        }
Run Code Online (Sandbox Code Playgroud)

注意:请参阅上面第一个链接的代码RazorViewToStringRenderer。这是界面:

public interface IRazorViewToStringRenderer
    {
        Task<string> RenderViewToStringAsync<TModel>(string viewName, TModel model);
    }
Run Code Online (Sandbox Code Playgroud)

然后,在 中Program.cs,我可以做这样的事情:

static async Task Main(string[] args)
        {
            var dto = BuildDto();
            var renderer = GetRenderer();

            var renderedString = await renderer.RenderViewToStringAsync("Views/Path/To/Some.cshtml", dto);
// ...

        }
Run Code Online (Sandbox Code Playgroud)