How to save the resulting HTML as a string instead of writing to the browser using the Razor viewer?

I created a website using MVC3 along with the Razor view engine. I want to make the resulting HTML and save it in a stream or line so that I can write it to a file, and not write to the browser.

I need to make the resulting HTML and convert it to PDF and provide PDF to the user as a reporting form. I already have this part, I just can’t figure out how best to embed HTML in some kind of variable.

EDIT . I ended up in a different direction and wanted to share the results. I created an attribute that uses the WKHTMLTOPDF project to convert a stream to a PDF. Now all I do is add an attribute to the action and instead of displaying the HTML in the browser, it opens the save dialog as.

public class PdfInterceptAttribute : ActionFilterAttribute { public override void OnResultExecuted(ResultExecutedContext filterContext) { var viewResult = filterContext.Result as ViewResult; var workingDir = ConfigurationManager.AppSettings["PdfWorkingPath"]; var fileName = workingDir + @"\" + Guid.NewGuid() + ".pdf"; if (viewResult != null) { var view = viewResult.View; var writer = new StringWriter(); var viewContext = new ViewContext(filterContext.Controller.ControllerContext, view, viewResult.ViewData, viewResult.TempData, writer); view.Render(viewContext, writer); HtmlToPdf(new StringBuilder(writer.ToString()), fileName); filterContext.HttpContext.Response.Clear(); var pdfByte = File.ReadAllBytes(fileName); filterContext.HttpContext.Response.ContentType = "application/pdf"; filterContext.HttpContext.Response.AddHeader("Content-Disposition", "attachment; filename=Report.pdf"); filterContext.HttpContext.Response.BinaryWrite(pdfByte); filterContext.HttpContext.Response.End(); } base.OnResultExecuted(filterContext); } private static bool HtmlToPdf(StringBuilder file, string fileName) { // assemble destination PDF file name var workingDir = ConfigurationManager.AppSettings["PdfWorkingPath"]; var exePath = ConfigurationManager.AppSettings["PdfExePath"]; //Path to the WKHTMLTOPDF executable. var p = new Process { StartInfo = {FileName = @"""" + exePath + @""""} }; var switches = "--print-media-type "; switches += "--margin-top 4mm --margin-bottom 4mm --margin-right 0mm --margin-left 0mm "; switches += "--page-size A4 "; p.StartInfo.Arguments = switches + " " + "-" + " " + fileName; p.StartInfo.UseShellExecute = false; // needs to be false in order to redirect output p.StartInfo.RedirectStandardOutput = true; //p.StartInfo.RedirectStandardError = true; p.StartInfo.RedirectStandardInput = true; // redirect all 3, as it should be all 3 or none p.StartInfo.WorkingDirectory = workingDir; p.Start(); var sw = p.StandardInput; sw.Write(file.ToString()); sw.Close(); // read the output here... string output = p.StandardOutput.ReadToEnd(); // ...then wait n milliseconds for exit (as after exit, it can't read the output) p.WaitForExit(60000); // read the exit code, close process int returnCode = p.ExitCode; p.Close(); // if 0 or 2, it worked (not sure about other values, I want a better way to confirm this) return (returnCode <= 2); } } 
+4
source share
2 answers

I am using this code:

 private string RenderView<TModel>(string viewPath, TModel model, TempDataDictionary tempData = null) { var view = new RazorView( ControllerContext, viewPath: viewPath, layoutPath: null, runViewStartPages: false, viewStartFileExtensions: null ); var writer = new StringWriter(); var viewContext = new ViewContext(ControllerContext, view, new ViewDataDictionary<TModel>(model), tempData ?? new TempDataDictionary(), writer); view.Render(viewContext, writer); return writer.ToString(); } 

The current ControllerContext used here; if you don't want this, you need to make fun of HttpContextBase .

If you want to pass data from a view, you need to pass it to TempData , not the ViewBag .

+5
source

Source: https://habr.com/ru/post/1341707/


All Articles