asp.net-mvcrazorrazor-3

How to get the Layout value of razor files?


I'm doing some custom infrastructure for auto-generating specific bundles for individual views, and have a case where I need to get the Layout value for each view while iterating them as files.

I've tried var view = new RazorView(new ControllerContext(), actionView.FullName, null, true, null); but this is taking the LayoutPath as an input, and it is indeed resulting in an empty string on the LayoutPath property of the RazorView if I give null for that parameter, so it's not parsing the file for the value.

Could there be any other way to solve this in a similar manner, or would my best/only option be to just parse the text of the raw file (and _ViewStart)?

This is only done once at application start, so the performance is currently not an issue.


Solution

  • Alright, after a lot of source debugging and an epic battle with the internal access modifier, I have a working solution without having to render the whole page. I don't expect anyone else ever having the need for this, but anyway:

    var httpContext = new HttpContextWrapper(new HttpContext(new HttpRequest("", "http://dummyurl", ""), new HttpResponse(new StreamWriter(new MemoryStream()))));
    var page = Activator.CreateInstance(BuildManager.GetCompiledType(ReverseMapPath(actionView.FullName))) as WebViewPage;
    
    page.Context = httpContext;
    page.PushContext(new WebPageContext(), new StreamWriter(new MemoryStream()));
    page.Execute();
    
    var layoutFileFullName = page.Layout;
    
    // If page does not have a Layout defined, search for _ViewStart
    if (string.IsNullOrEmpty(layoutFileFullName))
    {
        page.VirtualPath = ReverseMapPath(actionView.FullName);
        var startpage = StartPage.GetStartPage(page, "_ViewStart", new string[] {"cshtml"});
        startpage.Execute();
        layoutFileFullName = startpage.Layout;
    }
    

    Tada!

    Ps. ReverseMapPath is a any arbitrary function to resolve the relative path of a full file name, see for example Getting relative virtual path from physical path