X

Creating vCard with image in .Net

vCard is popular format for exchanging contacts. Besides e-mail clients also modern mobile phones are able to read and send contacts as vCard. This posting introduces same ideas how to implement vCard support in your applications and how to add images to vCards.

ASP.NET Core version of this solution is available at my blog post Creating vCard in ASP.NET Core.

Our goal is make our system to output vCard like shown on image. We will write class for vCard and I give you some hints how to output those things in your web applications. These tips may be also useful for desktop applications.

I consider vCard as data transfer object(DTO). To make it simpler to use I use only properties of simple type so it is also possible to use them over web services. You can also use vCard as data contract between your application and domain model. How you implement vCard is up to you, I just help you get started.

vCard class

My vCard class is simple. It contains some properties for vCard data and one method that outputs vCard in vCard format. I try to keep this code short, so forgive me father for all  documentation and other missing stuff and things implemented as dirty code.

public class VCard
{
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public string Organization { get; set; }
    public string JobTitle { get; set; }
    public string StreetAddress { get; set; }
    public string Zip { get; set; }
    public string City { get; set; }
    public string CountryName { get; set; }
    public string Phone { get; set; }
    public string Mobile { get; set; }
    public string Email { get; set; }
    public string HomePage { get; set; }
    public byte[] Image { get; set; }
    public override string ToString()
    {
        var builder = new StringBuilder();
        builder.AppendLine("BEGIN:VCARD");
        builder.AppendLine("VERSION:2.1");
        // Name
        builder.AppendLine("N:" + LastName + ";" + FirstName);
        // Full name
        builder.AppendLine("FN:" + FirstName + " " + LastName);
        // Address
        builder.Append("ADR;HOME;PREF:;;");
        builder.Append(StreetAddress + ";");
        builder.Append(City + ";;");
        builder.Append(Zip + ";");
        builder.AppendLine(CountryName);
        // Other data
        builder.AppendLine("ORG:" + Organization);
        builder.AppendLine("TITLE:" + JobTitle);
        builder.AppendLine("TEL;HOME;VOICE:" + Phone);
        builder.AppendLine("TEL;CELL;VOICE:" + Mobile);
        builder.AppendLine("URL;" + HomePage);
        builder.AppendLine("EMAIL;PREF;INTERNET:" + Email);
        builder.AppendLine("END:VCARD");
        return builder.ToString();
    }
}

Using ToString() may be not a very good idea if you need to reserve default representation of vCard for user-interface output. Of course, there may be other considerations. You can rename this method to something else if you don’t want to use ToString() as name of method.

Adding image to vCard

We have basic vCard now but we have no support for images. Let’s update VCard class so our friends can more easily match our name and face. It is specially useful for dudes who sit too much at computer and doesn’t meet their friends very often.

vCard may contain image in it. Of course, image must be encoded to text. Base64 encoding works well for us. I suppose you have code that outputs image as byte array. Of course, you can modify my code and use some other type to keep image data. I tried to keep VCard and its dependencies minimal.

// Add image
builder.AppendLine("PHOTO;ENCODING=BASE64;TYPE=JPEG:");
builder.AppendLine(Convert.ToBase64String(Image));
builder.AppendLine(string.Empty);

Add this code right before vCard line where VCARD:END is appended to builder. Note that after image we have to output two line breaks. Without them image is not shown.

Testing output

Now let’s test VCard. We need to find out if it outputs data correctly or not. My test method is simple. I create new vCard, load image to it and then write it on my local hard disc. As a next thing I check out what Outlook thinks about my vCard.

public void Run()
{
    var myCard = new VCard
    {
        FirstName = "Gunnar",
        LastName = "Peipman",
        Organization = "Developers Team Ltd",
        JobTitle = "n00b",
        StreetAddress = "Tööstuse 48",
        City = "Tallinn",
        CountryName = "Estonia",
        Phone = "343-23232",
        Mobile = "232-67854",
        Email = "gunnar@secret-address.com",
        HomePage = "www.developers-team.com"
    };
    myCard.Image = File.ReadAllBytes("C:\\Images\\me.jpg");
    using (var file = File.OpenWrite("C:\\Files\\me.vcf"))
    using (var writer = new StreamWriter(file))
    {
        writer.Write(myCard.ToString());
    }
}

