Features View Engine is an ASP.NET MVC view engine which enables feature folder support. It resolves view paths using the controller's namespace.
Install using NuGet:
Install-Package FeaturesViewEngine
There is a default view engine - DefaultControllerFeaturesViewEngine. Register this view engine on the application start (usually in Global.asax):
ViewEngines.Engines.Insert(0, new DefaultControllerFeaturesViewEngine());
This view engine will resolve views by the controller's namespace. In these locations:
%feature%/{0}.cshtml
%feature%/Views/{0}.cshtml
%feature%/Views/{1}{0}.cshtml
The %feature% placeholder will match the controller's namespace excluding an assembly name. For example, you have a controller in the namespace - MyAssembly.Web.Features.HomePage and the assembly name is - MyAssembly.Web. Then the %feature% placeholder will be replaced with path - ~/Features/HomePage.
NOTE: This view engine resolves only paths for views which have a controller. You should create a separate view engine for views which are rendered without a controller.
If you have a different convention for view path, then you can create a derived view engine from ControllerFeaturesViewEngine and define your paths. You can user DefaultControllerFeaturesViewEngine as a template:
public sealed class DefaultControllerFeaturesViewEngine : ControllerFeaturesViewEngine
{
public DefaultControllerFeaturesViewEngine()
{
var paths = new[]
{
$"{FeaturePlaceholder}/{{0}}.cshtml",
$"{FeaturePlaceholder}/Views/{{0}}.cshtml",
$"{FeaturePlaceholder}/Views/{{1}}{{0}}.cshtml"
};
ViewLocationFormats = paths;
PartialViewLocationFormats = paths;
}
}
FeaturePlaceholder is a constant for %feature%.
Sometimes assembly name doesn't match the default namespace name. Then you should create a derived view engine from ControllerFeaturesViewEngine (see "Custom paths" section) and override NamespacePrefixToRemove method to return your namespace prefix to ignore.
In some cases, it is useful to have a different view path format. For example, in a multisite environment, you might want to have different view paths for the same feature.
Then you can create a derived view engine (see "Custom paths" section) and override FormatViewPath method with your view path resolution logic.