{{announcement.body}}
{{announcement.title}}

Creating vCard in ASP.NET Core

DZone 's Guide to

Creating vCard in ASP.NET Core

Create vCards in ASP.NET CORE for Outlook.

· Web Dev Zone ·
Free Resource

It’s time to get back to the old era of this blog and bring my vCard action result to today’s ASP.NET Core world. There’s support for images, so we can provide really good looking vCards from ASP.NET Core applications. This blog post gives a good base for custom vCard solutions in ASP.NET Core.

vCard Class

Previously, I built a vCard class to be a simple DTO-style class with a ToString() method that builds up a string output of vCard.

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 string GetFullName()    {        
    return FirstName + LastName;    }     
  
  public override string ToString()    {        
    var builder = new StringBuilder();        
    builder.AppendLine("BEGIN:VCARD");       
    builder.AppendLine("VERSION:2.1");         
    
    // Name        
    builder.Append("N:").Append(LastName)               
      .Append(";").AppendLine(FirstName);         
    
    // Full name        
    builder.Append("FN:").Append(FirstName)               
      .Append(" ").AppendLine(LastName);         
    
    // Address        
    builder.Append("ADR;HOME;PREF:;;").Append(StreetAddress)               
      .Append(";").Append(City).Append(";")               
      .Append(Zip).Append(";").AppendLine(CountryName);         
    
    // Other data        
    builder.Append("ORG:").AppendLine(Organization);        
    builder.Append("TITLE:").AppendLine(JobTitle);        
    builder.Append("TEL;WORK;VOICE:").AppendLine(Phone);        
    builder.Append("TEL;CELL;VOICE:").AppendLine(Mobile);        
    builder.Append("URL:").AppendLine(HomePage);        
    builder.Append("EMAIL;PREF;INTERNET:").AppendLine(Email);         
    
    // Image        
    if(Image != null) {           
      builder.AppendLine("PHOTO;ENCODING=BASE64;TYPE=JPEG:");            
      builder.AppendLine(Convert.ToBase64String(Image));            
      builder.AppendLine(string.Empty);        
    }         
    
    builder.AppendLine("END:VCARD");         
    return builder.ToString();    
  }
}


There are more attributes that vCard supports, but my code focuses on the most important ones. I left out others, as I have not needed these is practice over last 10 years. Those who need more attributes can take my code and add the ones they need.

vCard Action Result

Creating an action result for vCard is simple. Most of the dirty work is done in the ToString() method of vCard. Our action result must set response headers and write vCard to response stream.

public class vCardActionResult : IActionResult {    
  private readonly VCard _vCard;     
  
  public vCardActionResult(VCard vCard)    {        
    _vCard = vCard;    
  }     
  
  public async Task ExecuteResultAsync(ActionContext context)    {        
    var fileName = _vCard.GetFullName() + ".vcf";       
    var disposition = "attachment; filename=" + fileName;         
    var response = context.HttpContext.Response;        
    
    response.ContentType = "text/vcard";        
    response.Headers.Add("Content-disposition", disposition);         
    
    var bytes = Encoding.UTF8.GetBytes(_vCard.ToString());         
    await response.Body.WriteAsync(bytes, 0, bytes.Length);    
  }
}


Here is my sample controller action to download vCard.

public async Task<IActionResult> vCard() {    
  var vcard = new VCard();    
  vcard.FirstName = "Gunnar";    
  vcard.LastName = "Peipman";    
  vcard.Email = "gunnar@example.com";    
  vcard.City = "Tallinn";    
  vcard.CountryName = "Estonia";    
  vcard.Phone = "00-12345";    
  vcard.Mobile = "00-10101";    
  vcard.Organization = "Freelancer";    
  vcard.JobTitle = "Chief Everything Office";     
  vcard.Image = await System.IO.File.ReadAllBytesAsync("gunnar300.jpg");     
  
  return new vCardActionResult(vcard);
}


My controller action works. When opening a downloaded vCard with Outlook, it shows a nice business card.

