Based on this answer: https://stackoverflow.com/a/2343089/3889469
I am having trouble serving up a vCard upon a form submit.
@using (Html.BeginRouteForm(MvcSettings.SitecoreRouteName, FormMethod.Post, new { name = "vCard_verify", @class = "vCardVerify" }))
{
@Html.AntiForgeryToken()
@Html.Sitecore().FormHandler("Content", "vCard")
@Html.Hidden("vCardGuid")
<div id="g-recaptcha-vCard"></div>
}
Controller Action:
[HttpPost]
[ValidateAntiForgeryToken]
public vCardResult vCard()
{
NameValueCollection formNvc = Request.Form;
string Guid = formNvc["vCardGuid"];
var context = new SitecoreContext();
var person = context.GetItem<Person>(Guid);
var card = new VCard
{
FirstName = person.First_Name,
LastName = person.Last_Name,
StreetAddress = "street",
City = "city",
State = "state",
Zip = "zip",
CountryName = "USA",
Organization = "Org",
JobTitle = person.Title,
Phone = person.Phone,
Fax = "Fax",
Image = "image",
HomePage = "google.com",
Email = person.Email_Address
};
return new vCardResult(card);
}
And
public class vCardResult : ActionResult
{
private VCard _card;
protected vCardResult() { }
public vCardResult(VCard card)
{
_card = card;
}
public override void ExecuteResult(ControllerContext context)
{
var response = HttpContext.Current.Response; // context.HttpContext.Response;
response.ContentType = "text/vcard";
response.AddHeader("Content-Disposition", "attachment; fileName=" + _card.FirstName + " " + _card.LastName + ".vcf");
var cardString = _card.ToString();
var inputEncoding = Encoding.Default;
var outputEncoding = Encoding.GetEncoding("windows-1257");
var cardBytes = inputEncoding.GetBytes(cardString);
var outputBytes = Encoding.Convert(inputEncoding,
outputEncoding, cardBytes);
response.BinaryWrite(outputBytes);
//response.OutputStream.Write(outputBytes, 0, outputBytes.Length);
//response.End();
}
}
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 State { get; set; }
public string CountryName { get; set; }
public string Phone { get; set; }
public string Fax { get; set; }
public string Email { get; set; }
public string HomePage { get; set; }
public string Image { get; set; }
public override string ToString()
{
var builder = new StringBuilder();
builder.AppendLine("BEGIN:VCARD");
builder.AppendLine("VERSION:4.0");
// Name
builder.AppendLine("N:" + LastName + ";" + FirstName + ";;;");
// Full name
builder.AppendLine("FN:" + FirstName + " " + LastName);
//Company
builder.AppendLine("ORG:" + Organization);
//Title
builder.AppendLine("TITLE:" + JobTitle);
//Phone
builder.AppendLine("TEL;TYPE=work:" + Phone);
//Fax
builder.AppendLine("TEL;TYPE=fax:" + Fax);
// Address
builder.Append("ADR;TYPE=work;LABEL=\"" + StreetAddress + "\n" + City + ", " + State + " " + Zip + "\n" + CountryName + "\":;;");
builder.Append(StreetAddress + ";");
builder.Append(City + ";");
builder.Append(State + ";");
builder.Append(Zip + ";");
builder.AppendLine(CountryName);
// Photo
builder.AppendLine("PHOTO; MEDIATYPE = image / png:" + Image);
//Site
builder.AppendLine("URL;" + HomePage);
//Email
builder.AppendLine("EMAIL:" + Email);
builder.AppendLine("END:VCARD");
return builder.ToString();
}
}
The error I get is: OutputStream is not available when a custom TextWriter is used. I believe that the headers were already sent before my action gets called, however I am not sure what the alternative is? How do I force a download of a file and still load the current page using Sitecore 8 MVC?