From f33122e13d3907ad95cd2470fe675308e809d423 Mon Sep 17 00:00:00 2001 From: Mike Phares Date: Wed, 28 May 2025 12:40:38 -0700 Subject: [PATCH] Removed PdfViewController, HtmlViewRenderer and FakeView to be replaced with ViewEngineResult Render method --- .../Controllers/ECNController.cs | 51 +- .../Controllers/LotTravelerController.cs | 51 +- Fab2ApprovalSystem/Fab2ApprovalSystem.csproj | 3 - .../PdfGenerator/BinaryContentResult.cs | 66 +- Fab2ApprovalSystem/PdfGenerator/FakeView.cs | 28 - .../PdfGenerator/HtmlViewRenderer.cs | 49 - .../PdfGenerator/PdfViewController.cs | 54 - .../PdfGenerator/PrintHeaderFooter.cs | 147 +-- .../PdfGenerator/StandardPdfRenderer.cs | 41 +- Fab2ApprovalSystem/Views/ECN/ECNPdf.cshtml | 975 +++++++++--------- 10 files changed, 690 insertions(+), 775 deletions(-) delete mode 100644 Fab2ApprovalSystem/PdfGenerator/FakeView.cs delete mode 100644 Fab2ApprovalSystem/PdfGenerator/HtmlViewRenderer.cs delete mode 100644 Fab2ApprovalSystem/PdfGenerator/PdfViewController.cs diff --git a/Fab2ApprovalSystem/Controllers/ECNController.cs b/Fab2ApprovalSystem/Controllers/ECNController.cs index b0541e4..f8fe79c 100644 --- a/Fab2ApprovalSystem/Controllers/ECNController.cs +++ b/Fab2ApprovalSystem/Controllers/ECNController.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.Configuration; +using System.IO; using System.Linq; using System.Web; using System.Web.Mvc; @@ -21,7 +22,7 @@ namespace Fab2ApprovalSystem.Controllers; [Authorize] [OutputCache(NoStore = true, Duration = 0, VaryByParam = "*")] [SessionExpireFilter] -public class ECNController : PdfViewController { +public class ECNController : Controller { private const string ECN_PREFIX = "ECN_"; private const string TECN_PREFIX = "TECN_"; @@ -669,9 +670,6 @@ public class ECNController : PdfViewController { } } - /// - /// Get a list of Approvers and the status - /// public ActionResult GetApproversList([DataSourceRequest] DataSourceRequest request, int issueID, byte step, bool isTECN, bool isEmergrncyTECN) { int isITARCompliant = 0; ECN ecn = new ECN(); @@ -893,10 +891,12 @@ public class ECNController : PdfViewController { if (!di.Exists) di.Create(); - // To render a PDF instead of an HTML, all we need to do is call ViewPdf instead of View. This - // requires the controller to be inherited from MyController instead of MVC's Controller. - SavePdf(ecnFolderPath + "\\ECNForm_" + outputFileName, "ECNPdf", ecn); - SavePdf(ecnFolderPath + "\\ECNApprovalLog_" + outputFileName, "ECNApprovalPdf", ecn); + string htmlText; + string pageTitle = string.Empty; + htmlText = RenderViewToString("ECNPdf", ecn); + StandardPdfRenderer.WritePortableDocumentFormatToFile(pageTitle, htmlText, $"{ecnFolderPath}\\ECNForm_{outputFileName}"); + htmlText = RenderViewToString("ECNApprovalPdf", ecn); + StandardPdfRenderer.WritePortableDocumentFormatToFile(pageTitle, htmlText, $"{ecnFolderPath}\\ECNApprovalLog_{outputFileName}"); } catch (Exception ex) { EventLogDMO.Add(new WinEventLog() { IssueID = ecnNumber, UserID = @User.Identity.Name, DocumentType = "ECN", OperationType = "Generate PDF", Comments = ex.Message }); ecn = null; @@ -906,6 +906,24 @@ public class ECNController : PdfViewController { return true; } + private string RenderViewToString(string viewName, ECNPdf ecnPdf) { + string result; + ViewData.Model = ecnPdf; + using (StringWriter writer = new()) { + try { + ViewEngineResult viewResult = ViewEngines.Engines.FindView(ControllerContext, viewName, string.Empty); + if (viewResult is null) + return $"A view with the name '{viewName}' could not be found"; + ViewContext viewContext = new(ControllerContext, viewResult.View, ViewData, TempData, writer); + viewResult.View.Render(viewContext, writer); + result = writer.GetStringBuilder().ToString(); + } catch (Exception ex) { + result = $"Failed - {ex.Message}"; + } + } + return result; + } + public bool GenerateECNPdfDifferentLocation(int ecnNumber, int folderName) { ECNPdf ecn = new ECNPdf(); try { @@ -923,9 +941,9 @@ public class ECNController : PdfViewController { if (!di.Exists) di.Create(); - // To render a PDF instead of an HTML, all we need to do is call ViewPdf instead of View. This - // requires the controller to be inherited from MyController instead of MVC's Controller. - SavePdf(ecnFolderPath + "\\ECNForm_" + outputFileName, "ECNPdf", ecn); + string pageTitle = string.Empty; + string htmlText = RenderViewToString("ECNPdf", ecn); + StandardPdfRenderer.WritePortableDocumentFormatToFile(pageTitle, htmlText, $"{ecnFolderPath}\\ECNForm_{outputFileName}"); } catch (Exception ex) { EventLogDMO.Add(new WinEventLog() { IssueID = ecnNumber, UserID = @User.Identity.Name, DocumentType = "ECN", OperationType = "Generate PDF", Comments = ex.Message }); ecn = null; @@ -941,9 +959,14 @@ public class ECNController : PdfViewController { ecn = ecnDMO.GetECNPdf(ecnNumber); ViewBag.Category = ecnDMO.GetCategoryID(ecn); ViewBag.TrainingNotificationTo = ecnDMO.GetTrainingNotificationTo(ecn, trainingDMO); - // To render a PDF instead of an HTML, all we need to do is call ViewPdf instead of View. This - // requires the controller to be inherited from MyController instead of MVC's Controller. - return this.ViewPdf("", "ECNPdf", ecn); + string pageTitle = string.Empty; + string htmlText = RenderViewToString("ECNPdf", ecn); + if (System.Diagnostics.Debugger.IsAttached) { + return Content(htmlText, "text/html"); + } else { + byte[] buffer = StandardPdfRenderer.GetPortableDocumentFormatBytes(pageTitle, htmlText); + return new BinaryContentResult(buffer, "application/pdf"); + } } catch (Exception ex) { EventLogDMO.Add(new WinEventLog() { IssueID = ecnNumber, UserID = @User.Identity.Name, DocumentType = "ECN", OperationType = "Print PDF", Comments = ex.Message }); ecn = null; diff --git a/Fab2ApprovalSystem/Controllers/LotTravelerController.cs b/Fab2ApprovalSystem/Controllers/LotTravelerController.cs index b1503d7..d54deb1 100644 --- a/Fab2ApprovalSystem/Controllers/LotTravelerController.cs +++ b/Fab2ApprovalSystem/Controllers/LotTravelerController.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.Configuration; +using System.IO; using System.Linq; using System.Threading; using System.Web; @@ -20,7 +21,7 @@ namespace Fab2ApprovalSystem.Controllers; [Authorize] [OutputCache(NoStore = true, Duration = 0, VaryByParam = "*")] [SessionExpireFilter] -public class LotTravelerController : PdfViewController { +public class LotTravelerController : Controller { LotTravelerDMO LotTravDMO = new LotTravelerDMO(); string docTypeString = "LotTraveler"; @@ -199,9 +200,14 @@ public class LotTravelerController : PdfViewController { try { workRequest = LotTravDMO.GetLTWorkRequestItemPDF(workRequestID); - // To render a PDF instead of an HTML, all we need to do is call ViewPdf instead of View. This - // requires the controller to be inherited from MyController instead of MVC's Controller. - return this.ViewPdf("", "WorkRequestPDF", workRequest); + string pageTitle = string.Empty; + string htmlText = RenderViewToString("WorkRequestPDF", workRequest); + if (System.Diagnostics.Debugger.IsAttached) { + return Content(htmlText, "text/html"); + } else { + byte[] buffer = StandardPdfRenderer.GetPortableDocumentFormatBytes(pageTitle, htmlText); + return new BinaryContentResult(buffer, "application/pdf"); + } } catch (Exception ex) { Functions.WriteEvent(_AppSettings, @User.Identity.Name + "\r\n DisplayWorkRequestPDF - LotTraveler\r\n" + ex.InnerException.ToString(), System.Diagnostics.EventLogEntryType.Error); EventLogDMO.Add(new WinEventLog() { IssueID = workRequest.SWRNumber, UserID = @User.Identity.Name, DocumentType = "LotTravler", OperationType = "Generate PDF", Comments = ex.Message }); @@ -210,6 +216,24 @@ public class LotTravelerController : PdfViewController { } } + private string RenderViewToString(string viewName, object model) { + string result; + ViewData.Model = model; + using (StringWriter writer = new()) { + try { + ViewEngineResult viewResult = ViewEngines.Engines.FindView(ControllerContext, viewName, string.Empty); + if (viewResult is null) + return $"A view with the name '{viewName}' could not be found"; + ViewContext viewContext = new(ControllerContext, viewResult.View, ViewData, TempData, writer); + viewResult.View.Render(viewContext, writer); + result = writer.GetStringBuilder().ToString(); + } catch (Exception ex) { + result = $"Failed - {ex.Message}"; + } + } + return result; + } + public ActionResult WorkRequestRevision(int workRequestID) { int isITARCompliant = 1; LTWorkRequest workRequest = new LTWorkRequest(); @@ -251,9 +275,7 @@ public class LotTravelerController : PdfViewController { return Content("Successfully Saved"); } - /// - /// - /// + public JsonResult GetBaseFlowLocations(string baseFlow) { List loclist = LotTravDMO.GetBaseFlowLocations(baseFlow); return Json(loclist, JsonRequestBehavior.AllowGet); @@ -332,9 +354,6 @@ public class LotTravelerController : PdfViewController { return Content(newWorkRequestID.ToString()); } - /// - /// For the Revison - /// public ActionResult UpdateMaterialDetailRevision(LTWorkRequest model) { var modelMaterialDetail = model.LTMaterial; int previousMaterialID = model.LTMaterial.ID; @@ -1232,15 +1251,19 @@ public class LotTravelerController : PdfViewController { LotTravDMO.DeleteLot(ltLotID); } - /// public ActionResult DisplayLotTravlerPdf(int ltLotID, int revisionNumber) { LotTravelerPdf traveler = new LotTravelerPdf(); try { traveler = LotTravDMO.GetLotTravlerPdf(ltLotID, revisionNumber); - // To render a PDF instead of an HTML, all we need to do is call ViewPdf instead of View. This - // requires the controller to be inherited from MyController instead of MVC's Controller. - return this.ViewPdf("", "LotTravelerPDF", traveler); + string pageTitle = string.Empty; + string htmlText = RenderViewToString("LotTravelerPDF", traveler); + if (System.Diagnostics.Debugger.IsAttached) { + return Content(htmlText, "text/html"); + } else { + byte[] buffer = StandardPdfRenderer.GetPortableDocumentFormatBytes(pageTitle, htmlText); + return new BinaryContentResult(buffer, "application/pdf"); + } } catch (Exception ex) { EventLogDMO.Add(new WinEventLog() { IssueID = traveler.SWRNumber, UserID = @User.Identity.Name, DocumentType = "LotTraveler", OperationType = "Generate PDF", Comments = ex.Message }); traveler = null; diff --git a/Fab2ApprovalSystem/Fab2ApprovalSystem.csproj b/Fab2ApprovalSystem/Fab2ApprovalSystem.csproj index 6a98c01..135d7d2 100644 --- a/Fab2ApprovalSystem/Fab2ApprovalSystem.csproj +++ b/Fab2ApprovalSystem/Fab2ApprovalSystem.csproj @@ -325,9 +325,6 @@ - - - diff --git a/Fab2ApprovalSystem/PdfGenerator/BinaryContentResult.cs b/Fab2ApprovalSystem/PdfGenerator/BinaryContentResult.cs index ba08fc7..0efa5f3 100644 --- a/Fab2ApprovalSystem/PdfGenerator/BinaryContentResult.cs +++ b/Fab2ApprovalSystem/PdfGenerator/BinaryContentResult.cs @@ -1,43 +1,43 @@ #if !NET8 +using System.Web; +using System.Web.Mvc; +using System.Web.Security; +#endif -// -------------------------------------------------------------------------------------------------------------------- -// -// http://www.SemanticArchitecture.net pkalkie@gmail.com -// -// -// An ActionResult used to send binary data to the browser. -// -// -------------------------------------------------------------------------------------------------------------------- +#if !NET8 +using System; +using System.Collections.Generic; +using System.Net; +using System.Net.Http; +using System.Security.Claims; +using System.Threading.Tasks; +using System.IO; +#endif -namespace Fab2ApprovalSystem.PdfGenerator { - using System.IO; - using System.Web; - using System.Web.Mvc; +namespace Fab2ApprovalSystem.PdfGenerator; - /// - /// An ActionResult used to send binary data to the browser. - /// - public class BinaryContentResult : ActionResult { - private readonly string contentType; - private readonly byte[] contentBytes; +public class BinaryContentResult : ActionResult { + private readonly string contentType; + private readonly byte[] contentBytes; - public BinaryContentResult(byte[] contentBytes, string contentType) { - this.contentBytes = contentBytes; - this.contentType = contentType; - } + public BinaryContentResult(byte[] contentBytes, string contentType) { + this.contentBytes = contentBytes; + this.contentType = contentType; + } - public override void ExecuteResult(ControllerContext context) { - var response = context.HttpContext.Response; - response.Clear(); - response.Cache.SetCacheability(HttpCacheability.Public); - response.ContentType = this.contentType; +#if !NET8 + public override void ExecuteResult(ControllerContext context) { + var response = context.HttpContext.Response; + response.Clear(); + response.Cache.SetCacheability(HttpCacheability.Public); + response.ContentType = contentType; - using (var stream = new MemoryStream(this.contentBytes)) { - stream.WriteTo(response.OutputStream); - stream.Flush(); - } + using (var stream = new MemoryStream(contentBytes)) { + stream.WriteTo(response.OutputStream); + stream.Flush(); } } -} -#endif \ No newline at end of file +#endif + +} \ No newline at end of file diff --git a/Fab2ApprovalSystem/PdfGenerator/FakeView.cs b/Fab2ApprovalSystem/PdfGenerator/FakeView.cs deleted file mode 100644 index 1aff427..0000000 --- a/Fab2ApprovalSystem/PdfGenerator/FakeView.cs +++ /dev/null @@ -1,28 +0,0 @@ -#if !NET8 - -// -------------------------------------------------------------------------------------------------------------------- -// -// http://www.SemanticArchitecture.net pkalkie@gmail.com -// -// -// Defines the FakeView type. -// -// -------------------------------------------------------------------------------------------------------------------- - -namespace Fab2ApprovalSystem.PdfGenerator { - using System; - using System.IO; - using System.Web.Mvc; - - public class FakeView : IView { - #region IView Members - - public void Render(ViewContext viewContext, TextWriter writer) { - throw new NotImplementedException(); - } - - #endregion - } -} - -#endif \ No newline at end of file diff --git a/Fab2ApprovalSystem/PdfGenerator/HtmlViewRenderer.cs b/Fab2ApprovalSystem/PdfGenerator/HtmlViewRenderer.cs deleted file mode 100644 index d3ba69d..0000000 --- a/Fab2ApprovalSystem/PdfGenerator/HtmlViewRenderer.cs +++ /dev/null @@ -1,49 +0,0 @@ -#if !NET8 - -// -------------------------------------------------------------------------------------------------------------------- -// -// http://www.SemanticArchitecture.net pkalkie@gmail.com -// -// -// This class is responsible for rendering a HTML view to a string. -// -// -------------------------------------------------------------------------------------------------------------------- - -namespace Fab2ApprovalSystem.PdfGenerator { - using System.IO; - using System.Text; - using System.Web; - using System.Web.Mvc; - using System.Web.Mvc.Html; - - /// - /// This class is responsible for rendering a HTML view into a string. - /// - public class HtmlViewRenderer { - public string RenderViewToString(Controller controller, string viewName, object viewData) { - var renderedView = new StringBuilder(); - using (var responseWriter = new StringWriter(renderedView)) { - var fakeResponse = new HttpResponse(responseWriter); - var fakeContext = new HttpContext(HttpContext.Current.Request, fakeResponse); - var fakeControllerContext = new ControllerContext(new HttpContextWrapper(fakeContext), controller.ControllerContext.RouteData, controller.ControllerContext.Controller); - - var oldContext = HttpContext.Current; - HttpContext.Current = fakeContext; - - using (var viewPage = new ViewPage()) { - var html = new HtmlHelper(CreateViewContext(responseWriter, fakeControllerContext), viewPage); - html.RenderPartial(viewName, viewData); - HttpContext.Current = oldContext; - } - } - - return renderedView.ToString(); - } - - private static ViewContext CreateViewContext(TextWriter responseWriter, ControllerContext fakeControllerContext) { - return new ViewContext(fakeControllerContext, new FakeView(), new ViewDataDictionary(), new TempDataDictionary(), responseWriter); - } - } -} - -#endif \ No newline at end of file diff --git a/Fab2ApprovalSystem/PdfGenerator/PdfViewController.cs b/Fab2ApprovalSystem/PdfGenerator/PdfViewController.cs deleted file mode 100644 index f55bdef..0000000 --- a/Fab2ApprovalSystem/PdfGenerator/PdfViewController.cs +++ /dev/null @@ -1,54 +0,0 @@ -#if !NET8 - -// -------------------------------------------------------------------------------------------------------------------- -// -// http://www.SemanticArchitecture.net pkalkie@gmail.com -// -// -// Extends the controller with functionality for rendering PDF views -// -// -------------------------------------------------------------------------------------------------------------------- - -namespace Fab2ApprovalSystem.PdfGenerator { - using System.Web.Mvc; - using System.IO; - - /// - /// Extends the controller with functionality for rendering PDF views - /// - public class PdfViewController : Controller { - private readonly HtmlViewRenderer htmlViewRenderer; - private readonly StandardPdfRenderer standardPdfRenderer; - - public PdfViewController() { - this.htmlViewRenderer = new HtmlViewRenderer(); - this.standardPdfRenderer = new StandardPdfRenderer(); - } - - protected ActionResult ViewPdf(string pageTitle, string viewName, object model) { - // Render the view html to a string. - string htmlText = this.htmlViewRenderer.RenderViewToString(this, viewName, model); - - // Let the html be rendered into a PDF document through iTextSharp. - byte[] buffer = standardPdfRenderer.Render(htmlText, pageTitle); - - // Return the PDF as a binary stream to the client. - return new BinaryContentResult(buffer, "application/pdf"); - } - - protected void SavePdf(string fileName, string viewName, object model) { - // Render the view html to a string. - string htmlText = this.htmlViewRenderer.RenderViewToString(this, viewName, model); - - // Let the html be rendered into a PDF document through iTextSharp. - byte[] buffer = standardPdfRenderer.Render(htmlText, ""); - - using (FileStream fs = new FileStream(fileName, FileMode.Create)) { - fs.Write(buffer, 0, buffer.Length); - } - - } - } -} - -#endif \ No newline at end of file diff --git a/Fab2ApprovalSystem/PdfGenerator/PrintHeaderFooter.cs b/Fab2ApprovalSystem/PdfGenerator/PrintHeaderFooter.cs index 00322fc..23af4ef 100644 --- a/Fab2ApprovalSystem/PdfGenerator/PrintHeaderFooter.cs +++ b/Fab2ApprovalSystem/PdfGenerator/PrintHeaderFooter.cs @@ -1,79 +1,102 @@ +#if !NET8 +using System.Web; +using System.Web.Mvc; +using System.Web.Security; +#endif #if !NET8 -namespace Fab2ApprovalSystem.PdfGenerator { - using iTextSharp.text; - using iTextSharp.text.pdf; +using iTextSharp.text; +using iTextSharp.text.pdf; +#endif - using System; +#if !NET8 +using System; +using System.Collections.Generic; +using System.Net; +using System.Net.Http; +using System.Security.Claims; +using System.Threading.Tasks; +#endif - /// - /// This class represents the standard header and footer for a PDF print. - /// application. - /// - public class PrintHeaderFooter : PdfPageEventHelper { - private PdfContentByte pdfContent; - private PdfTemplate pageNumberTemplate; - private BaseFont baseFont; - private DateTime printTime; +namespace Fab2ApprovalSystem.PdfGenerator; - public string Title { get; set; } +#if !NET8 - public override void OnOpenDocument(PdfWriter writer, Document document) { - printTime = DateTime.Now; - baseFont = BaseFont.CreateFont(BaseFont.HELVETICA, BaseFont.CP1252, BaseFont.NOT_EMBEDDED); - pdfContent = writer.DirectContent; - pageNumberTemplate = pdfContent.CreateTemplate(50, 50); - } +public class PrintHeaderFooter : PdfPageEventHelper { - public override void OnStartPage(PdfWriter writer, Document document) { - base.OnStartPage(writer, document); + private PdfContentByte pdfContent; + private PdfTemplate pageNumberTemplate; + private BaseFont baseFont; + private DateTime printTime; +#endif - Rectangle pageSize = document.PageSize; +#if NET8 - if (Title != string.Empty) { - pdfContent.BeginText(); - pdfContent.SetFontAndSize(baseFont, 11); - pdfContent.SetRGBColorFill(0, 0, 0); - pdfContent.SetTextMatrix(pageSize.GetLeft(40), pageSize.GetTop(40)); - pdfContent.ShowText(Title); - pdfContent.EndText(); - } - } +public class PrintHeaderFooter { - public override void OnEndPage(PdfWriter writer, Document document) { - base.OnEndPage(writer, document); +#endif - int pageN = writer.PageNumber; - string text = pageN + " - "; - float len = baseFont.GetWidthPoint(text, 8); + public string Title { get; set; } - Rectangle pageSize = document.PageSize; - pdfContent = writer.DirectContent; - pdfContent.SetRGBColorFill(100, 100, 100); +#if !NET8 + public override void OnOpenDocument(PdfWriter writer, Document document) { + printTime = DateTime.Now; + baseFont = BaseFont.CreateFont(BaseFont.HELVETICA, BaseFont.CP1252, BaseFont.NOT_EMBEDDED); + pdfContent = writer.DirectContent; + pageNumberTemplate = pdfContent.CreateTemplate(50, 50); + } + + public override void OnStartPage(PdfWriter writer, Document document) { + base.OnStartPage(writer, document); + + Rectangle pageSize = document.PageSize; + + if (Title != string.Empty) { pdfContent.BeginText(); - pdfContent.SetFontAndSize(baseFont, 8); - pdfContent.SetTextMatrix(pageSize.Width / 2, pageSize.GetBottom(30)); - pdfContent.ShowText(text); + pdfContent.SetFontAndSize(baseFont, 11); + pdfContent.SetRGBColorFill(0, 0, 0); + pdfContent.SetTextMatrix(pageSize.GetLeft(40), pageSize.GetTop(40)); + pdfContent.ShowText(Title); pdfContent.EndText(); - - pdfContent.AddTemplate(pageNumberTemplate, (pageSize.Width / 2) + len, pageSize.GetBottom(30)); - - pdfContent.BeginText(); - pdfContent.SetFontAndSize(baseFont, 8); - pdfContent.ShowTextAligned(PdfContentByte.ALIGN_RIGHT, printTime.ToString(), pageSize.GetRight(40), pageSize.GetBottom(30), 0); - pdfContent.EndText(); - } - - public override void OnCloseDocument(PdfWriter writer, Document document) { - base.OnCloseDocument(writer, document); - - pageNumberTemplate.BeginText(); - pageNumberTemplate.SetFontAndSize(baseFont, 8); - pageNumberTemplate.SetTextMatrix(0, 0); - pageNumberTemplate.ShowText(string.Empty + (writer.PageNumber - 1)); - pageNumberTemplate.EndText(); } } -} -#endif \ No newline at end of file + + public override void OnEndPage(PdfWriter writer, Document document) { + base.OnEndPage(writer, document); + + int pageN = writer.PageNumber; + string text = pageN + " - "; + float len = baseFont.GetWidthPoint(text, 8); + + Rectangle pageSize = document.PageSize; + pdfContent = writer.DirectContent; + pdfContent.SetRGBColorFill(100, 100, 100); + + pdfContent.BeginText(); + pdfContent.SetFontAndSize(baseFont, 8); + pdfContent.SetTextMatrix(pageSize.Width / 2, pageSize.GetBottom(30)); + pdfContent.ShowText(text); + pdfContent.EndText(); + + pdfContent.AddTemplate(pageNumberTemplate, (pageSize.Width / 2) + len, pageSize.GetBottom(30)); + + pdfContent.BeginText(); + pdfContent.SetFontAndSize(baseFont, 8); + pdfContent.ShowTextAligned(PdfContentByte.ALIGN_RIGHT, printTime.ToString(), pageSize.GetRight(40), pageSize.GetBottom(30), 0); + pdfContent.EndText(); + } + + public override void OnCloseDocument(PdfWriter writer, Document document) { + base.OnCloseDocument(writer, document); + + pageNumberTemplate.BeginText(); + pageNumberTemplate.SetFontAndSize(baseFont, 8); + pageNumberTemplate.SetTextMatrix(0, 0); + pageNumberTemplate.ShowText(string.Empty + (writer.PageNumber - 1)); + pageNumberTemplate.EndText(); + } + +#endif + +} \ No newline at end of file diff --git a/Fab2ApprovalSystem/PdfGenerator/StandardPdfRenderer.cs b/Fab2ApprovalSystem/PdfGenerator/StandardPdfRenderer.cs index 27b0946..2ae98e3 100644 --- a/Fab2ApprovalSystem/PdfGenerator/StandardPdfRenderer.cs +++ b/Fab2ApprovalSystem/PdfGenerator/StandardPdfRenderer.cs @@ -8,20 +8,34 @@ using System.IO; namespace Fab2ApprovalSystem.PdfGenerator; -/// -/// This class is responsible for rendering a html text string to a PDF document using the html renderer of iTextSharp. -/// public class StandardPdfRenderer { + private const int HorizontalMargin = 40; private const int VerticalMargin = 40; - public byte[] Render(string htmlText, string pageTitle) { - byte[] renderedBuffer; + public static byte[] GetPortableDocumentFormatBytes(string pageTitle, string htmlText) { + byte[] results; + using (MemoryStream memoryStream = GetPortableDocumentFormat(pageTitle, htmlText)) { + results = new byte[memoryStream.Position]; + memoryStream.Position = 0; + memoryStream.Read(results, 0, results.Length); + } + return results; + } - using (MemoryStream outputMemoryStream = new()) { + public static void WritePortableDocumentFormatToFile(string pageTitle, string htmlText, string path) { + using (MemoryStream memoryStream = GetPortableDocumentFormat(pageTitle, htmlText)) { + using (FileStream fileStream = new(path, FileMode.Create)) { + memoryStream.CopyTo(fileStream); + } + } + } + + public static MemoryStream GetPortableDocumentFormat(string pageTitle, string htmlText) { + MemoryStream result = new(); #if !NET8 - using (Document pdfDocument = new Document(PageSize.A4, HorizontalMargin, HorizontalMargin, VerticalMargin, VerticalMargin)) { - PdfWriter pdfWriter = PdfWriter.GetInstance(pdfDocument, outputMemoryStream); + using (Document pdfDocument = new Document(PageSize.A4, HorizontalMargin, HorizontalMargin, VerticalMargin, VerticalMargin)) { + using (PdfWriter pdfWriter = PdfWriter.GetInstance(pdfDocument, result)) { pdfWriter.CloseStream = false; pdfWriter.PageEvent = new PrintHeaderFooter { Title = pageTitle }; pdfDocument.Open(); @@ -30,15 +44,10 @@ public class StandardPdfRenderer { htmlWorker.Parse(htmlViewReader); } } - } -#endif - - renderedBuffer = new byte[outputMemoryStream.Position]; - outputMemoryStream.Position = 0; - outputMemoryStream.Read(renderedBuffer, 0, renderedBuffer.Length); } - - return renderedBuffer; +#endif + return result; } + } \ No newline at end of file diff --git a/Fab2ApprovalSystem/Views/ECN/ECNPdf.cshtml b/Fab2ApprovalSystem/Views/ECN/ECNPdf.cshtml index dccd03b..92c02b5 100644 --- a/Fab2ApprovalSystem/Views/ECN/ECNPdf.cshtml +++ b/Fab2ApprovalSystem/Views/ECN/ECNPdf.cshtml @@ -1,535 +1,506 @@ @model Fab2ApprovalSystem.ViewModels.ECNPdf - - -
- - - +@{ + Layout = null; +} - - - - - - - - + + + + + + + + - - - -
- @Model.Title -
- - @if (@Model.ConvertedFromNumber != null) - { - - - - } - @if (@Model.ConvertedToNumber != null) - { - - - - } - @if (@Model.ConvertedFromNumber == null && @Model.ConvertedToNumber == null) - { - - - - } + - - - - - - + + + + + + -
- ECN# @Model.ECNNumber (Converted from TECN#:@Model.ConvertedFromNumber) -
- ECN# @Model.ECNNumber (Converted to ECN#:@Model.ConvertedToNumber) -
- ECN# @Model.ECNNumber -
- - Submit Date#:  - - - @Model.SubmitedDate - -
- - Originator Name:  - - - @Model.OriginatorName - -
-
- - @* - + +
- - Affected Department:  - - - @Model.AffectedDepartments - -
+ + - - -
+ + + - *@ - - - - - - - - - -
+ @Model.Title +
- - Affected Area:  - - - @Model.AffectedModules - @*@Model.AffectedAreas*@ - -
- - Category:  - - - @(ViewBag.Category) - -
- - ITAR/EC:  - - - @(Model.IsDocEC ? "Yes" : "No") - -
-
-
- - - - - - - - - - - - - - - @* - - *@ - - - - - - - - - - - - + +
ECN - TECN Details
- - - - - - - - - - - - - - - - -
- - ECN:   - - - @(Model.IsECN ? "Yes" : "No") - - - - TECN:  - @(Model.IsTECN ? "Yes" : "No") - - - - Emergency:   - - - @(Model.IsEmergencyTECN ? "Yes" : "No") - -
- - Expiration Date: - - - - @Convert.ToString(string.Format("{0:MM/dd/yyyy}", Model.ExpirationDate)) - - - - Extension Date: - - - - @Convert.ToString(string.Format("{0:MM/dd/yyyy}", @Model.ExtensionDate)) - - - - Cancellation Date: - - - @Model.CancellationApprovalDate - -
- - # lots affected: - - - @Model.NumberOfLotsAffected - - - - Recipe Or/And Flow Change: - - - @Model.RecipeChange - - - - Affected product families: - - - @Model.AffectedProductFamilies - -
-
- - - - - - @foreach (string attachmentName in Model.Attachments) + + + - + + + + - -
- - Affected Documents:  - - -
+ + @if (@Model.ConvertedFromNumber != null) { - + + + } + @if (@Model.ConvertedToNumber != null) + { + + + + } + @if (@Model.ConvertedFromNumber == null && @Model.ConvertedToNumber == null) + { + + + + } + + + - } - -
+
+ ECN# @Model.ECNNumber (Converted from TECN#:@Model.ConvertedFromNumber) +
+ ECN# @Model.ECNNumber (Converted to ECN#:@Model.ConvertedToNumber) +
+ ECN# @Model.ECNNumber +
+ + Submit Date#:  + - @attachmentName + @Model.SubmitedDate
-
+ + Originator Name:  + + + @Model.OriginatorName + +
-
- - - - - - - - - -
Description of Change Reason for Change
- - @Html.Raw(@Model.DescriptionOfChange) - - - - @Html.Raw(@Model.ReasonForChange) - -
-
- - - - - - - - -
Training Notification
- - - - -
- - Training: - @(Model.TrainingRequired ? "Yes" : "No") - - - - @(Model.TrainingBy.Length > 0 ? "(" + Model.TrainingBy + ")" : Model.TrainingBy) - -
-
- -
- - - - - - - - - - - - - - -
Systems
- - PCRB: - - - @(Model.PCRBRequired ? "Yes" : "No") - - - - PCRB#:   - @Model.PCRBNumber - - - - Metrology Change:    - - - @(Model.MetrologyChangeRequired ? "Yes" : "No") - - - - SPC Change: - - - @(Model.SPCChangeRequired ? "Yes" : "No") - - - - FI Change: - - - @(Model.FIChangeRequired ? "Yes" : "No") - - - - OI Change: - - - @(Model.SPNChangeRequired ? "Yes" : "No") - -
- - -
- - - - - - - - - - -
Training Notification
- - Training: - - - @(Model.TrainingRequired ? "Yes" : "No") - - - - Training Notification to:   - @(ViewBag.TrainingNotificationTo) - -
- - -
- - - - - - - - - -
Change Impact
- - - - - - - -
- - Impact On ESH: - - - @if (Model.ImpactOnEnvironment == 1) - { - @: Positive - } - else if (Model.ImpactOnEnvironment == 2) - { - @: Negative - } - else - { - @: N/A - } - -
- - @Html.Raw(@Model.ImpactOnEnvironmentDescription) - -
-
- - - - - - - -
- - Impact On Capacity: - - - @(Model.ImpactOnCapacity == 1 ? "Yes" : "No") - -
- - @Html.Raw(@Model.ImpactOnCapacityDescription) - -
-
- @* - -
- - RH(ITAR): - - - @(Model.IsRH ? "Yes" : "No") - +
*@ -
- - + - -
+ + @* - - - - -
- - Material Consumption Change: - - - @(Model.MaterialConsumptionChangeRequired == 1 ? "Yes" : "No") - + + Affected Department:  + + + @Model.AffectedDepartments +
- - @Html.Raw(@Model.MaterialConsumptionChangeDescription) - -
-
-
- - - - - - - - @foreach (Fab2ApprovalSystem.ViewModels.ECNApprovalLog ecnApp in Model.Approvalog) - { + *@ + + + + + + + + + +
- Full Name - - Role - - Approved/Denied - - Date Time -
+ + Affected Area:  + + + @Model.AffectedModules + @*@Model.AffectedAreas*@ + +
+ + Category:  + + + @(ViewBag.Category) + +
+ + ITAR/EC:  + + + @(Model.IsDocEC ? "Yes" : "No") + +
+
+
+ + + + + + + + + + + +
ECN - TECN Details
+ + + + + + + + + + + + + + + + +
+ + ECN:   + + + @(Model.IsECN ? "Yes" : "No") + + + + TECN:  + @(Model.IsTECN ? "Yes" : "No") + + + + Emergency:   + + + @(Model.IsEmergencyTECN ? "Yes" : "No") + +
+ + Expiration Date: + + + + @Convert.ToString(string.Format("{0:MM/dd/yyyy}", Model.ExpirationDate)) + + + + Extension Date: + + + + @Convert.ToString(string.Format("{0:MM/dd/yyyy}", @Model.ExtensionDate)) + + + + Cancellation Date: + + + @Model.CancellationApprovalDate + +
+ + # lots affected: + + + @Model.NumberOfLotsAffected + + + + Recipe Or/And Flow Change: + + + @Model.RecipeChange + + + + Affected product families: + + + @Model.AffectedProductFamilies + +
+
+ + + + + + @foreach (string attachmentName in Model.Attachments) + { + + } + +
+ + Affected Documents:  + + +
+ + @attachmentName + +
+
+
+ + + + + - - - - } - - -
Description of Change Reason for Change
- @ecnApp.FullName + @Html.Raw(@Model.DescriptionOfChange) - @ecnApp.SubRole - - - - @ecnApp.Operation - - - - @ecnApp.OperationTime + @Html.Raw(@Model.ReasonForChange)
-
+
+ + + + + + + + + + + + + + + + +
Systems
+ + PCRB: + + + @(Model.PCRBRequired ? "Yes" : "No") + + + + PCRB#:   + @Model.PCRBNumber + + + + Metrology Change:    + + + @(Model.MetrologyChangeRequired ? "Yes" : "No") + + + + SPC Change: + + + @(Model.SPCChangeRequired ? "Yes" : "No") + + + + FI Change: + + + @(Model.FIChangeRequired ? "Yes" : "No") + + + + OI Change: + + + @(Model.SPNChangeRequired ? "Yes" : "No") + +
+ + + + + + + + + + + + +
Training Notification
+ + Training: + + + @(Model.TrainingRequired ? "Yes" : "No") + + + + Training Notification to:   + @(ViewBag.TrainingNotificationTo) + +
+ + + + + + + + + + + + + + +
Change Impact
+ + + + + + + +
+ + Impact On ESH: + + + @if (Model.ImpactOnEnvironment == 1) + { + @: Positive + } + else if (Model.ImpactOnEnvironment == 2) + { + @: Negative + } + else + { + @: N/A + } + +
+ + @Html.Raw(@Model.ImpactOnEnvironmentDescription) + +
+
+ + + + + + + +
+ + Impact On Capacity: + + + @(Model.ImpactOnCapacity == 1 ? "Yes" : "No") + +
+ + @Html.Raw(@Model.ImpactOnCapacityDescription) + +
+
+ @* + + + +
+ + RH(ITAR): + + + @(Model.IsRH ? "Yes" : "No") + +
*@ +
+ + + + + + + +
+ + Material Consumption Change: + + + @(Model.MaterialConsumptionChangeRequired == 1 ? "Yes" : "No") + +
+ + @Html.Raw(@Model.MaterialConsumptionChangeDescription) + +
+
+ + + + + + + + + + + + @foreach (Fab2ApprovalSystem.ViewModels.ECNApprovalLog ecnApp in Model.Approvalog) + { + + + + + + + } +
+ Full Name + + Role + + Approved/Denied + + Date Time +
+ + @ecnApp.FullName + + + + @ecnApp.SubRole + + + + @ecnApp.Operation + + + + @ecnApp.OperationTime + +
+ + + + + \ No newline at end of file