I've been searching for a way to determine the "nesting level" of a view. I've found: Determine view 'nesting level' here on stackoverflow.com. But that only works with RenderAction
and only says if it is a child view or not.
What I would like is that layout has level 0, views rendered in layout (e.g. with @RenderBody()
) has level 1, views rendered in that view (e.g. with @Html.Partial(...)
) has level 2.
For example:
- _Layout.cshtml (0)
- _LoginPartial.cshtml (1)
- Index.cshtml (1)
- DataTable.cshtml (2)
- DataHeader.cshtml (3)
- DataRow.cshtml (3)
- DataTable.cshtml (2)
Do anyone have a solution for this?
After some investigation I found a static class System.Web.WebPages.TemplateStack
that is used when executing views, pushing template on to stack before execution and popping after execution so the size of the stack can be used to determine the level. There is no count variable or any public property/method to get the actual stack. However there is a private method GetStack(HttpContextBase)
.
I solved it by using reflection and a extension method:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.Web.WebPages;
using System.Reflection;
using System.Collections;
namespace Mollwe.Helpers
{
public static class TemplateStackLevelAccessor
{
private static MethodInfo _getStackMethod;
public static int GetTemplateLevel(this HtmlHelper htmlHelper)
{
return GetTemplateLevel(htmlHelper.ViewContext);
}
public static int GetTemplateLevel(this ViewContext viewContext)
{
return GetTemplateLevel(viewContext.HttpContext);
}
public static int GetTemplateLevel(this HttpContextBase httpContext)
{
if (_getStackMethod == null)
{
_getStackMethod = typeof(TemplateStack).GetMethod("GetStack", BindingFlags.NonPublic | BindingFlags.Static);
}
var stack = _getStackMethod.Invoke(null, new object[] { httpContext }) as Stack<ITemplateFile>;
return stack.Count - 1;
}
}
}
Maybe not the best way but it works. As the stack is used within execution of view it will only work in views or in code called from views.
Dependant on System.Web.WebPages.WebPageBase
's implementation of ExecutePageHierarchy()
that is called in derived type System.Web.Mvc.WebViewPage
which is used in RazorView.RenderView(...)
.
For anyone looking to do this in ASP.Net Core, you need to implement your own ViewResultExecutor
. You can intercept all 'ExecuteAsync()' calls, which get nested, allowing one to build their own nesting level.
See here for more details: Hooking into razor page execution for ASP.Net Core
来源:https://stackoverflow.com/questions/13398485/get-nesting-level-of-view-in-asp-net-mvc-4