First a little context. When you call Html.RenderPartial you send the View name, that view will be searched at locations specified by RazorViewEngine.PartialViewLocationFormats:
Html.RenderPartial("Post", item);
When you set the Layout property at Razor page, you can´t just say the name, you need to specify the path. How can I just specify the name?
//Layout = "_Layout.cshtml";
Layout = "_Layout"; //Dont work
I need this because I overrided the RazorViewEngine.MasterLocationFormats.
Currently I am specifying the Master at controller:
return View("Index", "_Layout", model);
This works, but I prefer to do this at View.
There is no direct way to do it,
But we can write an HtmlExtension like "RenderPartial()" which will give complete layout path at runtime.
public static class HtmlExtensions
{
public static string ReadLayoutPath<T>(this HtmlHelper<T> html,string layoutName)
{
string[] layoutLocationFormats = new string[] {
"~/Views/{1}/{0}.cshtml",
"~/Views/Shared/{0}.cshtml"
};
foreach (var item in layoutLocationFormats)
{
var controllerName= html.ViewContext.RouteData.Values["Controller"].ToString();
var resolveLayoutUrl = string.Format(item, layoutName, controllerName);
string fullLayoutPath = HostingEnvironment.IsHosted ? HostingEnvironment.MapPath(resolveLayoutUrl) : System.IO.Path.GetFullPath(resolveLayoutUrl);
if (File.Exists(fullLayoutPath))
return resolveLayoutUrl;
}
throw new Exception("Page not found.");
}
}
In the view we can use it as,
@{
Layout = Html.ReadLayoutPath("_Layout");
}
Can I ask why you are doing this or more specifically why are you returning a layout page from a controller? You are missing the point of master pages it seems.
You can't specify just the "name", you need to specify the path of the layout view so that it can in turn be applied to the view are rendering.
Layout = "~/SomeCustomLocation/SomeFolder/_Layout.cshtml"