vCard open in Outlook

vCard open in Outlook


We have a working vCard solution, but it’s not yet very convenient to use.

Using vCard Action Result in Practice

The first annoying thing for me is creating a new instance of vCardActionResult in the controller action. ASP.NET Core action results can be often called by a special method. To follow the same pattern, I created my own base class for controllers.

public class BaseController : Controller {    
  public IActionResult VCard(VCard vCard)    {        
    return new vCardActionResult(vCard);    
  }
}


It’s simple, it’s primitive but it makes writing of vCard returning actions more intuitive.

public async Task<IActionResult> Download() {    
  var vcard = new VCard();    
  vcard.FirstName = "Gunnar";    
  vcard.LastName = "Peipman";    
  vcard.Email = "gunnar@example.com";    
  vcard.City = "Tallinn";    
  vcard.CountryName = "Estonia";    
  vcard.Phone = "00-12345";    
  vcard.Mobile = "00-10101";    
  vcard.Organization = "Freelancer";    
  vcard.JobTitle = "Chief Everything Office";     
  vcard.Image = await System.IO.File.ReadAllBytesAsync("gunnar300.jpg");    
  
  return VCard(vcard);
}


The second annoying thing for me is the code that creates a VCard instance. It can be there in the controller, but I prefer to keep it somewhere else for reusability. Usually, vCard data comes from Customer, Person or Company classes. Let’s write a simple Customer class.

public class Customer {    
  public string FirstName { get; set; }    
  public string LastName { get; set; }    
  public string City { get; set; }    
  public string Country { get; set; }    
  public string Email { get; set; }    
  public string Mobile { get; set; }}


It’s up to the concrete solution to keep the following extension method that takes customer infomation and writes it to a vCard, but here’s the code.

public static class VCardExtensions {    
  public static VCard ToVCard(this Customer customer)    {        
    var vCard = new VCard();        
    vCard.City = customer.City;        
    vCard.CountryName = customer.Country;        
    vCard.Email = customer.Email;        
    vCard.Mobile = customer.Mobile;       
    vCard.FirstName = customer.FirstName;        
    vCard.LastName = customer.LastName;         
    
    return vCard;    
  }
}


Let’s rewrite the vCard controller action, so it uses the Customer class to get a step closer to real a scenario.

public async Task<IActionResult> vCard() {    
  var customer = new Customer    {        
    FirstName = "Gunnar",        
    LastName = "Peipman",        
    Email = "gunnar@example.com",        
    Mobile = "0012345",        
    City = "Tallinn",        
    Country = "Estonia"    };     
  
  var vcard = customer.ToVCard();    
  vcard.Image = await System.IO.File.ReadAllBytesAsync("gunnar300.jpg");     
  
  return VCard(vcard);
}


This is how our vCard controller action looks in practice.

public async Task<IActionResult> Download(int id) {    
  var customer = await _dataContext.Customers                                     .FirstOrDefaultAsync(c => c.Id == id);     if(customer == null)    {        return NotFound();    }     var vcard = customer.ToVCard();    vcard.Image = await System.IO.File.ReadAllBytesAsync("gunnar300.jpg");     return VCard(vcard);}

About using base controller. Don’t create base controller only to have nice VCard() method. If your application already uses base controller then it’s safe to add vCard() method there. If you don’t have base controller and you don’t plan to use it then just create new instance of vCardActionResult in actions that return vCard.

Wrapping Up

It wasn't hard to take an old vCard action result and update it. We added a VCard() method to the base controller to make it more intuitive for other developers to return vCard from controller actions. To better support real scenarios, we created the ToVCard() extension method that converts our Customer domain class to vCard. This blog post is a good starting point for your own vCard solution in .NET Core.

The post Creating vCard in ASP.NET Core appeared first on Gunnar Peipman - Programming Blog.

Topics:
web dev ,vcard ,asp.net ,c# ,tutorial

Published at DZone with permission of

Opinions expressed by DZone contributors are their own.

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}