【问题标题】:ASP.NET Core ViewLocationExpander can not find view in other assemblyASP.NET Core ViewLocationExpander 在其他程序集中找不到视图
【发布时间】:2017-09-23 13:55:50
【问题描述】:

我有以下解决方案:

src
   /Web
   /Web.Admin
        /Controller
          /TestControllr.cs
        /Views
            /Test
               /Index.cshtml

我将应用程序部分用于单独的我的应用程序部分:

public class Startup
{
    public void ConfigureServices(IServiceCollection services)
    {
        var adminAssembly = Assembly.Load(new AssemblyName("Web.Admin"));

        services.AddMvc().AddApplicationPart(adminAssembly);

        services.Configure<RazorViewEngineOptions>(options =>
        {
           options.ViewLocationExpanders.Add(new AdminViewLocationExpander());

        });
    }
}

并创建一个名为 AdminViewLocationExpander 的 ViewLocationExpander:

public class AdminViewLocationExpander : IViewLocationExpander
{
    public void PopulateValues(ViewLocationExpanderContext context)
    {
    }

    public IEnumerable<string> ExpandViewLocations(ViewLocationExpanderContext context, IEnumerable<string> viewLocations)
    {
        const string adminAssembly = "Web.Admin";

        var adminViewsLocations = new []
        {
            $"/{adminAssembly}/Views/{{1}}/{{0}}.cshtml",
            $"/{adminAssembly}/Views/Shared/{{0}}.cshtml"
        };

        viewLocations = adminViewsLocations.Concat(viewLocations);

        return viewLocations;
    }
}

当我使用这个 URL localhost:6046/Test/Index 运行应用程序时,得到以下信息:

 InvalidOperationException: The view 'Index' was not found. The following 
 locations were searched:
 /Web.Admin/Views/Test/Index.cshtml
 /Web.Admin/Views/Shared/Index.cshtml
 /Views/Test/Index.cshtml
 /Views/Shared/Index.cshtml

我该如何解决这个问题?

【问题讨论】:

  • 你的项目被命名为“App.Web.Admin”而不是“Web.Admin”所以adminAssembly变量应该设置为App.Web.Admin,对吧?
  • @NickGeorge 不,我编辑问题

标签: c# asp.net-mvc razor asp.net-core


【解决方案1】:

在我的项目中,我将视图作为嵌入资源保存在单独的类库项目/程序集中,打包为 nuget。例如here is one project with embedded views

我不需要自定义 IViewLocationExpander 来查找它们。相反,我创建了一个这样的扩展方法:

public static RazorViewEngineOptions AddCloudscribeSimpleContentBootstrap3Views(this RazorViewEngineOptions options)
{
    options.FileProviders.Add(new EmbeddedFileProvider(
                typeof(Bootstrap3).GetTypeInfo().Assembly,
                "cloudscribe.SimpleContent.Web.Views.Bootstrap3"
          ));

    return options;
} 

然后在主应用程序的启动中,我像这样添加它们:

services.AddMvc()
.AddRazorOptions(options =>
{
    options.AddCloudscribeSimpleContentBootstrap3Views();


});

在我的带有嵌入式视图的类库中,我只是将它们放在 Views 文件夹中,而在我的 .csproj 文件中,我将它们设为嵌入式资源,如下所示:

<ItemGroup>
<EmbeddedResource Include="Views\**" Exclude="bin\**;obj\**;**\*.xproj;packages\**;@(EmbeddedResource)" />
</ItemGroup>

它们的工作方式与它们在磁盘上的工作方式相同,如果我想覆盖/自定义一个视图,我可以在本地复制它,并且将自动使用本地视图而不是嵌入的视图。

【讨论】:

  • Razor 编译任务(.csproj 中的标记 &lt;MvcRazorCompileOnPublish&gt;)是否考虑了这些嵌入视图?
  • 不,我不这么认为。但我认为 2.1 版本的工作正在进行中,这将使在类库中拥有预编译视图变得更加容易。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-03-18
  • 2018-06-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多