Basiclly I'm trying to create an HTML, I already have it written but I want the user to be able to put some text on the textboxes and saving it into strings and use later when creating the HTML file.
I tried playing abit with StreamWriter but I don't think that will be the best idea.
Also I want it to open on the default web browser , or just on IE if it's easier after the file is created.
I really need help as I'm struggling especially with the creating part.
Thanks for reading!
You can also do this without external libraries.
Set up your HTML file as follows:
<!DOCTYPE html>
<html>
<header>
<title>{MY_TITLE}</title>
</header>
<body></body>
</html>
Then edit and save the HTML from C#:
const string fileName = "Foobar.html";
//Read HTML from file
var content = File.ReadAllText(fileName);
//Replace all values in the HTML
content = content.Replace("{MY_TITLE}", titleTextBox.Text);
//Write new HTML string to file
File.WriteAllText(fileName, content);
//Show it in the default application for handling .html files
Process.Start(fileName);
If you already have the HTML you want to export (just not customized), you could manually add format strings to it (like {0}, {1}, {2}) where you want to substitute text from your app, then embed it as a resource, load it in at runtime, substitute the TextBox text using string.Format, and finally write it out again. This is admittedly a really fragile way to do it, as you need to make sure the number of parameters agrees between the resource file and your call to string.Format. In fact, this is a horrible way to do it. Actually, you should do it the way #EmilePels suggests, which is basically a less fragile version of this answer.
Related
I am using XML/XSLT to create an aspx page which can grow quite large. Even though the file is successfully created, when the file size approaches 300K, the error: “CS1647: An expression is too long or complex to compile” is issued when opening the file in a browser (tried both IE and Chrome). No other useful information is shown on the failed .NET error page.
My development environment is VS 2012 Express for Web on a Win7 x64 laptop.
Since this problem does not occur during the execution of the program, I am at a loss as to how to approach solving this problem. Can anyone suggest a strategy or work around to this issue?
EDIT
The C# code used to create the aspx page is
// load the xml file
XmlDocument reportDetails = new XmlDocument();
reportDetails.Load(ReportDetailsPath);
//setup the xslt transform
XslCompiledTransform xslt = new XslCompiledTransform();
xslt.Load(XlsRptPath);
StringWriter sw = new StringWriter();
xslt.Transform(ReportDetails, null, sw);
//create the aspx file
using (StreamWriter outfile = new StreamWriter(aspxPath))
{
outfile.Write(sw.ToString());
}
Old question, and largely answered in the comments. But for the sake of completeness, let's answer it ;). Your issue is not with XSLT itself, but with the generated file which hits the 300k boundary of maximum expression size in C#. There are a couple of things you can do:
Make the generated code below 300k (but this might not be possible in your case)
Take any string constants in the generated code and place them in a
resource file. The format of such resource files is XML and you can
auto-generate it, just make sure the IDs in the resource match the
IDs you use in the generated ASPX
Place part of the generated code in a code-behind file. An ASPX is
parsed as one expression, but the code-behind is not. This is a
matter of structuring the generated code.
Split the ASPX in multiple pages, if your design allows this. You can
recombine them with iframes.
Split the ASPX file in multiple ASCX controls. This is perhaps the
most natural thing to do. Each ASCX control can be referenced/added
to the ASPX file. Each ASCX control should not exceed the 300k limit.
If there is a lot of generated CSS that blows up the size, place it
in a separate CSS file.
If there are a lot of long absolute paths in image references and the
like, you can collapse them and make the references relative, i.e. by
using <base>, which may save you some space.
If the error is caused by actual large (constant) expressions, consider the
hints in the answers in this post for a resolution.
I am sorry for not posting my solution sooner, but I was too stressed at the time to do so. Better late than never I guess.
Instead of trying to create a complete aspx web page for each associated xml file, I created a stub and applied the xslt transform at run-time from within an associated Site.Master. The stub's MasterPageFile property is set to this Site.Master. This approach does sacrifice some performance, but it works for any size web page. Here is an example of the outputted webpage.
Example aspx stub file:
<%# Page Title="Top Austin Beauty Salons List" MetaDescription="List of best Google-ranked Austin beauty salon" Language="C#" MasterPageFile="~/Site1.Master" %>
<asp:Content ID="Content2" ContentPlaceHolderID="ContentPlaceHolder1" runat="server">
</asp:Content>
Site.Master Page_Load:
protected void Page_Load(object sender, EventArgs e)
{
string vp = Page.AppRelativeVirtualPath;
if (vp.ToLower().EndsWith("default.aspx") || vp.ToLower().EndsWith("webform2.aspx")) return; // ignore some aspx files used for ohter reasons
string xmlPath = Page.MapPath(vp.Substring(0, vp.LastIndexOf(".")) + #".xml");
string xslPath = Page.MapPath("mainpage.xslt");
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.Load(xmlPath);
XsltArgumentList argsList = new XsltArgumentList();
argsList.AddParam("xmlPath", "", xmlPath);
XslCompiledTransform xslt = new XslCompiledTransform();
xslt.Load(xslPath);
// Execute the transform and output the results to a string writer.
StringWriter sw = new StringWriter();
xslt.Transform(xmlDoc, argsList, sw);
content.InnerHtml = sw.ToString(); // add the generated html to the associated stub aspx content section
}
In my scenario I want to download the HTML of a page (any page on the Internet) programaticaly but also I want all of the images in the HTML to be in base64 embedded format (not referenced)
In other words, instead of :
<img src='/images/delete.gif' />
I want the downloaded html to look like this:
<img src="data:image/gif;base64,R0lGODl..." />
This way I don't need to go through the process of storing all images in directories, etc, etc.
Does any of you have any idea how this can be done? Or any plugin to do this efficiently?
Well, you'd need to:
Download the original HTML
Find each img element in the HTML (for instance using the HTML agility pack) and for each one:
If it's already using a data URL, ignore it
Otherwise:
Download the image
Encoded it in Base64 using Convert.ToBase64String
Replace the original img tag with one using the base64 version (either in the original string, or via a DOM representation)
Save the final HTML to disk
Is any of these steps causing you a particular problem? You could potentially make it quicker by downloading the images in parallel, but I'd get a serial version working first.
Instead of using a html page with images as base64 encoded strings in the src attribute you might consider using the MHTML format instead. Most browsers supports the format and it embeds all external resources (including images).
var msg = new CDO.MessageClass();
msg.MimeFormatted = true;
msg.CreateMHTMLBody("http://www.google.com", CDO.CdoMHTMLFlags.cdoSuppressNone, "", "");
var stream = msg.GetStream();
var mhtml = stream.ReadText(stream.Size);
Use a regular expression (regex) to extract URLs from img tags, translate them to absolute URLs using the Uri class, then use WebClient to download the target images. After that it's just a case of using Convert.ToBase64String to produce the Base64.
I have a small application written in c# as a console app that I want to use to send an email. I was planning on storing the email inside an xml file along with other information that the message will need like a subject. However there seems to be a problem because the XML file doesnt like </br> characters.
Im wondering what I should do in order to store a html email do I just have to keeo the body html in a seperate html file and then read each line into a StreamReader object?
The easiest way would be to store the HTML content in a CDATA section:
<mail>
<subject>Test</subject>
<body>
<![CDATA[
<html>
...
</html>
]]>
</body>
</mail>
Use a CDATA section, that will contain your email HTML code :
<?xml version="1.0"?>
<myDocument>
<email>
<![CDATA[
<html>
<head><title>My title</title></head>
<body><p>Hello world</p></body>
</html>
]]>
</email>
</myDocument>
You can use CDATA section in your XML - here you can read about it.
You could store the HTML as CDATA within the XML.
But looking at what you are trying to do, you may wish instead look at the System.Web.UI.WebControls.MailDefinition class, as it already contains a reasonable way of using mail templates.
The msdn documentation gears towards it being used in WinForms apps, but you can simply use a ListDictionary to fill the replacements.
Here is a simplistic example, to give an idea of how MailDefinition can be used, I won't go into to much detail, as it's a little outside of the scope of the original question.
protected MailMessage GetNewUserMailMessage(string email, string username, string password, string loginUrl)
{
MailDefinition mailDefinition = new MailDefinition();
mailDefinition.BodyFileName = "~/mailtemplates/newuser.txt";
ListDictionary replacements = new ListDictionary();
replacements.Add("<%username%>", username);
replacements.Add("<%password%>", password);
replacements.Add("<%loginUrl%>", loginUrl);
return mailDefinition.CreateMailMessage(email, replacements, this);
}
I want to create a HTML document and create table init using C#. I don't want to use ASP or any thing like that. I want to do this by using C# Windows Application.
The created document should not use MS Word or may not depend on any other app and save it to any folder (C:\) etc. It is totally independent of any other MS product and can run in any PC
Something like this :)
String exportdirectory = "c:";
StreamWriter sw;
sw = File.CreateText(exportDirectory + "filename.html");
sw.WriteLine("<table>");
sw.WriteLine("<tr>");
sw.WriteLine("<td>");
sw.WriteLine("contents of table!");
sw.WriteLine("</td>");
sw.WriteLine("</tr>");
sw.WriteLine("</table>");
sw.Close();
This is just creating a string ( maybe using a StringBuilder ) and appending data, then save it with a StreamWriter. If you want something more versatile, try to use some sort of stringtemplate, http://www.antlr.org/wiki/display/ST/StringTemplate+Documentation for example, this could allow you to isolate the "view" portion of your application allowing some sort of configuration to easily drive the output generation.
Well its not clear why you have such requirement or why are u mentioning MS Word... it doesn't make sense...
But what you want is your programme to Create a HTMl File.. (you dont even need ASP.NEt for that.. its for web server programming...)
My best guess is you want something to emit data in HTML format according to some user requirements.
For that..
Simply just create a file with HTML Extension and start Emitting HTML specific tags to it.
Few guys have already mentioned how to do that.
A quick and Dirty way would be somthing like this...
public void CreateFile()
{
StringBuilder sb = new StringBuilder();
sb.Append("<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd \"> \r\n ");
sb.Append("<html xmlns=\"http://www.w3.org/1999/xhtml\">\r\n");
sb.Append("<head>\r\n");
sb.Append("<meta content=\"text/html; charset=utf-8\" http-equiv=\"Content-Type\" />\r\n");
sb.Append("<title>My HTMl Page</title>\r\n");
sb.Append("</head>\r\n");
sb.Append("<body>\r\n");
sb.Append("<table>\r\n");
//If you are emiting some data like a list of items
foreach (var item in Items)
{
sb.Append("<tr>\r\n");
sb.Append("<td>\r\n");
sb.Append(item.ToString());
sb.Append("</td>\r\n");
sb.Append("</tr>\r\n");
}
sb.Append("</table>\r\n");
sb.Append("</body>\r\n");
sb.Append("</html>\r\n");
System.IO.StreamWriter sr = new System.IO.StreamWriter("Your file path .html");
sr.Write(sb.ToString());
}
There is also a System.Web.UI.HTML32TextWriter class that is specially ment for this purpose but you didn't wanted anything from ASP, so...
I have a long javascript in a string and programatically using RegisterClientScriptBlock, I add it to my page.
Is there any way to have the intellisense detect my javascript inside the string?
Code:
string Script0 =
#"
function dummy()
{
}
var PTRValues = new Array();
...
...
..
";
this.Page.ClientScript.RegisterClientScriptBlock(this.GetType(), "myCustomScriptBlock", Script0, true);
No, you can't get intellisense inside the JS string. The IDE doesn't know this particular string is JS.
If it's long don't put it in the *.cs file. Instead store it in a *.js. If you really want you can load the file into memory at runtime and serve it embedded in the html instead of referenced.
Unfortunately, this is not possible.
The best solution is to make put the code separate .js file, then write the following:
Page.ClientScript.RegisterClientScriptBlock(
GetType(),
"myCustomScriptBlock",
File.ReadAllText(myJSFilePath),
true
);
For optimal performance, you should read it only once, then store in in the cache.
Ok, these guys are getting close...
Don't EVER embed scripts in code. Always embed as resource or for prototyping and develepment use ClientScript to render a <script/> tag and reference a .js file.
There are just too many reasons wny you would not want to embed script in code to list. google it.
What you are after is to render some javascript from the codebehind via ClientScript and you would like design time intellisense support?
Ok,
To get intellisense you will need a .js of some kind. The approach I suggest, to promote maintainability and prevent dupe scripts that can get out of sync is:
create an EMPTY file called myScript.js.
create another script containing your code named myScript-vsdoc.js
mark myScript-vsdoc.js as embedded resource and serve it as and embedded web resource
meanwhile, back in the IDE, add a script tag pointing to myScript.js, which is an EMPTY file
press SHIFT-CTRL-J and bingo, you have intellisense for your embedded script, your embedded script is in a source file that is editable and discoverable and you have no duplication.
That is how i do it.