This is what I ended up doing in my situation.
The controller code below consists of two actions. The first action returns a model I can use for setting the page title (this could just be a string depending on your use case). The second action is for getting the file contents. In my case I was storing the file contents in a database so I use an id to fetch the document.
The second action also sets the response headers so that the file name shows up properly when they try to download the file.
public IActionResult PreviewDocument(int id)
{
Document document = _legislationFolderService.GetDocument(id);
if (document == null)
return NotFound($"Could not find document with id of {id}");
return View(document);
}
public IActionResult PreviewDocumentContents(int id)
{
DocumentContents documentContents = _legislationFolderService.GetDocumentContents(id);
if (documentContents == null)
return NotFound($"Could not find contents for document with id of {id}");
Response.Headers.Add("Content-Disposition", $"inline; filename={documentContents.Document.Name}.pdf");
return new FileStreamResult(new MemoryStream(documentContents.Contents), "application/pdf");
}
In the view below (PreviewDocument.cshtml) I used an iframe to fill the page and link to the PreviewDocumentContents action. I didn't want the layout included from my main template so I set that to null and put up a basic html structure for the page, where I set the title right in the html.
@model EFloorFiles.Service.Models.Document
@{
Layout = null;
ViewBag.Title = Model.Name;
}
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>@ViewData["Title"] - E-Floor Files</title>
<style type="text/css">
body, html {
width: 100%;
height: 100%;
overflow: hidden;
margin: 0;
}
iframe {
width: 100%;
height: 100%;
border: none;
}
</style>
</head>
<body>
<iframe src="@Url.Action("PreviewDocumentContents", new { id = Model.Id })"></iframe>
</body>
</html>