I've created a Html helper that encodes email addresses in order to prevent SPAM. This is the same technique used by the MarkdownSharp library when auto-generating email links.
The problem is that TagBuilder.MergeAttribute
encodes the attribute text which breaks the link. Is it possible to override this behaviour or at least specify the attribute another way. I know I can fall back to just using string concatenation or a StringBuilder
but TabBuilder
does offer a number of benefits such as easily merging other HTML attributes.
/// <summary>
/// Creates an encoded email link in the hopes of foiling most SPAM bots
/// </summary>
public static IHtmlString EmailLink(this HtmlHelper html, string email, string text = null, object htmlAttributes = null)
{
Ensure.Argument.NotNullOrEmpty(email, "email");
var encodedEmail = EncodeEmailAddress(email);
var tb = new TagBuilder("a");
tb.MergeAttribute("href", "mailto:" + encodedEmail);
tb.InnerHtml = text ?? encodedEmail;
if (htmlAttributes != null)
{
tb.MergeAttributes(new RouteValueDictionary(htmlAttributes));
}
return new HtmlString(tb.ToString());
}
/// <summary>
/// encodes email address randomly
/// roughly 10% raw, 45% hex, 45% dec
/// note that @ is always encoded and : never is
/// </summary>
private static string EncodeEmailAddress(string addr)
{
var sb = new StringBuilder(addr.Length * 5);
var rand = new Random();
int r;
foreach (char c in addr)
{
r = rand.Next(1, 100);
if ((r > 90 || c == ':') && c != '@')
sb.Append(c); // m
else if (r < 45)
sb.AppendFormat("&#x{0:x};", (int)c); // m
else
sb.AppendFormat("&#{0};", (int)c); // m
}
return sb.ToString();
}