This time I am lucky. Okay, almost lucky. Outlook 2007 shows almost everything fine.The only exception is StreetAddress. We can see there characters that doesn’t match in UTF-8 and Windows-1257. But let’s solve this problem in next section.

Downloading vCards

Downloading vCard is not complex thing to implement. I found something weird here: Outlook 2007 was not able to read UTF-8 format vCards. I had to convert vCard to Windows-1257 to get Outlook 2007 reading them. Let’s see now how to download vCard from your web application.

Response.Clear();
Response.ContentType = "text/vcard";
var cardString = myCard.ToString();
var inputEncoding = Encoding.Default;
var outputEncoding = Encoding.GetEncoding("windows-1257");
var cardBytes = inputEncoding.GetBytes(cardString);
var outputBytes = Encoding.Convert(inputEncoding,
                        outputEncoding, cardBytes);
Response.OutputStream.Write(outputBytes, 0, outputBytes.Length);
Response.End();

Before writing vCard to response stream we clean response buffer so it is empty and contains no surprises. We also convert card output to Windows-1257 character set so Outlook is able to understand it. We output vCard as byte array because in this case it is sure that web server cannot modify string encoding.

So, that’s it guys. Our vCards should work now as expected and if you move VCard class to some common library you are able to use it in more than one application.

Liked this post? Empower your friends by sharing it!
Categories: ASP.NET

