Embedded view can not be found in ASP.NET Core MVC

孤者浪人 提交于 2020-01-13 10:55:09

问题


I can't reuse my cshtml files from another assembly. Here's the bare-bone sample:

  • Create an ASP.NET Core Web Application project with default template (using Web-Application, Model-View-Controller), and name it ViewReuse
  • Add a class library called ViewLibrary
  • Add a reference to Microsoft.AspNetCore.All metapackage in ViewLibrary
  • Create a folder called Views, then create another folder called Shared, and inside it create a simple cshtml file called ReusedLayout.cshtml
  • Add EmbeddedResources Include='Views\**\*.cshtml' to csproj of ViewLibrary, to include all views inside the ViewLibrary.dll
  • In ViewReuse project, inside Startup.cs, change configuration of MVC service to services.AddMvc().ConfigureApplicationPartManager(p => { p.ApplicationParts.Add(new AssemblyPart(typeof(ReusedController).Assembly)); });
  • Change About.cshtml to use the layout from ViewLibrary: Layout = "/Views/Shared/ReusedLayout.cshtml"
  • Then run the application, and navigate to /home/about.

For me I encountered this error:

InvalidOperationException: The layout view '/Views/Shared/ReusedLayout.cshtml' could not be located. The following locations were searched: /Views/Shared/ReusedLayout.cshtml

What have I done wrong? How do I solve this issue?


回答1:


Try right-click over the view files and in properties change to embedded resource.




回答2:


I solved it by the following way:

Razor class library project

First I created a solution called RazorDll with a Razor dll library project and deleted everything in it. Now create the MVC structure for the views. For testing purpose, I added a file called _Layout2 there.

Also add an empty Startup class in the project root for assembly detection later:

namespace RazorDll {
    public class Startup {
    }
}

Its important to have all Razor filed embedded! You have two ways of doing this:

Embedd all in the .csproj file properties

If you have a project just for embedding all Razor view, this is the best option since you don't have to edit file propertys for every view by hand. Just right click on the project and choose edit project file, or open the corresponding .csproj file with any text editor and insert the following in <Project>

  <ItemGroup>
    <EmbeddedResource Include="Views\**\*.cshtml">
      <CopyToOutputDirectory>Never</CopyToOutputDirectory>
    </EmbeddedResource>
  </ItemGroup>

Embedd single Razor views by hand

Just right click on a Razor views .cshtml file, choose properties and set the build action to embedded ressource. Required for every view you want to use from another .NET Core assembly.

Consuming MVC project for the Razor class library

Now create the MVC project, called MvcDemo here. This is a normal ASP.NET Core 2.1 MVC project (choosed the LTS here, but should also work with 2.2) that got linked to our Razor dll

To search for Razor views in the Assembly, we add it in Startup.ConfigureServices method:

var viewAssembly = typeof(RazorDll.Startup).GetTypeInfo().Assembly;
var fileProvider = new EmbeddedFileProvider(viewAssembly);
services.Configure<RazorViewEngineOptions>(options => {
    options.FileProviders.Add(fileProvider);
});

Notice the full qualified type in typeof to distinct between the Startup class of the consuming MVC project (which would be loaded without namespace) and the Razor class library.

You're ready to change e.g. _ViewStart.cshtml to consume our test _Layout2 from our Razor class library:

@{
    Layout = "_Layout2";
}

Result of a simple POC demo project:



来源:https://stackoverflow.com/questions/48051478/embedded-view-can-not-be-found-in-asp-net-core-mvc

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!