Extracting XML from XMLFormView - c#

Is there a way to get the XML presented in a XMLFormView? I'm trying to create a custom web part with a "Save as PDF" button for an InfoPath form. The idea is to combine the XML with the form's XSL and make the resulting HTML into PDF which is presented to the user as a popup.
Because it is to be presented as a popup, using Workflows is not an option.

http://msdn.microsoft.com/en-us/library/microsoft.office.infopath.server.controls.xmlformview.xmllocation.aspx
This property will give you the Url of the Base XML file. You can read the Stream reader to read this XML.

Take a look at my codeplex project http://ip2html.codeplex.com/
It allows you to generate HTML from the given (InfoPath) XML & (XMLFormView) XSLT.

We ended up using the XmlFormHostItem.NotifyHost method to send HTML to a custom web part in a button-clicked event, which converted the HTML to PDF using Winnovative HTML to PDF converter.
HTML generation from InfoPath code-behind:
var formData = new XmlDocument();
var xslt = new XslCompiledTransform(true);
// Load the form data
formData.LoadXml(MainDataSource.CreateNavigator().InnerXml);
// Extract the stylesheet from the package
xslt.Load(ExtractFromPackage("Print.xsl")); // (uses Template.OpenFileFromPackage(string fileName) to get xsl)
// Perform XSL-transformation
// [...]
// Send HTML to web part
this.NotifyHost(formData.InnerXml);
One drawback of this method is that the NotifyHost event only fires once per form, so if the user clicks 'Save as PDF' and then cancels, he must reload the form in order to be able to save as PDF.

Related

WebView2 - How can I get the same functionality as WebBrowser.Document.OpenNew(true)

In System Forms Webbrowser, Below is the code to Open New HTML Document each time webrowser is updated with new HTML content
webBrowser1.Navigate("about:blank");
webBrowser1.Document.OpenNew(true).Write(html);
In Microsoft.Web.WebView2.WinForms.WebView2 I can use navigate to string like below to update HTML string.
webBrowser.NavigateToString(html);
But this doesn't open a new document. It updates on same.
Is there a way in WebView2 to set HTML content on the new document each time content is changed?
There's a javascript document.open(type, replace) that can help you to achieve the same functionality as the old WebBrowser control's Document.OpenNew(replaceInHistory).
To use it with WebView2, you need to call ExecuteScriptAsync, for example:
await webView21.EnsureCoreWebView2Async();
await webView21.ExecuteScriptAsync(
"document.open('text/html', true);" +
"document.write('<html><body>XXXXXXXXXX</body></html>');");
It will open a new document and replaces the history.

How to approach production of PDF and RTF reports in a WPF application?

