Reputation: 3390
I'm currently developing a site using ASP.Net MVC3 with Razor. Inside the "View/Shared" folder, I want to add a subfolder called "Partials" where I can place all of my partial views (for the sake of organizing the site better.
I can do this without a problem as long as I always reference the "Partials" folder when calling the views (using Razor):
@Html.Partial("Partials/{ViewName}")
My question is if there is a way to add the "Partials" folder to the list that .Net goes through when searching for a view, this way I can call my view without having to reference the "Partials" folder, like so:
@Html.Partial("{ViewName}")
Thanks for the help!
Upvotes: 56
Views: 46100
Reputation: 13350
If you are doing this in ASP.NET Core, simple go to the Startup class, under ConfigureServices
method, and put
services.AddMvc()
.AddRazorOptions(opt => {
opt.ViewLocationFormats.Add("/Views/{1}/Partials/{0}.cshtml");
opt.ViewLocationFormats.Add("/Views/Shared/Partials/{0}.cshtml");
});
Upvotes: 14
Reputation: 3390
Solved this. To add the "Shared/Partials" sub directory I created to the list of locations searched when trying to locate a Partial View in Razor using:
@Html.Partial("{NameOfView}")
First create a view engine with RazorViewEngine as its base class and add your view locations as follows. Again, I wanted to store all of my partial views in a "Partials" subdirectory that I created within the default "Views/Shared" directory created by MVC.
public class RDDBViewEngine : RazorViewEngine
{
private static readonly string[] NewPartialViewFormats =
{
"~/Views/{1}/Partials/{0}.cshtml",
"~/Views/Shared/Partials/{0}.cshtml"
};
public RDDBViewEngine()
{
base.PartialViewLocationFormats = base.PartialViewLocationFormats.Union(NewPartialViewFormats).ToArray();
}
}
Note that {1} in the location format is the Controller name and {0} is the name of the view.
Then add that view engine to the MVC ViewEngines.Engines Collection in the Application_Start() method in your global.asax:
ViewEngines.Engines.Add(new RDDBViewEngine());
Upvotes: 72
Reputation: 1139
I've updated lamarant's excellent answer to include Areas:
public class RDDBViewEngine : RazorViewEngine
{
private static readonly string[] NewPartialViewFormats =
{
"~/Views/{1}/Partials/{0}.cshtml",
"~/Views/Shared/Partials/{0}.cshtml"
};
private static List<string> AreaRegistrations;
public RDDBViewEngine()
{
AreaRegistrations = new List<string>();
BuildAreaRegistrations();
base.PartialViewLocationFormats = base.PartialViewLocationFormats.Union(NewPartialViewFormats).ToArray();
base.PartialViewLocationFormats = base.PartialViewLocationFormats.Union(areaRegistrations).ToArray();
}
private static void BuildAreaRegistrations()
{
string[] areaNames = RouteTable.Routes.OfType<Route>()
.Where(d => d.DataTokens != null && d.DataTokens.ContainsKey("area"))
.Select(r => r.DataTokens["area"].ToString()).ToArray();
foreach (string areaName in areaNames)
{
AreaRegistrations.Add("~/Areas/" + areaName + "/Views/Shared/Partials/{0}.cshtml");
AreaRegistrations.Add("~/Areas/" + areaName + "/Views/{1}/Partials/{0}.cshtml");
}
}
}
Then don't forget to include in your application start:
public class MvcApplication : System.Web.HttpApplication
{
protected void Application_Start()
{
...
ViewEngines.Engines.Add(new RDDBViewEngine());
}
}
Upvotes: 7
Reputation: 656
You can also update the partialview-location-formats of the registered RazorViewEngine. Place the below code in Application_Start in Global.asax.
RazorViewEngine razorEngine = ViewEngines.Engines.OfType<RazorViewEngine>().FirstOrDefault();
if (razorEngine != null)
{
string[] newPartialViewFormats = new[] {
"~/Views/{1}/Partials/{0}.cshtml",
"~/Views/Shared/Partials/{0}.cshtml"
};
razorEngine.PartialViewLocationFormats =
razorEngine.PartialViewLocationFormats.Union(newPartialViewFormats).ToArray();
}
Upvotes: 5
Reputation: 891
It´s nice to custom the view engine, but if you just want to have a subfolder por partials you don´t need that much...
Just use the full path to the partial view, as done for the Layout View:
@Html.Partial("/Views/Shared/Partial/myPartial.cshtml")
Hope it helps someone...
Upvotes: 20
Reputation: 411
Thank you for your answers. This has organized my Shared folder, but why do you create a new type of view engine? I just made a new RazorViewEngine
, set it's PartialViewLocationFormats
and added it to the list of ViewEngines
.
ViewEngines.Engines.Add(new RazorViewEngine
{
PartialViewLocationFormats = new string[]
{
"~/Views/{1}/Partials/{0}.cshtml",
"~/Views/Shared/Partials/{0}.cshtml"
}
});
Upvotes: 31
Reputation: 3037
You can create register your own view engine that derives from whatever view engine your are using (Webforms/Razor) and specify whatever locations you want in the constructor or just add them to the list of already existing locations:
this.PartialViewLocationFormats = viewLocations;
Then in application start you would add your view engine like so:
ViewEngines.Engines.Add(new MyViewEngineWithPartialPath());
Upvotes: 1