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

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

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?

Upvotes: 8

Views: 3184

Answers (2)

Lion
Lion

Reputation: 17879

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.

enter image description here

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.

enter image description here

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

enter image description here enter image description here

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:

enter image description here

Upvotes: 2

isaeid
isaeid

Reputation: 553

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

Upvotes: 0

Related Questions