Frederik Vig – ASP.NET developer

Follow me

Extending PageData with some cool Html Helpers

I’ve been reading up on ASP.NET MVC recently. One of the things I love about ASP.NET MVC is the control we as developers have over our markup. ASP.NET MVC doesn’t use server controls, instead it relies heavily on extension methods for generating markup. For some time now I’ve been playing with the idea of adding similar functionality to EPiServer and the EPiCode.Extensions project.

This evening I started adding some of these Html Helpers to the project. I’ve started by focusing on generating links (anchors, hyperlinks). Nothing special, but something that I think will save a lot of repetitive coding.

Update: 08.12.2009

I wrote another blog post explaining my thoughts more: Html Helpers vs Server controls.

LinkExtensions

using System;
using System.Collections.Generic;
using System.Web.Routing;
using EPiCode.Extensions.Helper;
using EPiServer.Core;
 
namespace EPiCode.Extensions
{
    public static partial class PageDataExtensions
    {
        public static string HtmlLink(this PageData page)
        {
            return HtmlLink(page, page.PageName, null);
        }
 
        public static string HtmlLink(this PageData page, string linkText)
        {
            return HtmlLink(page, linkText, null);
        }
 
        public static string HtmlLink(this PageData page, Func<PageData, string> linkText)
        {
            return HtmlLink(page, linkText(page), null);
        }
 
        public static string HtmlLink(this PageData page, object attributes)
        {
            return HtmlLink(page, page.PageName, new RouteValueDictionary(attributes));
        }
 
        public static string HtmlLink(this PageData page, string linkText, object attributes)
        {
            return HtmlLink(page, linkText, new RouteValueDictionary(attributes));
        }
 
        public static string HtmlLink(this PageData page, Func<PageData, string> linkText, object attributes)
        {
            return HtmlLink(page, linkText(page), new RouteValueDictionary(attributes));
        }
 
        private static string HtmlLink(PageData page, string linkText, IDictionary<string, object> attributes)
        {
            if (page.PageLink == null || page.PageLink.ID < 1)
            {
                return string.Empty;
            }
 
            return HtmlHelper.GenerateLink(page.LinkURL, linkText, attributes);
        }
    }
}

Usage

    // Method signatur
    public static string HtmlLink(this PageData page)
 
    // Usage
    CurrentPage.HtmlLink();
 
    // Renders
    <a href="/en/mypage/">My PageName</a>
    // Method signatur
    public static string HtmlLink(this PageData page, string linkText)
 
    // Usage
    CurrentPage.HtmlLink("Some text");
 
    // Renders
    <a href="/en/mypage/">Some text</a>
    // Method signatur
    public static string HtmlLink(this PageData page, Func<PageData, string> linkText)
 
    // Usage    
    CurrentPage.HtmlLink(p => p.GetProperty("Heading|PageName").Value.ToString());
 
    // Renders
    <a href="/en/mypage/">My Heading</a>
    // Method signatur
    public static string HtmlLink(this PageData page, object attributes)
 
    // Usage
    CurrentPage.HtmlLink(new { style = "color:red;" });
 
    // Renders
    <a href="/en/mypage/" style="color:red;">My PageName</a>
    // Method signatur
    public static string HtmlLink(this PageData page, string linkText, object attributes)
 
    // Usage
    CurrentPage.HtmlLink("Some text", new { target = "_blank", title = "A very cool link"});
 
    // Renders
    <a href="/en/mypage/" target="_blank" title="A very cool link">Some text</a>
    // Method signatur
    public static string HtmlLink(this PageData page, Func<PageData, string> linkText, object attributes)
 
    // Usage
    CurrentPage.HtmlLink(p => p.StartPublish.ToShortDateString(), new { style = "text-decoration: none;", @class = "myclass" });
 
    // Renders
    <a class="myclass" href="/en/mypage/" style="text-decoration: none;">11/3/2009</a>

This will of course be extra cool combined with the Page Type Builder project.

So what do you think? Cool? Spaghetti code? Don’t care? Comments are very much appreciated! :)

Related Posts:

Share:
  • Twitter
  • DotNetKicks
  • DZone
  • del.icio.us
  • Facebook
  • Google Bookmarks
  • StumbleUpon
  • Digg

10 Comments

  1. Steve says:

    Interesting post!

    For MVC, I absolutely see the point of these Html Helpers, as they are quite important to actually render stuff consistently. For web forms, I’m not sure. One of the key architectural features of web forms is separation of markup and logic, hence server controls.

    What about control adapters with this approach? They won’t be invoked for your code. We all create html markup directly from code now and then, and I always feel a little naughty when I do – as I shouldn’t really be doing it. :-)

    I love extensions, but I think I’ll find a seat on the fence for this one.

    Btw. I’d try to group all methods of this kind together with a naming scheme, like HtmlLink, HtmlImage etc. (if you decide to create more that is. :-)

    /Steve

  2. Frederik Vig says:

    Totally agree on the naming convention. Renamed it HtmlLink, which makes much more sense :) .

  3. Tom Stenius says:

    I somewhat agree with Steve, though I find myself doing these kind of things every once and a while, to have them in the extension project will be great help for those occasions.

    //Tom

  4. Jonas Persson says:

    Interesting post!

  5. Peter Sunna says:

    Personally I think control adapters are a bit too complex and I think this approach is much cleaner. Only working with web controls is nice in theory but the code usually ends up being harder to read and understand when trying to do things that’s not out of the box (to speak sales language…)

    So, don’t let steve stop you! :)

  6. Steve says:

    Peter – much cleaner? You’ve kidding, right? :-)

    Control adapters are there to save your hiney after the fact (and they are advanced, not for everyone). They give you a way to fix things in existing controls. I’ve used them as work arounds for tricky bugs or design shortcomings in EPiServer for an example. Hard coding your html from your C# code makes that impossible.

    Btw. this post is not about control adapters, my comment was that this code makes control adapters useless.

  7. Peter Sunna says:

    Sorry steve, I misread your comment about control adapters. You are of course right, they become useless with this approach. Control adapters are good for changing the output of existing web controls, which you indeed can’t if you don’t use web controls… Lots of nice improvements to EPiServer have been done in this way.

    However, I never use control adapters on my own code due to the simple fact that I try to make sure that I can control all Html that is rendered from the “markup”. Or, put in another way, I prefer having the Html in user controls instead of web controls. I think the problem that control adapters are trying to solve is a problem that shouldn’t exist (in a perfect developer world). The solution should be to provide another user control or something similar. Not write a C# class that hides all Html that’s being rendered in an adavanced, not for everyone, CreateDefaultControls method.

  8. Steve says:

    Good, then we agree :-)

    “Not write a C# class that hides all Html that’s being rendered in an adavanced, not for everyone, CreateDefaultControls method.”
    – or in an extension method like Frederik is doing here ;-)

    /Steve

  9. [...] received some very good comments on my post Extending PageData with some cool Html Helpers. Which made me want to explain my [...]

  10. Might come in handy when creating a HTML mail or something like that. Otherwise I don’t see the point. Always a bad idea to put markup in code behind IMHO.

Leave a Reply

Spam Protection by WP-SpamFree

© Copyright Frederik Vig. Based on Fluid Blue theme