Views in separate assemblies in ASP.NET MVC
Essentially this is the same issue as people had with WebForms and trying to compile their UserControl ASCX files into a DLL. I found this http://www.codeproject.com/KB/aspnet/ASP2UserControlLibrary.aspx that might work for you too.
Is it possible to access MVC Views located in another project?
MVC does not compile views into DLL's, but instead references them as files from the root of your site directory. The location, by convention is ~/Views and a search path is followed. This is more or less hard coded into the default view engines.
Because Views are files, when you break them into a separate project, they won't exist in your primary web application project. Thus, the view engine can't find them. When you compile the app, any projects referenced will only copy the DLL's (and potentially a few other things, like pdb's, etc.)
Now, there are ways to work around this, but to be honest, they're usually more trouble than they're worth. You can look into "Portable Areas" in the mvc contrib project, but these are not well supported and there's been talk of replacing them with NuGet packaging.
You can also follow @mo.esmp's advice, and create a custom view engine, but you'll still need to figure out ways to copy the Views somewhere the site can access them upon build and/or deploy.
My suggestion would be to NOT break out projects in the manner you describe. I don't see any value in it. If your project becomes so large, I would instead separate your code into areas, and keep all your area code and data together.
What value is there in separating items that are clearly dependent upon each other into separate assemblies who's only purpose is to collect things based on their purpose? I see some value in separating models into their own project, since models can be used by more than one assembly. Controllers and views, however, are only ever used by the MVC primary site.
ASP.NET MVC 6: view components in a separate assembly
Update 2017-03-09
Things have changed a bit in Visual Studio 2017 using MS Build. Luckily it's much simpler. Here's how to get this to work:
In the external assembly, add this to the csproj file:
<ItemGroup>
<EmbeddedResource Include="Views/**/*.cshtml" />
</ItemGroup>
In the main web project, add this NuGet package:Microsoft.Extensions.FileProviders.Embedded
Then in Startup, add the external assembly to the list of File Providers:
services.Configure<RazorViewEngineOptions>(options =>
{
options.FileProviders.Add(new EmbeddedFileProvider(
typeof(SampleClassInAssembly).Assembly
# Prior to .Net Standard 2.0
# typeof(SampleClassInAssembly).GetTypeInfo().Assembly
));
});
I'll leave the original answer below for now, in case people are still trying to get this to work with older versions of .Net Core and project.json
.
================================================================
Here are the steps to make this work.
- Make sure your view structure in the components assembly is the same as your web project. Note that there was a mistake in the screenshot that I posted along with my question.
Register
CompositeFileProvider
inStartup.cs
of the web project:services.Configure<RazorViewEngineOptions>(options =>
{
options.FileProvider = new CompositeFileProvider(
new EmbeddedFileProvider(
typeof(BookOfTheMonthViewComponent).GetTypeInfo().Assembly,
"BookStore.Components"
),
options.FileProvider
);
});
Both CompositeFileProvider
and EmbeddedFileProvider
are new, so you'll need to get these from the aspnetvnext
NuGet feed. I did this by adding this source:
Add the dependencies in project.json
:
"Microsoft.AspNet.FileProviders.Composite": "1.0.0-*",
"Microsoft.AspNet.FileProviders.Embedded": "1.0.0-*",
Lastly, add this to the project.json
of the Components
assembly:
"resource": "Views/**"
That should be enough to get this working.
Here is a working demo:
https://github.com/johnnyoshika/mvc6-view-components/tree/master
This answer was formulated from this discussion here: https://github.com/aspnet/Mvc/issues/3750
Update 2016-01-15
There is currently one painful problem with external view components. Any changes you make to the view cshtml file does not automatically get recompiled. Even a forced Visual Studio clean and rebuild doesn't do it. You need to change a .cs file in the components assembly in order to trigger a view recompilation, but it looks like this is something that will be corrected in the future. The reason for this problem is explained here: https://github.com/aspnet/Mvc/issues/3750#issuecomment-171765303
Rendering Views from external assemblies in .NET 6 web app
So at least for .NET 6 you don't have to do anything special. Just reference your Razor Class Library and you have access to it. Nothing in the Startup (now Program). I did have to structure the project in the typical 'Controllers'/'Views' folder structure, but my calling application finds the controllers and views.
Rendering Views from external assemblies in MVC6
To load views from a separate assembly, you need EmbeddedFileProvider
and CompositeFileProvider
. I provide more information on how to use these here: https://stackoverflow.com/a/34366119/188740
Executing mvc views in a separate appdomain
I don't think moving to a separate appdomain is necessarily going to help you. Your best bet would be to precompile the views and then deploy them to your hosting environment.
More info on precompilation can be found here: http://sparkviewengine.com/documentation/precompiling
asp.net mvc loading views from separate assembly
You could write a custom VirtualPathProvider.
Related Topics
A Call to Pinvoke Function '[...]' Has Unbalanced the Stack
How Does the Ternary Operator Work
ASP.NET MVC 2 - Bind a Model's Property to a Different Named Value
Stopwatch VS. Using System.Datetime.Now for Timing Events
Is There Any Benefit to This Switch/Pattern Matching Idea
What Is the Simplest Way to Get Indented Xml with Line Breaks from Xmldocument
How to Use the Paint Event to Draw Shapes at Mouse Coordinates
Sending Arguments to Background Worker
C# Use System.Type as Generic Parameter
Remove HTML Tags from String Including &Nbsp in C#
Is Shifting Bits Faster Than Multiplying and Dividing in Java? .Net
Predefined Type 'System.Valuetuple'2' Is Not Defined or Imported
No Overflow Exception for Int in C#
How to Read and Write from the Serial Port