Extending PageData with some cool Html Helpers
Posted on December 8, 2009 by Frederik Vig in EPiServerI’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:
Frederik Vig
Post Author
I'm a partner and ASP.NET developer for the Norwegian web agency Geta. I mainly write about things I work with, which are: .NET and web technologies
Other posts by Frederik Vig →
Steve says:
Post Author December 8, 2009 at 00:46Interesting 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
Frederik Vig says:
Post Author December 8, 2009 at 01:03Totally agree on the naming convention. Renamed it HtmlLink, which makes much more sense :).
Tom Stenius says:
Post Author December 8, 2009 at 04:54I 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
Jonas Persson says:
Post Author December 8, 2009 at 08:57Interesting post!
Peter Sunna says:
Post Author December 8, 2009 at 10:09Personally 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! π
Steve says:
Post Author December 8, 2009 at 10:35Peter – 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.
Peter Sunna says:
Post Author December 8, 2009 at 12:37Sorry 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.
Steve says:
Post Author December 8, 2009 at 13:44Good, 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
Johan Kronberg says:
Post Author December 9, 2009 at 14:38Might 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.
Rodrick Biancaniello says:
Post Author September 9, 2011 at 09:53The right panel of you blog shows up all out of whack! i’m using Firefox if it helps.