Like many of my posts, this one comes from a student question in a training class. And as in many cases, the question prompts some digging, which results in me learning as much as the student. In this case, it became a lesson in doubling down on bad starting information.
The Original Question
How do I create an Action method in an MVC 5 application that automatically opens a downloaded Word document from the browser?
My First Answer
It’s easy!
Or so I thought. I could just create an Action method that returned an instance of the FileResult class. One of the required parameters of the method was the MIME type for the file. Not knowing what it was right off the top of my head, I looked up the MIME type for a Word document and decided to use application/vnd.openxmlformats-officedocument.wordprocessingml.document
Seems a bit verbose, I said, but who knows. From there, not being able to get anything else to work, I finally cobbled together this code that would prompt the browser to attempt to open a downloaded file using the Content-Disposition header set to the value of inline:
public ActionResult GetWordDocInline() { string fileName = "Word-File-Sample.docx"; Response.Headers.Set("Content-Disposition", "inline; filename=\"" + fileName + "\""); return File(@"\Documents\Word-File-Original.docx", "application/vnd.openxmlformats-officedocument.wordprocessingml.document" ); }
Unfortunately, without intervention from the user, that didn’t result in a file that opens automatically.
Hm. After some more exploration, it turns out that my MIME type value in the beginning was what caused the rest of my problems. Further research shows that using the much more simplified MIME type of application/msword does indeed allow the browser to behave in the predictable way we expect, given the documentation around the File() method– We just add the optional 3rd parameter (the downloaded file’s name) to prompt the browser to attempt opening the file (Which is the only difference between the 2 methods below:)
public ActionResult GetWordDocAttach() { return File(@"\Docs\SomeWordFile.docx", "application/msword"); } public ActionResult GetWordDocInline() { return File(@"\Docs\SomeWordFile.docx", "application/msword", "NewDownloadedFileName.docx" ); }
My Other Kinda Peripheral Answer
There’s a different way!
When I couldn’t make the original approach work, I tried a little side-hack which it turns out could be pretty useful to have the file open automatically, in the browser! In fact, the solution I found might even more flexible, because you don’t need to have Word installed, if you use Office Web Viewer. As the linked article describes:
To get there, your document must be publicly available on the Internet and the URL to the document needs to be properly URL encoded.
So here’s the controller action I made:
public ActionResult UseOfficeViewer() { //Doc in an Azure storage account Blob container set to allow //anonymous read access... string documentUrl = @"https://someAzureStorageAccount.blob.core.windows.net/" + "someBlobContainer/aDemoWordDoc.docx"; string officeViewerUrl = @"http://view.officeapps.live.com/op/view.aspx?src="; ViewBag.fullUrl = officeViewerUrl + documentUrl; return View(); }
If you wanted to take this a step further, parameterize the method to accept a file path instead of the one I’ve hardcoded in the documentUrl string. After that, it’s trivial to put a link in the View that opens the document:
//fullURL created by the Action method <a href="@ViewBag.fullUrl" target="_blank">Click here to display the doc</a>
You should get something like this in your browser… Note the buttons on the top right that allow the user to download the doc or send it to OneDrive (Click on the image to open it in a new tab)–
The Bottom Line
Maybe you knew about Office Web Viewer, but I didn’t, and even though my original mistake with the MIME type was painful (“banging my head against the screen” painful) to solve, it forced me to explore and find an alternate solution. This gives me options I didn’t know I had, like adding Azure code to dynamically upload Word docs to my Azure Storage Account, and then display them with Office Web Viewer.
The Moral of the Story (in Metaphor Form)
Not all wrong turns are created equal. Sometimes you end finding a cool new restaurant you didn’t know about. Or something like that. Metaphor is a dicey language construct. Use it at your discretion.
(Code examples use an MVC5 application in Visual Studio 2017 running on .NET Framework version 4.6.1, using a local installation of MS Word 2016)
No Comments Yet