Generating a document using OpenXml and returning it from code-behind looks trivial but it's not! I lost many hours searching on Internet to understand why my accents are obfuscated.
After many unsuccessful attempts, I arrive to this code: SPEncode.UrlEncode() But wait… I don't always work with SharePoint… another solution was given by Rick Strahl: Uri.EscapeDataString
The accent problem only occurs when working with IE. Others browsers seems to handle the encoding fine.
Other problems encountered: Office Word cannot download the document if SSL is used. But this time, it seems to be a known bug.
public void SetContentType(System.Web.HttpRequest request, System.Web.HttpResponse response, String reportName)
{
if (reportName.Length > 128) reportName = reportName.Substring(0, 128);
string encodedFilename = reportName.Replace(';', ' ');
if (request.Browser.Browser.Contains("IE"))
{
// Replace the %20 to obtain a clean name when saving the file from Word.
encodedFilename =
Uri.EscapeDataString(Path.GetFileNameWithoutExtension(encodedFilename)).Replace("%20", " ")
+ Path.GetExtension(encodedFilename);
}
// use the correct content-type (not 'application/msword') or FF will append .doc to the filename
response.AppendHeader("Content-Disposition", "attachment;filename=\"" + encodedFilename + "\"");
if (reportName.EndsWith(".docx"))
response.ContentType = "application/vnd.ms-word.document";
else
response.ContentType = "application/vnd.ms-word.template";
// IE cannot download an MS Office document from a website using SSL if the response
// contains HTTP headers such as: Pragram: no-cache and/or Cache-controo: no-cache,max-age=0,must-revalidate
// http://support.microsoft.com/kb/316431/
if (!(request.IsSecureConnection && request.Browser.Browser.Contains("IE")))
response.Cache.SetCacheability(System.Web.HttpCacheability.NoCache);
}
That's it for the cosmetic part of the generation. Now, let's deal with a minimal empty document, generated from scratch:
using (WordprocessingDocument package = WordprocessingDocument.Create(generatedStream, WordprocessingDocumentType.Document))
{
MainDocumentPart mainPart = package.AddMainDocumentPart();
new Document(new Body()).Save(mainPart);
Body body = mainPart.Document.Body;
body.Append(new Paragraph(
new Run(
new Text("Hello World!"))));
mainPart.Document.Save();
}
You cannot write a smaller code!
Now we will output the document stream to the asp.net response. Put the next code in your Page or IHttpHandler
using(MemoryStream generatedStream = new MemoryStream())
{
CreateDocument(generatedStream);
SetContentType(context.Request, context.Response, "Modèle par défaut.docx");
generatedStream.WriteTo(context.Response.OutputStream);
context.Response.Flush();
}
And you will obtain:

