Copied to clipboard

Flag this post as spam?

This post will be reported to the moderators as potential spam to be looked at


  • Laurence Gillian 597 posts 1216 karma points
    Jul 09, 2013 @ 14:19
    Laurence Gillian
    0

    Razor Layouts - RenderBody() = Unusable Template

    Hello,

    I'm putting together some sites using Razor Layouts and I'm finding the templating engine a little odd/restrictive. So I can only assume, I am doing something wrong.

    _Layout.cshtml Contains the core layout (head, footer, etc)

    Article.cshtml Contains the parts needs to display an Article

    Home.cshtml Contains the homepage layout.

    Now where I come unstuck is, then injecting content into Article. Surely I place an RenderBody on article, and this should allow me to inject a subsequent template into Article.

    _Layout.cshtml
    -> Article.cshtml
    -> LandingPage.cshtml

    Following this principle, I could then inject content into LandingPage if it had a RenderBody(), which is super nice! However, as soon as the template has a RenderBody(), it won't serve in Umbraco.

    E.g.

    I want to be able to use Article.cshtml and LandingPage.cshtml as templates in Umbraco, and also be able to inject content into those templates, as you can do using a ContentPlaceHolder with WebForms.

    Doh!

    _Layout.cshtml

    <html>
    <head />
    <body>
      <header>header</header>
      <div class="container">
        RenderSection("left", false)
        RenderBody()
      </div>
      <footer>footer</footer>
    </body>
    </html>

     

    _Article.cshtml

    @inherits Umbraco.Web.Mvc.UmbracoTemplatePage
    @{
        Layout = "_Layout.cshtml";
    }
    
    @section left {
    <ul>
      @Umbraco.RenderMacro("NavHelper", new {mode="subnav"})
    </ul>
    }
    
    <div id="content">
      <h1>@Umbraco.Field("contentHeader", altFieldAlias: "pageName")</h1>
      @Umbraco.Field("contentBody")             
    </div>
            
    @RenderBody()
            

     

    LandingPage.cshtml

    @inherits Umbraco.Web.Mvc.UmbracoTemplatePage
    @{
        Layout = "_Article.cshtml";
    }
    
    <section>
      <h1>Super Fly Content for Landing Pages!</h1>
      <p>Nice!</p>
    </section>  

     

  • Laurence Gillian 597 posts 1216 karma points
    Jul 09, 2013 @ 14:32
    Laurence Gillian
    0

    This is essentially what I am trying to do:

    http://aboutcode.net/2010/11/08/nested-layout-pages-in-razor.html

    But it results in 

    The file "~/Views/Layout.cshtml" cannot be requested directly because it calls the "RenderBody" method.

  • Jeroen Breuer 4866 posts 12165 karma points MVP 3x admin c-trib
    Jul 09, 2013 @ 14:33
    Jeroen Breuer
    0

    Did you read this great Introducing “Razor” blog? Might help :-).

    Jeroen

  • Laurence Gillian 597 posts 1216 karma points
    Jul 09, 2013 @ 14:51
    Laurence Gillian
    0

    I have :) and it is very helpful, but just not with the nested bit ;)

    I can see how it could be made using 'section, false', but that seems a bit of a round about way of doing things.

    Is it that Razor Layouts do not support nested templates where each template can be used?

    It seems like for each layer of nesting, I would have to create a 'servable' template, resulting in twice as many templates.

  • Lotte Pitcher 46 posts 214 karma points MVP 5x c-trib
    Jul 09, 2013 @ 15:19
    Lotte Pitcher
    0

    I seem to remember you can only fill sections defined in the template, not 'grandparent' ones.

    So for example (with huge chunks stripped out, obviously!):

     
    Views/Site.cshtml

    @{ 
    Layout = null;
    @}
    <head>
    @RenderSection("siteHead", required:false)
    </head>
    <div id="siteContent">
    @RenderBody()
    </div>

     
    Views/Page.cshtml

    @{ 
    Layout = "Site.cshtml";
    @}
    @section siteHead {
       <!-- Page header stuff (if any) then define new section that nested templates can use -->
       @RenderSection("pageHead", required:false)
    }
    <div id="pageContent">
    @RenderBody()
    </div>

     

    Views/Page1.cshtml

    @{
       Layout = "Page.cshtml";
    }
    @section pageHead {
       <!-- stuff in header for this page -->
    }      
    <div>page content</div>

     

    Page1.cshtml should then render as:

    <head>
    <!-- Page header stuff (if any) then define new section that nested templates can use -->
    <!-- stuff in header for this page -->
    </head>
    <div id="siteContent">
    <div id="pageContent">
    <div>page content</div>
    </div>
    </div>

    Does that make sense / help at all?

    Lotte

  • Jeavon Leopold 3042 posts 13382 karma points MVP 8x admin c-trib
    Jul 09, 2013 @ 15:26
    Jeavon Leopold
    0

    I'm not 100% sure it's what your after but have you found the IsSectionDefined method? More info here

  • Laurence Gillian 597 posts 1216 karma points
    Jul 09, 2013 @ 16:37
    Laurence Gillian
    0

    Using sections and IsSectionDefined does achieve what I'm after, but it does rather seem like over kill.

    It seems you either, need to have an extra template for each 'inheritable' template to make it usable.

    Or two copies of the template, one thats inheritable and that isnt.

    Suddenly masterpages look like a really tidy solution!

  • Jeavon Leopold 3042 posts 13382 karma points MVP 8x admin c-trib
    Jul 09, 2013 @ 16:48
    Jeavon Leopold
    0

    I agree, I think when it comes to default content within a section, masterpages does look tidier. However as you say, you can achieve the same thing with sections and IsSectionDefined….

  • Laurence Gillian 597 posts 1216 karma points
    Jul 09, 2013 @ 17:03
    Laurence Gillian
    0

    Would it be possible to wrap RenderBody() in something, so the inhertiable template could be served? 

    Using RenderBody() makes the child templates so clean, and well Razorfied ;)

  • wolulcmit 357 posts 693 karma points
    Jul 10, 2013 @ 08:07
    wolulcmit
    0

    I also had beef with this when converting an Umbraco masterpages site to Mvc
    my conclusion was to just have an extra template with nothing in it to get around the 'cannot be requested directly' bullshit

    Not exactly great because you end up with more benign templates so I'm all ears for a better solution.
    I just tried the following using your suggestion above and it works:

    //Only call RenderBody if not on the main Document type
    @if(Model.Content.DocumentTypeAlias != "BigDaddy"){

    @RenderBody()
      // and any ifSectionDefined stuff

    }

    I'm keen to hear from others more experienced than I whether the above is just asking for trouble :)

    - Tim

  • Laurence Gillian 597 posts 1216 karma points
    Jul 10, 2013 @ 11:20
    Laurence Gillian
    0

    Interesting,

    I tend name my templates 1 to 1 against my document types.

    E.g. if Base is my root document type that every inherits off, it makes sense that my root template is called Base and is servable. 

    Has anybody got any thoughts on the above if statement, it looks like a nice way of doing it myself.

    Otherwise, it's a case of ditching render body and just using sections right? / have lots of extra empty templates.

  • Laurence Gillian 597 posts 1216 karma points
    Jul 10, 2013 @ 19:13
    Laurence Gillian
    0

    This really is quite ugly. I've been messing around all afternoon with this, but RenderBody() / RenderSection() just cannot exist on a View. 
    You can do some nasty nested nonense, but that becomes worse than masterpages.  

  • aweber1 1 post 21 karma points
    Apr 25, 2014 @ 19:30
    aweber1
    0

    For anyone else encountering this issue, the solution proposed by @wolulcmit worked great for me. Thanks!

    In a nutshell:

    //Only call RenderBody if not on the main Document type
    @if(Model.Content.DocumentTypeAlias!="BigDaddy"){

     
    @RenderBody()
     
    // and any ifSectionDefined stuff

    }
  • BJ Patel 75 posts 181 karma points
    Apr 15, 2016 @ 07:41
    BJ Patel
    0

    I my case same error

    but the issue was Content > Template.

    let say I have created a content but it's Template was not selected to Child Template which used Render body :)

    So I selected / change the template and it start working

Please Sign in or register to post replies

Write your reply to:

Draft