Use ASP.NET to e-mail contents of an entire HTML Page? - asp.net

I have a HTML page that I have created that essentially consists of:
<div>
<table>
<tr>
<td><asp:label runat="server" id="someText"></asp:label></td>
</tr>
</table>
</div>
The label text is generated on page load from an SQL query.
The above is a very basic and simplified version of what I have on my page.
What I'd like to achieve is to be able to e-mail the entirety of the rendered HTML page without having to build the page again in my code-behind to send it.
Is there a way of doing this?
Thanks in advance for any help.

Something like this maybe (haven't tested):
StringBuilder sb = new StringBuilder();
HtmlTextWriter hw = new HtmlTextWriter(new System.IO.StringWriter(sb));
this.Render(hw);
MailMessage message = new MailMessage();
message.IsBodyHtml = true;
message.Body = sb.ToString();
(new SmtpClient()).Send(message);

If you want to send the email as you render the page, without rerunning the page lifecycle, try the following.
Make a wrapper stream class that inherits Stream and contains two additional streams, and override its Write method to write to both streams. I don't think you need to override anything else except the Can_Whaterver_ properties, but I'm not sure.
Make a field in your Page class of type MemoryStream to hold a copy of the response.
Then, handle the page's PreInit event and set the Response.Filter, like this:
Response.Filter = new CopierStream(Response.Filter, responseCopy);
//`CopierStream` is the custom stream class; `responseCopy` is the MemoryStream
Finally, override the Page's Render method, and, after calling base.Render, you can send responseCopy by email using the SmtpClient class.
This is a very complicated technique that you should only do if you really don't want to re-run the page lifecycle.
Whichever way you do it, if your page has any images or hyperlinks, make sure that their urls include the domain name, or else they won't work in the email.

Use a webclient:
Dim wc As New WebClient
Dim str As String = wc.DownloadString("yoururl.com")
SendEmail(str) ' your email method '

Related

asp.net <form> tag getting stripped out of asp:literal

Okay... I know having nested tags is not officially supported. But stay with me on this one..
I have an ASP.NET web page with the standard <form runat=server> tag at the top. I am pulling in a Form (and associated fields) from a 3rd party source via HttpWebRequest on the server side (code behind). I can verify the data I get contains a <form> tag -- via a Trace statement. Then I assign the data to my literal like this:
Dim objRequest As System.Net.HttpWebRequest = System.Net.WebRequest.Create(url)
Dim objResponse As System.Net.WebResponse
objRequest.Method = "POST"
Dim byteArray As Byte() = Encoding.UTF8.GetBytes(postData.ToString)
objRequest.ContentType = "application/x-www-form-urlencoded"
objRequest.ContentLength = byteArray.Length
Dim dataStream As Stream = objRequest.GetRequestStream()
dataStream.Write(byteArray, 0, byteArray.Length)
dataStream.Close()
objResponse = objRequest.GetResponse()
Dim streamRead As New StreamReader(objResponse.GetResponseStream())
Dim strResponse As String = streamRead.ReadToEnd()
me.litCMSForm.Text = strResponse
When the page is rendered, somehow .NET removed the <form> tag that was within the literal.
I also tried assigning the variable "strResponse" to a public variable to be displayed and it too had the tag stripped out. And I tried assigning the variable to an asp:Label as well with no luck. And I tried assigning the value to the literal on the "PreRender" function with no success.
Any thoughts on this and why .NET is stripping out the <form> tag?
Thanks!
You're correct - nested form tags are not supported. What you can do is generate JavaScript that would pass the string to an HTML container outside of ASP.NET form or, better yet, output it to an independent iframe.
I had the same problem. I was able to work around the situation by adding another form before the one I really wanted to insert. It seems like ASP was only frisky enough to strip out the first firm it found.
Perhaps this would work for you:
me.litCMSForm.Text = "<form name='fakeOut'></form>" + strResponse
I actually had my form code be a little fancier (I gave it an action and an hidden input). I didn't continue to test to see what could be taken away because it worked.

Generate Compressed HTML From GridView Control in Asp.Net

Is there any Possibility that it can Generate Compressed HTML from the GridVIew ???
I do not suggest to do that, but I can give an idea for how I will try to do that:
You can render the GridView in a string, make the compression and then show it to the page.
TextWriter stringWriter = new StringWriter();
HtmlTextWriter GrapseMesaMou = new HtmlTextWriter(stringWriter);
cGridView.RenderControl(GrapseMesaMou);
// this is the string that you show on page (eg place it on a literal)
string cFinalResults = CompressHtml(stringWriter.ToString());
// not show it any more...
cGridView.Visible = false;
one html compressor: http://code.google.com/p/htmlcompressor/
I do not know if this can work smoothly for all cases, but you can give it a try to see if it is what you look for.

Asp.net error creating usercontrol from WebMethod

I'm referencing the article reference
To create a UserControl dynamically and pass it back to a page via jQuery.
When I just do a simple text in the UserControl "Hello World" everything works great... however, when I tried putting interactive controls on the control, I got the following message in my WebMethod (so the jQuery call stuff is irrelevant) (further testing showed that textboxes, and buttons cause the issue, but not labels)
Error executing child request for handler 'System.Web.UI.Page'
here's the webmethod:
[WebMethod]
public static string GetCtrl(string cname)
{
StringWriter sw = new StringWriter();
Page p = new Page();
Control c = p.LoadControl("~/Controls/" + cname);
p.Controls.Add(c);
try
{
HttpContext.Current.Server.Execute(p, sw, false);
}
catch (Exception err)
{
return err.Message;
}
sw.Close();
return sw.ToString();
}
The exception is happening during the Server.Execute call.
A solution may not be possible, I'd just like to know why interactive controls cause this.
EDIT:
Taking advice below I looked deeper and found the inner exception said something to the effect that it must be within a form tag marked with runat="server", while I'm displaying this control on a aspx page within the form tag... my guess is that there's got to be some sort of 'asp.net magic' connection there for the control to operate... regardless, it'd be nice to know how to render a page with controls on it anyway (even if it wasn't usable in this situation)
So I looked at the output of the above code and for those curious:
<span id="ctl00_lbl1">abc: </span>
So the control is rendering properly (with just the label id='lbl1') on the page, however, the control is itself rendered, and the page content is not there at all... Is there a way to generate the page source as well? (I must not understand the way the Server.Execute function works)
I'd start by narrowing down the problem. For instance, what happens if you leave off the
p.Controls.Add(c);
What happens if you properly implement a using statement?
using (StringWriter sw = new StringWriter()) {
// ...
HttpContext.Current.Server.Execute(p, sw, false);
return sw.ToString();
}
What happens, if you leave off the try/catch? It's costing you all the information in the exception other than the Message property, so why not just leave it off? Your caller might be expecting HTML in any case, so if you keep it, you might (later) want to wrap the output:
return "<p>" + ex.ToString() + "</p>";
Little by little, remove things until the problem goes away.
Based on what you learned from the InnerException, I recommend that you add an HtmlForm control to the page, then add your loaded control as a child control of the HtmlForm.
Using Scott Gu's blog as a reference, I also came across the same problem loading server controls in my widgets (e.g. GridView and RadTreeView controls would cause the same error) for our company's dashboard. Following John Saunders's tip, I added an HTML form control and script manager control (for RadTreeView controls) and it fixed the problem. Now my user controls render out as pure HTML. w00t!
[WebMethod]
public static string[] LoadWidget(string widgetID, string widgetPath)
{
try
{
var pageHolder = new Page();
var form = new HtmlForm();
var viewControl = (UserControl)pageHolder.LoadControl(widgetPath);
var scriptManager = new ScriptManager();
form.Controls.Add(scriptManager);
form.Controls.Add(viewControl);
pageHolder.Controls.Add(form);
var output = new StringWriter();
HttpContext.Current.Server.Execute(pageHolder, output, false);
return new string[]
{
widgetID, output.ToString()
};
}
catch (Exception e)
{
// handle error...
}
}
I would try rendering the control and sending that string back...
Control ctrl;
StringBuilder sb = new StringBuilder();
StringWriter tw = new StringWriter(sb);
HtmlTextWriter hw = new HtmlTextWriter(tw);
ctrl.RenderControl(hw);
return sb.ToString();