View Comments (9)

  • Great post.
    Just one comment on the code. I think the purpose of using StringBuilder is to avoid string concatenation. Here you are using a StringBuilder object but still doing a concate:
    builder.AppendLine("N:"+ LastName + ";" + FirstName);

    Something like this would be better:

    builder.AppendLine("N:");
    builder.AppendLine(LastName);
    builder.AppendLine(";");
    builder.AppendLine(FirstName);

  • Thanks Shuiab, you are correct. YOU should do something like this. I just tried to save some space so my blog entry is not too long to scroll. But you got the point. :)

  • builder.AppendLine("URL;" + HomePage);

    Just out of logical thinking I'm wondering if that line is correct. I expected it to read:

    builder.AppendLine("URL:" + HomePage);

    Cheers,
    Wes

  • Thanks for putting this use full article but my problem is that i want to export all data of a grid in vCard Format. Will you please help me for solving this

    my code is:-
    HttpContext.Current.Response.Clear();
    HttpContext.Current.Response.Charset = "";
    HttpContext.Current.Response.ContentType = "text/x-vCard";
    string vfilename = "MyContact.VCF";
    HttpContext.Current.Response.AddHeader("content-disposition", "inline;filename=" + vfilename);
    StringBuilder strHtmlContent = new StringBuilder();
    System.IO.StringWriter stringWrite = new System.IO.StringWriter();
    System.Web.UI.HtmlTextWriter htmlWrite = new HtmlTextWriter(stringWrite);
    stringWrite.WriteLine("BEGIN:VCARD");
    stringWrite.WriteLine("VERSION:2.1");
    for (int i = 0; i < DL_Contact.Items.Count; i++) { CheckBox cb = (CheckBox)DL_Contact.Items[i].FindControl("chk_conchk"); if (cb.Checked == true) { Label lid = (Label)DL_Contact.Items[i].FindControl("lbl_id"); x = Convert.ToInt32(lid.Text); Objref = DA_SBP.DA_Group.usp_exportcontact(x); foreach (DataRow rand in this.Objref.Tables["table"].Rows) { stringWrite.WriteLine("N:" + vname + ";" + vmail + ";" + vcno); vmail = rand["EmailId"].ToString(); vname = rand["FullName"].ToString(); vcno = rand["PhoneNo"].ToString(); vcomp = rand["CompanyName"].ToString(); vjobtitle = rand["JobTitle"].ToString(); vadd = rand["Address1"].ToString(); stringWrite.WriteLine("FN:" + vname); stringWrite.WriteLine("Email:" + vmail); stringWrite.WriteLine("ORG:" + vcomp); stringWrite.WriteLine("TITLE:" + vjobtitle); stringWrite.WriteLine("ADR;WORK;ENCODING=QUOTED-PRINTABLE:" + vadd); } } } stringWrite.WriteLine("END:VCARD"); HttpContext.Current.Response.Write(stringWrite.ToString()); HttpContext.Current.Response.End(); But it giving me only last record. Please Solve this...

  • very nice example, but, how can i do to read the card, for example from a vb.net app and withouth looping in the action of read image from this vbcard =)

    i hope u can help me
    thanks =)

  • Thanks for question, Chris! :)
    You have to write Parse() method to this class that takes string with vCard as input and then extracts information from it. Image is given as base64 encoded string. There are methods available in .NET framework to encode and decode base64 strings.

  • While it’s normal to desire a deep connection, don’t let the pleasure of a new relationship cause you to overlook pink flags or settle for lower than what you deserve. While the seek for a significant relationship can generally really feel intense, don’t forget that dating should be enjoyable! This part of life might be each exhilarating and fulfilling, particularly when you approach it with a playful and adventurous mindset. It’s important to strategy scheduling with flexibility and understanding. In your 40s, it’s important to embrace who you're with out hesitation or apology. So, embrace your interests and let them guide you in your relationship journey. Don't let the everyday up's and down's set you back, look at let downs as alternatives, people thinking optimistic helps to achieve optimistic results in the courting world and the rest for that matter. Listen attentively and validate their feelings, as this helps them feel heard and respected. Remember, dating should feel empowering, not compelled. Many people enter the courting scene with a romanticized view of love, hoping to recreate the intense passion of their 20s or 30s. However, it’s essential to acknowledge that relationships require effort, understanding, and compromise.

    In your 40s, it’s essential to balance realistic expectations with a robust commitment to your core values. Setting boundaries is important in your properly-being and can in the end contribute to a more balanced and fulfilling relationship. Discuss expectations with your companion - who covers the invoice, whether you appreciate conventional gestures like door-opening, or in case you want a extra egalitarian approach. I was befogged to search out out precisely how widespread this area had change into because it is little or no secret that quite a few people within the USA publicly do not like european football and decline to simply accept its existence. Today’s dating setting requires open dialogue about gender expectations and how they play out in trendy relationships. Many individuals still adhere to conventional gender roles, ready for men to make the primary transfer. At this age, individuals typically have a clearer sense of what they need in a accomplice and are more confident in their own identities and values. By engaging in these conversations, you may align your values and preferences, paving the way for a extra harmonious and satisfying connection. By honoring your instincts, you may make decisions that align together with your values and lead to more fulfilling connections.

    After 40, consider expanding your social circle via alumni associations, the place you may reconnect with former classmates who share similar life experiences. Be open-minded and respectful in conversations, exhibiting empathy and understanding for the life experiences of others. Dating in your 40s can provide benefits reminiscent of larger emotional maturity, stability, and a deeper understanding of non-public objectives and priorities. Embracing this proactive mindset will allow you to create relationships which can be based mostly on mutual understanding and respect. Every expertise - whether a misstep in a past relationship or a profession setback - has shaped you into the person you are immediately. Your instincts can assist you to discern whether a relationship is value pursuing or if it’s finest to stroll away. Offbeat date ideas, latamdate equivalent to grabbing breakfast before work or working errands collectively, will be gratifying and efficient ways to connect amidst a busy schedule. When you date in your 40s, it's best to prioritize your private pursuits and maintain your connections with mates and household. That first date is your introduction to a love curiosity, so it’s normal to be nervous or enthusiastic about it. It’s what I like to do. In case your companion needs to cancel or reschedule, keep in mind that it’s likely on account of life’s calls for rather than a reflection of their interest in you.

    As you might have come to comprehend, romantic curiosity and need for companionship doesn’t wane considerably as individuals get older. Embrace spontaneity by making an attempt out new activities, visiting fascinating locations, or simply having fun with the quirky moments that include dating. Avoid come off since junk mail postal mail, that's just unhappy. To submit a pet on Petfinder, a member must log in to the administration web page using his or her shelter ID and password. A reflexmate is a selfmate with the additional rule that if both aspect can ship checkmate, it must. People over 40 have many duties - career obligations, family commitments, and personal pursuits - due to this fact finding quality time for dating might be difficult. Engage in activities that align together with your pursuits and values, demonstrating your passions and dedication to personal development. Rather than viewing these moments as “baggage,” see them as worthwhile life lessons that have contributed to your growth.

Related Post