locked
Need Advice: when do you use @helper ? RRS feed

  • Question

  • User-1416423428 posted

    I have a fairly long <div>...</div> section that I was planning on using @helper to display it, passing it some List<string> object.

    Inside this @helper, I then have a for loop to go through the List<string> values.... but it seems @helper isn't ideal if there's a lot of C# logic that needs to be executed?

    It's fine I guess for simple @displaymevalue embedded within the html code, but not for lots of foreach/branching logic. Is that right? 

    Am I better off using @function instead?  

    when do you guys use a @helper?  (besides the Twitter and Facebook example of MS) 

    Wednesday, June 4, 2014 2:19 AM

Answers

  • User1713851783 posted

    Your code should be something like:

    @helper DisplaySlideShow(List<string> photoslides)
    {
      // demo
      <div id="homeslideshow" >
        <div id="slides" class="carousel slide" data-ride="carousel">
          <!-- Indicators -->  
          <ol class="carousel-indicators">
            @for (int i = 0; i < 9; i++)
            {
              <li data-target="slides" data-slide-to="@i"></li>
            }        
          </ol>
    // ....
    
    

    Try to look at the razor syntax in Introduction to ASP.NET Web Programming Using the Razor Syntax (C#).

    • Marked as answer by Anonymous Thursday, October 7, 2021 12:00 AM
    Wednesday, June 4, 2014 4:45 AM
  • User1853794821 posted

    Basically, any time you try to start some c# code "inside" an html element (in this case, "inside" the <u.</ul>), you need to escape out of html and into razor, using the @.  If it is an if or foreach statement, then preface the if or foreach with "@" and anything in the associated block is treated as valid c#.  If you are trying to do some c# that does not have an associated block, then surrounding the c# code with an @{.....} block will work for you.  

    There is no need to preface each html element with "@:".

    • Marked as answer by Anonymous Thursday, October 7, 2021 12:00 AM
    Wednesday, June 4, 2014 9:49 AM
  • User938738290 posted

    Gregori's spot on.

    CASpartan, in your second code example:

    @helper DisplaySlideShow(List<string> photoslides)
    {
      // demo
      <ol>
        for(int i=0;i<9;i++){
          <li data-target="slides" data-slide-to="@i"></li>
          }
      </ol>
    }

    Razor sees this:

    @helper DisplaySlideShow(List<string> photoslides)
    {
        Stuff1
    }

    And assumes that Stuff1 is going to be Razor syntax C# until you tell it otherwise.

    Then it sees:

    <ol class="carousel-indicators">
         Stuff2
    </ol>

    It notices the HTML tag, and assumes that Stuff2 is going to be HTML until you tell it otherwise.

    Then it sees:

    for (int i=0;i<9;i++) {
        <li data-target="slides" data-slide-to="@Stuff3"></li>
    }

    Since the word "for" isn't prefixed by an @, it assumes that you want to put "for (int i=0;i<9;i++)" into your page as raw HTML/text.  It only kicks back into C# mode when it sees the @ symbol, and assumes that Stuff3 that is going to be a C# expression to be evaluated and output.  Since Stuff3 in this case is simply the variable i, it tries to evaluate it, but it was never declared, since the for loop wasn't read as code.

    It makes a little more sense if you've ever had a compilers or programming languages course that dealt with grammars, but hopefully this explanation is enough for you.

    tl;dr: The Razor Engine assumes that anything contained inside HTML tags is to be written in the page as raw text/HTML until you tell it otherwise with the @ symbol.

    • Marked as answer by Anonymous Thursday, October 7, 2021 12:00 AM
    Wednesday, June 4, 2014 9:51 AM
  • User938738290 posted

    CASPartan

    But if I do this.... it works 

    @helper DisplaySlideShow(List<string> photoslides)
    {
      // demo
      @:<ol>
        for(int i=0;i<9;i++){
          <li data-target="slides" data-slide-to="@i"></li>
          }
      @:</ol>
    }

    The reason for this is that the Razor Engine sees the line

    @:<ol>

    As Razor syntax, not as raw HTML.  Therefore, it never switches to "HTML mode," and your for loop is read as C#, so i gets declared with no issue.

    • Marked as answer by Anonymous Thursday, October 7, 2021 12:00 AM
    Wednesday, June 4, 2014 9:57 AM
  • User1526116210 posted

    In answer to this question

    when do you guys use a @helper?

    I use @helper for recursion of my comments to get them nested, which of course Mike has an article for http://mikesdotnetting.com/Article/208/Practical-Recursion-in-ASP.NET-Web-Pages-with-WebMatrix

    In answer to this question

    Am I better off using @function instead?

    For your use of generating the necessary HTML for your carousel, it is best to use @helper if you would like the ability to easily add the carousel more than once to your page. Otherwise I would just use the code within your @helper but have that directly in the page instead of using a helper function.

    As the others said if you have razor code within HTML you need to have the @ symbol in front of your razor code, otherwise it will interpret the razorcode as plain text/HTML

    • Marked as answer by Anonymous Thursday, October 7, 2021 12:00 AM
    Wednesday, June 4, 2014 10:02 AM

All replies

  • User1713851783 posted

    Maybe this Mike's article could help: The Difference Between @Helpers and @Functions In WebMatrix.

    Wednesday, June 4, 2014 2:27 AM
  • User-1416423428 posted

    Here's my problem. 

    this simple code works as a @helper.

    @helper DisplaySlideShow(List<string> photoslides)
    {
      // demo
        for(int i=0;i<9;i++){
          <li data-target="slides" data-slide-to="@i"></li>
          }
    }

    ... now I enclose these <li> tags in a <ol> </ol> like so below, and you think it should work... 

    @helper DisplaySlideShow(List<string> photoslides)
    {
      // demo
      <ol>
        for(int i=0;i<9;i++){
          <li data-target="slides" data-slide-to="@i"></li>
          }
      </ol>
    }
    

    and Razor just goes bonkers... 

    Compiler Error Message: CS0103: The name 'i' does not exist in the current context

    Source Error:

    Line 17:   <ol>
    Line 18:     for(int i=0;i<9;i++){
    Line 19:       <li data-target="slides" data-slide-to="@i"></li>
    Line 20:       }
    Line 21:   </ol>
    Wednesday, June 4, 2014 4:07 AM
  • User-1416423428 posted

    But if I do this.... it works 

    @helper DisplaySlideShow(List<string> photoslides)
    {
      // demo
      @:<ol>
        for(int i=0;i<9;i++){
          <li data-target="slides" data-slide-to="@i"></li>
          }
      @:</ol>
    }
    

    Wednesday, June 4, 2014 4:08 AM
  • User-1416423428 posted

    Starting to add more html.... I have to prefix them all with @: 

    @helper DisplaySlideShow(List<string> photoslides)
    {
      // demo
      @:<div id="homeslideshow" >
        @:<div id="slides" class="carousel slide" data-ride="carousel">
          @:<!-- Indicators -->  
          @:<ol class="carousel-indicators">
            for (int i = 0; i < 9; i++)
            {
              <li data-target="slides" data-slide-to="@i"></li>
            }        
          @:</ol>
      @:</div>
      
    }

    I guess... that's a little bit better than constructing these html strings in C#, concatenating them and using  \" for all the quotes. 

    Wednesday, June 4, 2014 4:13 AM
  • User-1416423428 posted

    Continue adding more html code...  

    by trial and error, I find out some html code require @: in front, while others do not require it. 

    @helper DisplaySlideShow(List<string> photoslides)
    {
      // demo
      @:<div id="homeslideshow" >
        @:<div id="slides" class="carousel slide" data-ride="carousel">
          @:<!-- Indicators -->  
          @:<ol class="carousel-indicators">
            for (int i = 0; i < 9; i++)
            {
              <li data-target="slides" data-slide-to="@i"></li>
            }        
          @:</ol>
    
      
          <!-- Controls -->
          <a class="left carousel-control" href="#slides" data-slide="prev">
            <span class="icon-prev"></span>
          </a>
          <a class="right carousel-control" href="#slides" data-slide="next">
            <span class="icon-next"></span>
          </a>
      
        @:</div> <!--#slides-->
      @:</div> <!--#slideshow-->
      
    }
    

    This works....!  Why don't I need @: for the <a> tags?  The <!-- comment --> line also works without the need for @: 

    Wednesday, June 4, 2014 4:21 AM
  • User1713851783 posted

    Your code should be something like:

    @helper DisplaySlideShow(List<string> photoslides)
    {
      // demo
      <div id="homeslideshow" >
        <div id="slides" class="carousel slide" data-ride="carousel">
          <!-- Indicators -->  
          <ol class="carousel-indicators">
            @for (int i = 0; i < 9; i++)
            {
              <li data-target="slides" data-slide-to="@i"></li>
            }        
          </ol>
    // ....
    
    

    Try to look at the razor syntax in Introduction to ASP.NET Web Programming Using the Razor Syntax (C#).

    • Marked as answer by Anonymous Thursday, October 7, 2021 12:00 AM
    Wednesday, June 4, 2014 4:45 AM
  • User1853794821 posted

    Basically, any time you try to start some c# code "inside" an html element (in this case, "inside" the <u.</ul>), you need to escape out of html and into razor, using the @.  If it is an if or foreach statement, then preface the if or foreach with "@" and anything in the associated block is treated as valid c#.  If you are trying to do some c# that does not have an associated block, then surrounding the c# code with an @{.....} block will work for you.  

    There is no need to preface each html element with "@:".

    • Marked as answer by Anonymous Thursday, October 7, 2021 12:00 AM
    Wednesday, June 4, 2014 9:49 AM
  • User938738290 posted

    Gregori's spot on.

    CASpartan, in your second code example:

    @helper DisplaySlideShow(List<string> photoslides)
    {
      // demo
      <ol>
        for(int i=0;i<9;i++){
          <li data-target="slides" data-slide-to="@i"></li>
          }
      </ol>
    }

    Razor sees this:

    @helper DisplaySlideShow(List<string> photoslides)
    {
        Stuff1
    }

    And assumes that Stuff1 is going to be Razor syntax C# until you tell it otherwise.

    Then it sees:

    <ol class="carousel-indicators">
         Stuff2
    </ol>

    It notices the HTML tag, and assumes that Stuff2 is going to be HTML until you tell it otherwise.

    Then it sees:

    for (int i=0;i<9;i++) {
        <li data-target="slides" data-slide-to="@Stuff3"></li>
    }

    Since the word "for" isn't prefixed by an @, it assumes that you want to put "for (int i=0;i<9;i++)" into your page as raw HTML/text.  It only kicks back into C# mode when it sees the @ symbol, and assumes that Stuff3 that is going to be a C# expression to be evaluated and output.  Since Stuff3 in this case is simply the variable i, it tries to evaluate it, but it was never declared, since the for loop wasn't read as code.

    It makes a little more sense if you've ever had a compilers or programming languages course that dealt with grammars, but hopefully this explanation is enough for you.

    tl;dr: The Razor Engine assumes that anything contained inside HTML tags is to be written in the page as raw text/HTML until you tell it otherwise with the @ symbol.

    • Marked as answer by Anonymous Thursday, October 7, 2021 12:00 AM
    Wednesday, June 4, 2014 9:51 AM
  • User938738290 posted

    CASPartan

    But if I do this.... it works 

    @helper DisplaySlideShow(List<string> photoslides)
    {
      // demo
      @:<ol>
        for(int i=0;i<9;i++){
          <li data-target="slides" data-slide-to="@i"></li>
          }
      @:</ol>
    }

    The reason for this is that the Razor Engine sees the line

    @:<ol>

    As Razor syntax, not as raw HTML.  Therefore, it never switches to "HTML mode," and your for loop is read as C#, so i gets declared with no issue.

    • Marked as answer by Anonymous Thursday, October 7, 2021 12:00 AM
    Wednesday, June 4, 2014 9:57 AM
  • User1526116210 posted

    In answer to this question

    when do you guys use a @helper?

    I use @helper for recursion of my comments to get them nested, which of course Mike has an article for http://mikesdotnetting.com/Article/208/Practical-Recursion-in-ASP.NET-Web-Pages-with-WebMatrix

    In answer to this question

    Am I better off using @function instead?

    For your use of generating the necessary HTML for your carousel, it is best to use @helper if you would like the ability to easily add the carousel more than once to your page. Otherwise I would just use the code within your @helper but have that directly in the page instead of using a helper function.

    As the others said if you have razor code within HTML you need to have the @ symbol in front of your razor code, otherwise it will interpret the razorcode as plain text/HTML

    • Marked as answer by Anonymous Thursday, October 7, 2021 12:00 AM
    Wednesday, June 4, 2014 10:02 AM
  • User-1416423428 posted

    Gregori is spot on.

    Thank you all! 

    Now follow up question....  

    My @helper is working now, is it possible to capture the output of your @helper into a variable?  For use, let's say as a parameter in a Replace() statement. 

    @helper DisplaySlideshow(){
       html blah blah blah
    }
    
    then on my cshtml page.... I do this
    
    var myslides = Utilities.DisplaySlideshow(params etc.) 
    cmsBody.Replace("[SLIDES]", myslides);
    



    Wednesday, June 4, 2014 10:50 AM
  • User-1416423428 posted

    That was simple... never mind.

    string myslides = Utilities.DisplaySlideShow(photoslides).ToString();

    Wednesday, June 4, 2014 10:52 AM
  • User938738290 posted

    CASPartan

    Now follow up question....  

    My @helper is working now, is it possible to capture the output of your @helper into a variable?

    I don't think so.  This is one of the differences between Helpers and Functions.  Helpers can be used to write raw HTML to the page, just like you can in .cshtml files.  If you need a return value, you use a Function, but the @functions{ } statement locks the Razor engine into C# mode.

    EDIT: If it works for you, it works.

    EDIT: Hm, yep.  For posterity: Helpers return a HelperResult object, and HelperResult.ToString( ) just dumps the raw HTML that would have been output by the helper.

    Wednesday, June 4, 2014 10:55 AM
  • User938738290 posted

    Hot damn, check this out: http://haacked.com/archive/2011/02/27/templated-razor-delegates.aspx/.  Phil Haack has a really cool use for the HelperResult class.

    Wednesday, June 4, 2014 11:01 AM