Background
I am working on a WPF application that I need to implement reporting functionality for, in PDF and RTF formats. The reports are mostly tabular.
The application doesn't have a database. Instead its data is taken from local XML files from which I create View Models which are in turn passed to the UI for presentation to the user. I need to use these View Models for the reports.
Question
What is the best way for me to approach this requirement, so that I can use my existing View Models to produce reports in PDF and RTF formats?
Potentials
I was thinking if this was a web application I could generate a report in HTML and use 3rd party tools to convert it to PDF and RTF. I've done this before, and I know it would work. Unfortunately there's no guarantee that the user will have an internet connection so I have to keep the report generation local.
So I'm wondering about using XAML to define the report template. Is this possible? I see a utility for Xaml FlowDocument or XPS to PDF Converter on CodePlex but this works with FlowDocument, but I don't think this is what I need. The reports I'll be generating are mostly tabular.
It turns out this:
Xaml FlowDocument or XPS to PDF Converter
appears to be the solution.
I can specify tables in the FlowDocument and and specify a DataContext to bind my View Models to it, and then I can either convert that to PDF using the in-built functionality, or convert it to RTF with something similar to the following:
// get FlowDocument object
var uri = new Uri("/Documents/SamplePDF.xaml", UriKind.Relative);
FlowDocument doc = App.LoadComponent(uri) as FlowDocument;
// create TextRange representation of the FlowDocument
var content = new TextRange(doc.ContentStart, doc.ContentEnd);
if (content.CanSave(DataFormats.Rtf))
{
using (var stream = new FileStream(#"C:\Path\To\file.rtf", FileMode.OpenOrCreate))
{
// save it
content.Save(stream, DataFormats.Rtf);
}
}

Embedded WebBrowser in Windows Form C# project

I have a form with an embedded web browser control on it. I am currently using WebBrowser and use it like so:
webBrowser1.Navigate("about:blank");
HtmlDocument doc = this.webBrowser1.Document;
doc.Write(string.Empty);
String htmlContent = GetHTML();
doc.Write(htmlContent);
This writes the HTML correctly to the web browser control BUT it never clears the existing data and it just appends, so I end up with N web pages stacked on top of each other.
Is this the best control to use? If so why is it not clearing existing data?
You need to use:
HtmlDocument doc = this.webBrowser1.Document.OpenNew(true);
now the contents of the document will be cleared before writing.
All calls to Write should be preceded
by a call to OpenNew, which will clear
the current document and all of its
variables. Your calls to Write will
create a new HTML document in its
place. To change only a specific
portion of the document, obtain the
appropriate HtmlElement and set its
InnerHtml property.
Yes, it is.
You should be able to call the Clear method if you need to clear contents.
Check this article for in-depth details and sample code:
http://www.codeproject.com/KB/miscctrl/simplebrowserformfc.aspx
Call HtmlDocument.OpenNew between pages:
OpenNew will clear the previous loaded
document, including any associated
state, such as variables. It will not
cause navigation events in WebBrowser
to be raised.

Dynamically append number to PDF or make submit button change its URL based on that number

I'm serving up PDFs from a SQL db and presenting them in the browser. I'm trying to figure out a way to embed a number in the PDF dynamically so that the recordID for that PDFs SQL record is available to me when the user submits the XML form data. The user hits the submit button on the form and the form submits its XML data to my submission page. If there is some way of changing the submission URL on the fly then I could do a query string to pass my self the recordID. I'm not generating the PDF in code, its being created by hand and then uploaded to my site.
Edit
User is given a link someServer.com/pdfLink.aspx?formID=5 they go there and that pages pulls a PDF from the DB and displays it. This pulls up acrobat in browser full size so my aspx page isn't in control of submitting the completed form, Acrobat is. The user fills out the form and hits the submit button in the form. This submit button was set up at form design time to point to another page someSite.com/pdfSubmit.aspx The submit button posts the XML data to that page and I can process it. I need the recordID in the query string for the someSite.com/pdfSubmit.aspx page. To do this I would need to modify the PDF to either add the recordID and query string to the submit button's submit URL, or embed it in the PDF else ware. The big question is how do I modify the PDF just before I display it via someServer.com/pdfLink.aspx?formID=5 to do either of these two options.
Embedding a number in PDF is not exactly kosher, but there are some things that you can do that will honor the spec.
The current PDF spec says that "The last line of the file shall contain only the end-of-file marker
%%EOF
but there is some wiggle room - the implementation details say that it doesn't technically have to be the last line of the file, but only has to appear in the last 1K and, generally speaking, if you don't muck with things too much, most compliant readers won't even blink. If I had to do this, I would be inclined to add a newline (if there isn't one), then a % (which is a PDF comment), a marker to let me know it's mine, and finally the number. So something like:
// assume we already know it ends with %%EOF
void AppendNumberToPdf(Stream stm, int number, bool addNewline)
{
stm.Seek(0, SeekOrigin.End); // go to EOF
StreamWriter writer = new StreamWriter(stm, new ASCIIEncoding(), 1024);
writer.WriteLine(string.Format("{0}% {1} {2}", (addNewLine ? "\n" : ""), kMyMarkerString, number));
writer.Flush();
}
kMyMarkerString should be something like "MyApplicationDocumentIdentifier:" or some such thing that will make it easy to identify your tracks.
The querystring is read-only so you cannot dynamically change it at runtime. However can you:
Add the recordID to the form at the time the submit page is initially rendered
Can you process the submit form and then do a Response.Redirect or Server.Transfer to the correct page with the recordid parameter added to the querystring
While trying #plinth's suggestion I realized I had to change from XML submission (since his data was on the PDF directly. So I changed the form to submit as XDP which has XML data + embedded PDF. When I did this and viewed the raw XDP that the form submitted I ran across this.
<?xml version="1.0" encoding="UTF-8" ?>
<?xfa generator="XFA2_4" APIVersion="3.0.8262.0"?>
<xdp:xdp xmlns:xdp="http://ns.adobe.com/xdp/" timeStamp="2010-05-04T15:15:00Z" uuid="6d0944c8-1573-442c-9c85-11e372bd38c3">
<xfa:datasets xmlns:xfa="http://www.xfa.org/schema/xfa-data/1.0/">
<xfa:data>
<form1>
<TextField1>TestMe</TextField1>
</form1>
</xfa:data>
</xfa:datasets>
<pdf href="ViewPDF.aspx?formID=10" xmlns="http://ns.adobe.com/xdp/pdf/" />
</xdp:xdp>
Notice the 2nd to last line. It automatically includes the PDF's url which had the formID value that I needed. So all I had to do was get the XDP instead of pure XML post from the form and it gives me everything I needed.

Easiest way to display XML on an ASP.NET page

I have some XML in an XmlDocument, and I want to display it on an ASP.NET page. (The XML should be in a control; the page will have other content.) Right now, we're using the Xml control for that. Trouble is, the XML displays with no indentation. Ugly.
It appears that I'm supposed to create an XSLT for it, but that seems kind of boring. I'd rather just throw it into a control and have it automagically parse the XML and indent correctly. Is there an easy way to do that?
You could try to use XmlWriter/XmlTextWriter, set the writer's Indentation property, write to a StringBuilder or MemoryStream, and output the result inside a <pre> tag
A quick (and dirty) way of doing this would be to use an IFrame.
In truth, an XSLT is the "ideal" way for formatting an XML for display. Another option would be to parse it manually for display.
To use an Iframe:
ASPX side:
< iframe runat="server" id="myXMLFrame" src="~/MyXmlFile.xml" /></pre>
Code Side:
myXMLFrame.src = Page.ResolveClientUrl("~/MyXmlFile.xml")
You can find a slightly modified version of the XSLT that IE uses to transform XML to HTML when viewing in IE at http://www.dpawson.co.uk/xsl/sect4/N10301.html#d15977e117.
I have used it in a WebBrowser control in a WinForms application, and it works lika a charm. I have not tested it in FireFox/Chrome/Safari/Operat, though.

Categories