How to generate HTML email content with asp.net

I want to send emails in HTML format. How can I use asp.net to generate HTML content for emails.
Using output of .aspx page(Tried there was nothing in email body. Must be something in page that can't be used for email)
Using Webcontrol and get web control output and use it as email body.
Using custom http handler so can call handler to get email body.
Can you please suggest what would be the best solution?
Some guide or sample reference would be great if know one.
Thanks for all answers:
I am implementing code below:
string lcUrl = "http://localhost:50771/webform1.aspx";
// *** Establish the request
HttpWebRequest loHttp =
(HttpWebRequest)WebRequest.Create(lcUrl);
// *** Set properties
//loHttp.Timeout = 10000; // 10 secs
loHttp.UserAgent = "Code Web Client";
// *** Retrieve request info headers
HttpWebResponse loWebResponse = (HttpWebResponse)loHttp.GetResponse();
Encoding enc;
try
{
enc = Encoding.GetEncoding(loWebResponse.ContentEncoding);
}
catch
{
enc = Encoding.GetEncoding(1252);
}
StreamReader loResponseStream =
new StreamReader(loWebResponse.GetResponseStream(), enc);
string lcHtml = loResponseStream.ReadToEnd();
loWebResponse.Close();
loResponseStream.Close();
I think the ASPX file will make the most easy to edit mechanism. You can use
var stream = new MemoryStream();
var textWriter = new StreamWriter(stream);
Server.Execute("EmailGenerator.aspx", textWriter);
to capture the output of that page.
I personally don't like any of your options. I would probably do it by using an HTML file (or a template stored in a database) and substituting something like {{name}} with the appropriate parameter.
I did this, essentially we had a page that the user could view, and then they could click a button and send the html on the page in an email. Basically my page was responsible for generating the email. I did this by overriding the Render method, and providing my own stream or using the one passed to us. We did this dpeneding on if we were rendering what the user would see or emailing it.
protected override void Render(HtmlTextWriter writer)
{
if (_altPrintMethod)
{
System.Net.Mail.MailMessage....
mailMsg.Body=RenderHtml(baseUrl);
}
}
protected virtual string RenderHtml(string baseUrl)
{
RemapImageUrl(baseUrl);
StreamWriter sw = new StreamWriter(new MemoryStream());
HtmlTextWriter writer = new HtmlTextWriter(sw);
base.Render(writer);
writer.Flush();
StreamReader sr = new StreamReader(sw.BaseStream);
sr.BaseStream.Position = 0;
return sr.ReadToEnd();
}
One thing to note is you have to make sure all links are fully qualified. You might be able to use the base functionality. this is what I was doing in the RemapImageUrl basically I appended an absolute path on all my image files.

Hijack output from aspx

I want to convert an aspx page to PDF using a component that can convert Html to PDF. Is it possible to, during post back, redirect the output from the aspx-page and send it as a stream or string to a HtmlToPdf method?
protected override void Render(HtmlTextWriter writer)
{
// setup a TextWriter to capture the page markup
TextWriter tw = new StringWriter();
HtmlTextWriter htw = new HtmlTextWriter(tw);
// render the page into our surrogate TextWriter
base.Render(htw);
// convert the TextWriter markup to a string
string pageSource = tw.ToString();
if (convertToPDF)
{
// convert the page markup to a pdf
// eg, byte[] pdfBytes = HtmlToPdf(pageSource);
}
// write the page markup into the output stream
writer.Write(pageSource);
}
Have you tried to send the value returned from "HttpContext.Current.Response.OutputStream;" in the postback ?
Hi I think that the way to do this would be to use the Reponse.Filter property to intercept and alter the HTML being sent to a page.
There's a tutorial video and sample code in both VB.net and C# on this page on the ASP.net website:
http://www.asp.net/learn/videos/video-450.aspx
You would write an HttpFilter that is attached to the request. This is code that can change the output after it has been written by the ASP.NET Page's Render step.
This article shows how to do this (they change the output from HTML to valid XHTML, but the idea is the same).

Resources