Creating hCards in ASP.Net

10/10/2008

It's amazing how little you post when you get sick... Or program for that matter... However I do have an update for you today. A little while ago, I posted about vCards, how to create them, what they were, etc. There really isn't that much to them to be honest. However you can actually take that information and embed it in your HTML with the help of hCards.

hCards are basically just HTML representations of a vCard. They do this by using the class attribute of an item to determine what the information is. So for example, the email item could be a div or an a (as in <a href=...) object with the class set to email. Then anything you place before the closing tag would be classified as the email of the hCard. All we need to do is make sure that we enclose all of this in an object that has the class of "vcard". That's all there is to it. So for example:

   1: <div class="vcard">
   2: <span class="fn">James Craig</span>
   3: </div>

That would be a valid hCard (although missing a bit of information, such as my email, phone number, etc.). And since it uses the class attribute, we can use CSS to format the item the way that we want without hindering anything (which means the average person wouldn't even know that they're looking at a hCard).  In order to make your lives easier, I've modified my vCard code to output an hCard as well:

   1: /*
   2: Copyright (c) 2010 <a href="http://www.gutgames.com">James Craig</a>
   3: 
   4: Permission is hereby granted, free of charge, to any person obtaining a copy
   5: of this software and associated documentation files (the "Software"), to deal
   6: in the Software without restriction, including without limitation the rights
   7: to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
   8: copies of the Software, and to permit persons to whom the Software is
   9: furnished to do so, subject to the following conditions:
  10: 
  11: The above copyright notice and this permission notice shall be included in
  12: all copies or substantial portions of the Software.
  13: 
  14: THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  15: IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  16: FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  17: AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  18: LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  19: OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  20: THE SOFTWARE.*/
  21:  
  22: #region Usings
  23: using System.Collections.Generic;
  24: using System.Text;
  25: using System.Text.RegularExpressions;
  26: #endregion
  27:  
  28: namespace Utilities.FileFormats
  29: {
  30:     /// <summary>
  31:     /// Class for creating vCards
  32:     /// </summary>
  33:     public class VCard
  34:     {
  35:         #region Constructor
  36:  
  37:         /// <summary>
  38:         /// Constructor
  39:         /// </summary>
  40:         public VCard()
  41:         {
  42:             Relationships = new List<Relationship>();
  43:         }
  44:  
  45:         #endregion
  46:  
  47:         #region Public Functions
  48:  
  49:         /// <summary>
  50:         /// Gets the vCard
  51:         /// </summary>
  52:         /// <returns>A vCard in string format</returns>
  53:         public string GetVCard()
  54:         {
  55:             StringBuilder Builder = new StringBuilder();
  56:             Builder.Append("BEGIN:VCARD\r\nVERSION:2.1\r\n");
  57:             Builder.Append("FN:");
  58:             if (!string.IsNullOrEmpty(Prefix))
  59:             {
  60:                 Builder.Append(Prefix).Append(" ");
  61:             }
  62:             Builder.Append(FirstName + " ");
  63:             if (!string.IsNullOrEmpty(MiddleName))
  64:             {
  65:                 Builder.Append(MiddleName).Append(" ");
  66:             }
  67:             Builder.Append(LastName);
  68:             if (!string.IsNullOrEmpty(Suffix))
  69:             {
  70:                 Builder.Append(" ").Append(Suffix);
  71:             }
  72:             Builder.Append("\r\n");
  73:  
  74:             Builder.Append("N:");
  75:             Builder.Append(LastName).Append(";").Append(FirstName).Append(";")
  76:                 .Append(MiddleName).Append(";").Append(Prefix).Append(";")
  77:                 .Append(Suffix).Append("\r\n");
  78:             Builder.Append("TEL;WORK:").Append(DirectDial).Append("\r\n");
  79:             Builder.Append("EMAIL;INTERNET:").Append(StripHTML(Email)).Append("\r\n");
  80:             Builder.Append("TITLE:").Append(Title).Append("\r\n");
  81:             Builder.Append("ORG:").Append(Organization).Append("\r\n");
  82:             Builder.Append("END:VCARD\r\n");
  83:             return Builder.ToString();
  84:         }
  85:  
  86:         /// <summary>
  87:         /// Gets the hCard version of the vCard
  88:         /// </summary>
  89:         /// <returns>A hCard in string format</returns>
  90:         public string GetHCard()
  91:         {
  92:             StringBuilder Builder = new StringBuilder();
  93:             Builder.Append("<div class=\"vcard\">");
  94:             if (string.IsNullOrEmpty(Url))
  95:             {
  96:                 Builder.Append("<div class=\"fn\">");
  97:                 if (!string.IsNullOrEmpty(Prefix))
  98:                 {
  99:                     Builder.Append(Prefix).Append(" ");
 100:                 }
 101:                 Builder.Append(FirstName).Append(" ");
 102:                 if (!string.IsNullOrEmpty(MiddleName))
 103:                 {
 104:                     Builder.Append(MiddleName).Append(" ");
 105:                 }
 106:                 Builder.Append(LastName);
 107:                 if (!string.IsNullOrEmpty(Suffix))
 108:                 {
 109:                     Builder.Append(" ").Append(Suffix);
 110:                 }
 111:                 Builder.Append("</div>");
 112:             }
 113:             else
 114:             {
 115:                 Builder.Append("<a class=\"fn url\" href=\"").Append(Url).Append("\"");
 116:                 if (Relationships.Count > 0)
 117:                 {
 118:                     Builder.Append(" rel=\"");
 119:                     foreach (Relationship Relationship in Relationships)
 120:                     {
 121:                         Builder.Append(Relationship.ToString()).Append(" ");
 122:                     }
 123:                     Builder.Append("\"");
 124:                 }
 125:                 Builder.Append(">");
 126:                 if (!string.IsNullOrEmpty(Prefix))
 127:                 {
 128:                     Builder.Append(Prefix).Append(" ");
 129:                 }
 130:                 Builder.Append(FirstName).Append(" ");
 131:                 if (!string.IsNullOrEmpty(MiddleName))
 132:                 {
 133:                     Builder.Append(MiddleName).Append(" ");
 134:                 }
 135:                 Builder.Append(LastName);
 136:                 if (!string.IsNullOrEmpty(Suffix))
 137:                 {
 138:                     Builder.Append(" ").Append(Suffix);
 139:                 }
 140:                 Builder.Append("</a>");
 141:             }
 142:             Builder.Append("<span class=\"n\" style=\"display:none;\"><span class=\"family-name\">").Append(LastName).Append("</span><span class=\"given-name\">").Append(FirstName).Append("</span></span>");
 143:             if (!string.IsNullOrEmpty(DirectDial))
 144:             {
 145:                 Builder.Append("<div class=\"tel\"><span class=\"type\">Work</span> ").Append(DirectDial).Append("</div>");
 146:             }
 147:             if (!string.IsNullOrEmpty(Email))
 148:             {
 149:                 Builder.Append("<div>Email: <a class=\"email\" href=\"mailto:").Append(StripHTML(Email)).Append("\">").Append(StripHTML(Email)).Append("</a></div>");
 150:             }
 151:             if (!string.IsNullOrEmpty(Organization))
 152:             {
 153:                 Builder.Append("<div>Organization: <span class=\"org\">").Append(Organization).Append("</span></div>");
 154:             }
 155:             if (!string.IsNullOrEmpty(Title))
 156:             {
 157:                 Builder.Append("<div>Title: <span class=\"title\">").Append(Title).Append("</span></div>");
 158:             }
 159:             Builder.Append("</div>");
 160:             return Builder.ToString();
 161:         }
 162:         #endregion
 163:  
 164:         #region Private Functions
 165:  
 166:         private static string StripHTML(string HTML)
 167:         {
 168:             if (string.IsNullOrEmpty(HTML))
 169:                 return string.Empty;
 170:  
 171:             HTML = STRIP_HTML_REGEX.Replace(HTML, string.Empty);
 172:             HTML = HTML.Replace("&nbsp;", " ");
 173:             return HTML.Replace("&#160;", string.Empty);
 174:         }
 175:  
 176:         private static readonly Regex STRIP_HTML_REGEX = new Regex("<[^>]*>", RegexOptions.Compiled);
 177:  
 178:         #endregion
 179:  
 180:         #region Properties
 181:         /// <summary>
 182:         /// First name
 183:         /// </summary>
 184:         public string FirstName { get; set; }
 185:  
 186:         /// <summary>
 187:         /// Last name
 188:         /// </summary>
 189:         public string LastName { get; set; }
 190:  
 191:         /// <summary>
 192:         /// Middle name
 193:         /// </summary>
 194:         public string MiddleName { get; set; }
 195:  
 196:         /// <summary>
 197:         /// Prefix
 198:         /// </summary>
 199:         public string Prefix { get; set; }
 200:  
 201:         /// <summary>
 202:         /// Suffix
 203:         /// </summary>
 204:         public string Suffix { get; set; }
 205:  
 206:         /// <summary>
 207:         /// Work phone number of the individual
 208:         /// </summary>
 209:         public string DirectDial { get; set; }
 210:  
 211:         /// <summary>
 212:         /// Email of the individual
 213:         /// </summary>
 214:         public string Email { get; set; }
 215:  
 216:         /// <summary>
 217:         /// Title of the person
 218:         /// </summary>
 219:         public string Title { get; set; }
 220:  
 221:         /// <summary>
 222:         /// Organization the person belongs to
 223:         /// </summary>
 224:         public string Organization { get; set; }
 225:  
 226:         /// <summary>
 227:         /// Relationship to the person (uses XFN)
 228:         /// </summary>
 229:         public List<Relationship> Relationships { get; set; }
 230:  
 231:         /// <summary>
 232:         /// Url to the person's site
 233:         /// </summary>
 234:         public string Url { get; set; }
 235:  
 236:         #endregion
 237:     }
 238:  
 239:     #region Enums
 240:     /// <summary>
 241:     /// Enum defining relationships (used for XFN markup)
 242:     /// </summary>
 243:     public enum Relationship
 244:     {
 245:         Friend,
 246:         Acquaintance,
 247:         Contact,
 248:         Met,
 249:         CoWorker,
 250:         Colleague,
 251:         CoResident,
 252:         Neighbor,
 253:         Child,
 254:         Parent,
 255:         Sibling,
 256:         Spouse,
 257:         Kin,
 258:         Muse,
 259:         Crush,
 260:         Date,
 261:         Sweetheart,
 262:         Me
 263:     }
 264:     #endregion
 265: }

You may wish to go in and modify it a bit since it is set up for individuals and not organizations, doesn't have address information, geo information, etc. However, it should show you how incredibly easy it is to create an hCard. Once I get it working, I'll show you how to add in XFN information into the mix... For now though, download the code, leave feedback, and happy coding.



Comments