Recently, on a few different projects the opportunity to share views between web sites has arisen. I looked around and found a few different options but the one that stood out the most to me was the NuGet package RazorGenerator.Mvc. This package allows you to compile views into a separate .dll and use them across multiple MVC web projects. However, I did not run across an easy to follow, complete start up guide. In this write up, I’ll lay out the steps to setup RazorGenerator.Mvc as well as some of the pros and cons to this approach.
All screenshots are from Visual Studio 2013.
Step 1: Create an MVC Web Project
Open Visual Studio and create a new project:
Select MVC, change the authentication to whatever you want (I’m going to do No Auth here) and click OK:
Step 2: Add a Second Web Project for Shared Views
If you read the RazorGenerator.Mvc documentation, it will suggest that you add a class library for this next step. I suggest that you add a second MVC project instead. It will give you the solution structure you need, view type ahead, and additional setup you would need to otherwise do out of the box. Remove all of the folders except for Views. Delete all the excess views and the global.asax file until your solution looks similar to this:
Step 3: Add a Reference to the Shared Views Project
Right-click the references in your MVC project, select add reference, and add a reference to your Shared Views project:
Step 4: Add a Reference to RazorGenerator.Mvc
Right click the Shared View project and select ‘Manage NuGet Packages…’. Search for ‘RazorGenerator.Mvc’ online and click install:
When you do this, you’ll see that a new class – RazorGeneratorMvcStart – was added to the App_Start folder.
Step 5: Create a Shared View
Remove the ‘Index.cshtml’ file from the ‘Views > Home’ folder of your MVC project. Add a new ‘Index.cshtml’ view to the ‘Views > Home’ folder of your Shared Views project. Open up the properties window for this new view and in the ‘Custom Tool’ section enter ‘RazorGenerator’:
When you do this, you’ll see that a new class is generated for the Index view:
If you open up this new class, you’ll see the RazorGenerator creates a file similar to how a text template would – the entire view should be represented in this class. Also, if you look at the PageVirtualPathAttribute, you’ll see the mapping that is created to allow your consuming MVC projects to find the view.
Step 6: Running the Application
Once you’ve completed the above steps, you can run the MVC project. Since there is no home index view in the MVC project, you should successfully see the index page from the Shared Views project.
Overriding a Shared View
What if you have an index view in one of your MVC projects that you want to override the shared view? By default, RazorGenerator.Mvc shared views will always override views of the same path/name in consuming MVC projects. In order to prevent this behavior, you need to change the way in which the RazorGenerator is added to the View Engines. In the RazorGeneratorMvcStart.cs file that was added to the Shared Views project, add the RazorGenerator.Mvc engine to the end of the list instead of the start:
This will allow you to override shared views or partial views in consuming MVC projects.
If you do decide to add a Class Library instead of a second MVC project for your shared views, and you receive the error message “Could not precompile the file ‘ViewName.cshtml‘. Ensure that a genrator declaration exists in the cshtml file.” after compiling, you need to add a web.config with the proper MVC assembly bindings. This can be done by copying the web.config from your main MVC project.
Another way to tell that this is an issue, is if your ViewName.cshtml file includes the text “Could not precompile the file… Ensure that a generator declaration exists in the cshtml file.”:
I’ve included the source code for the sample solution below.