Contact   •   Products   •   Search

Rick Strahl's Web Log

Wind, waves, code and everything in between...
ASP.NET • C# • HTML5 • JavaScript • AngularJs

Capturing Output from ASP.Net Pages


One question I frequently see asked is how to capture output in ASP.Net applications. There are a variety of ways to accomplish this task depending on whether you need to capture the current page output or the capture the output of another page altogether. I typically have two separate scenarios for this:

 

1. Capture Current Page Content

I need to capture the current page content and either fix up the content in some way, or I need to capture it so that I can do things like email it, save it etc.

 

2. Capture Separate Page Content

In this scenario I usually need to run a page that is unrelated to the current page and capture the output. An example might be a mail merged document, or a confirmation template or even a user defined plug in that returns content to the current page.

 

Capturing the Current Page

For number 1 the process involves using the Render() method of the page to capture the output it generates and then manipulating the content. A couple of scenarios where I’ve used this approach is to capture the output from the current page and then email it to the customer. For example, in my West Wind Web Store the final confirmation page contains the order confirmation text that is then also mailed to the customer in HTML format. The code to do this looks something like this:

 

/// <summary>

/// Overridden to handle Confirmation of the order by

/// capturing the HTTP output and emailing it.

/// </summary>

/// <param name="writer"></param>

protected override void Render(HtmlTextWriter writer)

{

      // *** Write the HTML into this string builder

      StringBuilder sb = new StringBuilder();

      StringWriter sw = new StringWriter(sb);

 

      HtmlTextWriter hWriter = new HtmlTextWriter(sw);

      base.Render(hWriter);

 

      // *** store to a string

      string PageResult = sb.ToString();

 

      // *** Write it back to the server

      writer.Write(PageResult);

 

      // *** Now strip out confirmation part

      string Confirmation = wwUtils.ExtractString(PageResult,

        "<!--  Start Confirmation Display --->",

        "<!-- End Confirmation Display --->",false);

 

      if (wwUtils.Empty(Confirmation))

            return;

 

     

      // *** Add the header into the page

      Confirmation = string.Format(

           "<h2>{0} Order Confirmation</h2>\r\n{1}",

           App.Configuration.CompanyName,Confirmation);

 

      // Now create a full HTML doc and add styles required for email (no stylesheet)

      sb = new StringBuilder();

      sb.Append(@"

<html>

<head>

<meta http-equiv='content-type' content='text/html;charset=UTF-8'>

<style>

body

{

FONT-FAMILY: Verdana;

FONT-SIZE: 10pt;

FONT-WEIGHT: normal;

MARGIN-TOP: 0pt;

PADDING-TOP: 0pt

}

</style>

</head>

<body>

");              

     

sb.Append(Confirmation);

     

 

      WebStoreUtils.SendEmail(App.Configuration.CompanyName + " Order Confirmation #: " +

                                    Invoice.GetTypedDataRow().Invno,

                                    sb.ToString(),

                                          Invoice.Customer.GetTypedDataRow().Email);

}

 

This code basically captures the output of the current page by intercepting the Render() method and hijacking the HtmlTextWriter used to output the page’s content. The code points the TextWriter at a StringBuilder object that is used to gain access to the generated Html content. Once captured the content is then written out into the writer that was passed into the method which causes the output to be sent back to the ASP.Net pipeline for display.

 

At this point we have a string of the HTML content that is then further fixed up; in this case the code extracts the ‘main’ block of text from the HTML page which is delimited with a comment block so it’s easy to extract using a custom string extraction method in my utility library. I’m extracting the core text only because the header of the online document points at a style sheet and includes some script code that I don’t want or need for the email message, so the extraction retrieves just what’s actually required. The result HTML is then marked up with the necessary HTML header and styles to make it display correctly as a standalone HTML document that is to be displayed inside of an email client. I don’t use images either to avoid Outlooks blocking of images and instead inject a text header that replaces the Store’s usual image and link banner (stripped out above the <!--  Start Confirmation Display --->" comment). When the markup’s complete the text is simply sent to the Application’s stock SendMail method that sends off the confirmation message.

 

This approach works well and is very efficient if the content you need to retrieve exactly matches the content that you are already generating in your page.

 

Capturing content from another Page in the Current Application

If you need to capture content from another page altogether you can take advantage of a very powerful function in the Server object: Server.Execute(). Server.Execute() let’s you run another ASP.Net page, pass in a TextWriter object and then return control back to the current page, which can then retrieve the TextWriter and its content easily.

 

I use this concept all the time for performing mail merge operations. For example in the West Wind Web Store I frequently want to generate email messages for customers that are used to let users know about order status or failures like declined credit cards. These forms are stored in a separate Templates directory of the Web Site and contain form letters that customize the messages to the customer and their order. These pages typically are plain text messages, not HTML. For example, here is the Declined Order Template:

 

<%@ Page language="c#"%>

<%@ Assembly name="wwWebStore" %>

<%@ Assembly name="wwBusiness" %>

<%@ import namespace="Westwind.WebStore" %>

<%@ import namespace="Westwind.WebStore.Admin" %>

<%@ import namespace="System.Data" %>

 

 

<script runat="server">

public DataRowContainers.wws_customersRow Cust = null;

public DataRowContainers.wws_invoiceRow Inv = null;

</script>

 

<%

    // Put user code to initialize the page here

    busInvoice Invoice = WebStoreFactory.GetbusInvoice();

 

    string Pk = Request.QueryString["Id"];

    int NumPk = Int32.Parse(Pk);

    string Test = Request.QueryString["Test"];

   

  

    Invoice.Load(NumPk);

 

    this.Inv = Invoice.GetTypedDataRow();

    this.Cust = Invoice.Customer.GetTypedDataRow();

%>

 

<%= string.Format("{0:D}",Inv.Invdate) %>            

                 

 

Hi <%= Cust.Firstname.Trim() %>,

 

Your order # <%= Inv.Invno.Trim() %> for <%= string.Format("{0:C}",Inv.Invtotal) %> has been declined!

 

Your credit card was declined for this transaction.

Please check your card and especially the card billing info

provided and resubmit the order or use another card for

the transaction.

 

Reason for decline:

 

<%= HttpUtility.UrlDecode((string) Inv.Ccresultx) %>

 

You can re-submit the order at:

 

<%= Westwind.WebStore.App.Configuration.StoreBaseUrl %>ReloadOrder.aspx?InvNo=<%= Inv.Invno.Trim() %>

 

All of your contact information is still online so you won't

have to reenter this information. Simply reselect your items

to purchase.

 

Regards,

 

+++ Rick ---

 

Rick Strahl

West Wind Technologies

http://www.west-wind.com/

http://www.west-wind.com/wwThreads/

-----------------------------------

Making waves on the Web

 

In this case the page does not use CodeBehind (like the rest of the application), although it could. To redirect to this and any other templates in the project I use a generic static application method that performs what I refer to a TextMerge:

 

public static string AspTextMerge(string TemplatePageAndQueryString)

{

      string MergedText = "";

 

      // *** Save the current request information

      HttpContext Context = HttpContext.Current;

 

      // *** Fix up the path to point at the templates directory

      TemplatePageAndQueryString = Context.Request.ApplicationPath +

            "/templates/" + TemplatePageAndQueryString;

           

      // *** Now call the other page and load into StringWriter

      StringWriter sw = new StringWriter();

      try

      {

            // *** IMPORTANT: Child page's FilePath still points at current page

            //                QueryString provided is mapped into new page and then reset

            Context.Server.Execute(TemplatePageAndQueryString,sw);

            MergedText =  sw.ToString();

      }

      catch(Exception ex)

      {

            System.Diagnostics.Debug.Assert(false,ex.Message);

            MergedText = null;

      }

 

      return MergedText;

}

 

This method accepts a URL that’s relative to my application’s Templates directory and that can contain a querystring. Note that I’m retrieving the current HttpContext here since this is a static method that has no access to the Page – using HttpContext.Current makes it possible that the caller doesn’t have to pass in his context to the page.

 

To perform a text merge from anywhere then becomes a single static method call that looks like this:

 

string MergedLetter = WebStoreUtils.AspTextMerge(

      "DeclinedOrder_Template.aspx?id=" + Inv.Invno );

 

 

This is very cool! With this mechanism you can basically extend the functionality of ASP.Net outside of the current request processing. It’s possible to perform sophisticated side tasks that are unrelated to the current request processing in this fashion. In fact, it’s great for building template generators etc.

 

The one caveat here is that if you have a failure inside of this page you will not know what actually failed. Unlike a standard ASP.Net page you will not get a nicely formatted ASPX error page returned as a string, but the page will simply fail. If you need to find out what went wrong you have to walk the Exception stack.

 

Capturing content from another Page in the Another ASP.Net Application

Both of the above approaches work great, but they require that you capture content out of the current application. What then? Well there’s always the obvious solution: You can always access the other application via a plain HTTP request:

 

public static string RetrieveHttpContent(string Url,ref string ErrorMessage)

{

      string MergedText = "";

     

      System.Net.WebClient Http = new System.Net.WebClient();

     

      // Download the Web resource and save it into a data buffer.

      try

      {

            byte[] Result = Http.DownloadData(Url);

            MergedText = Encoding.Default.GetString(Result);

      }

      catch(Exception ex)

      {

            ErrorMessage =  ex.Message;

            return null;

      }

 

      return MergedText;

}

 

If you hit the local Web Server the performance of this operation is surprisingly fast so you shouldn’t worry too much about performance. Of course you can also use this to retrieve content from other Web sites if necessary and it’s a nice and easy wrapper to have around to quickly retrieve content from any URL in string format.

 

 

What about non-Web applications?

If you want template processing in WinForms applications – well you can do that too, using the ASP.Net runtime hosted in a Fat or Smart Client application. The ASP.Net Engine is fully self contained and you can actually host it natively in your own applications – although it is pretty resource intensive. I wrote an extensive article about this a while back and it includes a class that makes the process of executing ASP.Net pages from the file system fairly straight forward. With this class a WinForm application can then use a generic method to parse page templates like the Declined Order Template shown earlier with code like this:

 

public static string MergeText(string AspxPage,string QueryString, ref string ErrorMessage)

{

      // *** Use the runtime host class to run the Template page             

      Westwind.AspRuntimeHost.wwAspRuntimeHost Host = new Westwind.AspRuntimeHost.wwAspRuntimeHost();

      Host.cPhysicalDirectory = Directory.GetCurrentDirectory() + "\\Templates\\";

      Host.cVirtualPath = "/Templates";

 

      Host.cApplicationBase =  Directory.GetCurrentDirectory();

      Host.cConfigFile = Host.cPhysicalDirectory + "web.config";

 

           

      if (!Host.Start())

      {

            ErrorMessage = Host.cErrorMsg;

            return "";

      }

 

      string Message = Host.ProcessRequestToString(AspxPage,QueryString);

      if (Host.bError)

            ErrorMessage = Host.cErrorMsg;

 

      Host.Stop();

 

      return Message;

}

 

The wwAspRuntimeHost class makes short work of calling an ASP.Net page in the local file system assuming the directory it sits in is properly set up: It must contain a \bin directory as well as a web.config and global.asax file for ASP.Net to be able to start up in the directory. In this application I also have a Templates subdirectory into which I store custom templates – in fact the same templates that the online Web site uses. This directory then becomes my ‘Web Root’ to the ASP. Net runtime and I store all templates in this directory.

 

Then, to call one of the templates is as easy easy as:

 

public void DeclinedOrderEmail()

{

      string ErrorMessage = "";

      string Message = WebStoreUtils.MergeText("DeclinedOrder_Template.aspx",

                                        "id=" + Invoice.Pk.ToString(),ref ErrorMessage);

 

      if (ErrorMessage != "")

      {

            MessageBox.Show(ErrorMessage,App.WWSTORE_APPNAME,

                            MessageBoxButtons.OK,MessageBoxIcon.Exclamation);

            return;

      }

 

      // *** Display Email with merged text

      wwUtils.GoUrl("mailto:" +

                    this.Invoice.Customer.DataRow["Email"].ToString().TrimEnd() +

                    "?Subject=Re: West Wind Technologies Order Confirmation #" +

                    this.Invoice.DataRow["InvNo"].ToString().TrimEnd() +

                    "&Body=" +

                    Westwind.InternetTools.wwHttpUtils.UrlEncode(Message).Replace("+"," "));

}

 

 

In this example I generate a Declined Order notice which is then displayed in my default Email client ready for sending.

 

Summary

TextMerge functionality is something that I use in almost every application, and with ASP. Net you have a number of options available to you. The fact that the ASP.Net runtime is so flexible and that it exposes the ability to basically execute another page makes it very easy to build very sophisticated functionality that is not directly related to a Web Request. The fact that you can in fact plug the ASP.Net runtime into your own applications is one hell of a cool feature that opens many opportunities for customization and extensibility – it’s basically a pre-made execution and template engine that’s ready for you to be exploited. Have fun with it…

Make Donation


Feedback for this Post

 
# re: Capturing Output from ASP.Net Pages
by Rick Strahl June 11, 2004 @ 2:53pm
Dino Esposito posted a related BLOG entry a few days back that talks about using a Response Filter and the Application PreSentRequestContent handler method to generically capture content for all pages: http://weblogs.asp.net/despos/archive/2004/06/01/145436.aspx. Haven't tried that, but that seems to be a good way to go if you have to capture content from EVERY page.
# re: Capturing Output from ASP.Net Pages
by Rich Quackenbush July 12, 2004 @ 2:33am
Legendary post - Your example was clear and straightforward. This solved my problem for logging web page access!!!
# re: Capturing Output from ASP.Net Pages
by Richard Greene December 22, 2004 @ 5:09am
I would like to know how to take a document that has been revised in Word and pull out only the sections that have been revised in the Word document. The idea is to have one full document and a second document containing only the revised data that has been added. And this data to be put on an intranet.

Thanks, Rich
# re: Capturing Output from ASP.Net Pages
by Andrew Hallock February 17, 2005 @ 10:46am
I was figuring you could use this method to index your aspx pages in DotLucene; that is, simply capture the output as explained above, parse the HTML, and index the page.
# re: Capturing Output from ASP.Net Pages
by Tom Pester June 20, 2005 @ 9:10pm
I subscribe to your feed (always intresting sutff :) but I missed this post.
Now I know why : it doesnt get listed in any of the feeds.
The post say its was submitted the 8th of june but I can't find a trace of it in my rss client. You know what's going on?
# re: Capturing Output from ASP.Net Pages
by Johan June 23, 2005 @ 4:29am
thanx this helped me solve my problem
# re: Capturing Output from ASP.Net Pages
by Johan June 25, 2005 @ 1:01am
Is it possible to let the page submit a form with values to another page using this:
Context.Server.Execute(TemplatePageAndQueryString);
I need to post information to another page every 10 min using a form eg
<form id="Form1" method=”get” action=”URL”>
<INPUT type="hidden" value="<%”GETcyberprop()”%>" name=" msisdn">
</form
Please Email me if you know : johan@fleetcube.com
# re: Capturing Output from ASP.Net Pages
by Fritz Schenk June 29, 2005 @ 3:22pm
I enjoyed your contribution. I am in the process of translating a framework to .net. I avoided several options because I did not wish to manage temporary files and access the server from a an Asp page. Now these things are much easier.
# re: Capturing Output from ASP.Net Pages
by David Imm August 29, 2005 @ 2:09am
Is there a way to catch HTML output from any kind of application using page instantiation ?

in other words :
Is it possible to get the HTML output according to the following steps :

1) Dim Page as New MyApplication.SpecificPageofMyApplication
2) Dim StrOuput as String = GetOutput(Page)
# re: Capturing Output from ASP.Net Pages
by jeff September 29, 2005 @ 2:18pm
Within Server.Execute("/myPage.aspx"), I have the following problem in the code-behind of myPage.aspx.cs:

While I CAN access ASP.Net objects, such as string, IDictionary, or DataSet, I CANNOT get a reference to my custom objects, such as MyNamespace.testObj, from HttpContext.Current.Items or even from HttpContext.Current.Session. Note that items were stored in these containers prior to the Server.Execute call.

Example code:

System.Web.HttpContext ctx = System.Web.HttpContext.Current.Current;

// assignment successful
System.Data.DataSet myDataSet = (System.Data.DataSet) ctx.Items["testDataSet"];

// assignment attempt generates error, invalid cast; curiously, object appears in VS Watch ctx._items
MyNamespace myTestObj = (MyNamespace.testObj) ctx.Items["testObj"];


Thanks in advance for any insight.
# re: Capturing Output from ASP.Net Pages
by Jeff September 30, 2005 @ 6:57am
**************
Clarification of previous post:

myDLL_ONE.dll calls Server.Execute("/myPage.aspx"); myPage.aspx is located in myDLL_TWO.dll.
If the custom objects are created in myDLL_ONE.dll, then there is no problem accessing the objects within /myPage.aspx.
However, if the custom objects are created as part of myDLL_TWO.dll, then i receive an error, invalid cast object reference not found.

**************
# re: Capturing Output from ASP.Net Pages
by CJ January 14, 2006 @ 11:58am
Rick, how are you passing a query string in Server.Execute()?
# re: Capturing Output from ASP.Net Pages
by Rick Strahl January 14, 2006 @ 6:03pm
CJ, it's passed as the first parameter where you specify the application relative path. You pass page?querystring
# re: Capturing Output from ASP.Net Pages
by Brez February 15, 2006 @ 4:38am
Hmmm... almost spot on what I needed... unfortunately I want to grab the output of another page. This other page has a masterpage, but I want to get rid of the masterpage output. I want only the page itself. Of course Server.Execute("/myPage.aspx") catches the masterpage info as well. Any idea how I could handle this?

Probably I will end up adding a querystring check on this other page that would trigger this.MasterPageFile = ""; or something similar in Page_Load, but any suggestion to a more elegant approach that would let the other page unchanged is welcome :-)
# re: Capturing Output from ASP.Net Pages
by Nick March 15, 2006 @ 10:17am
Great Post, nice and clear, exactly what i was trying to google up.
# re: Capturing Output from ASP.Net Pages
by A.V.Ebrahimi July 04, 2006 @ 6:56am
Thanks, it was great.

I used it to cache result of a cube report.
# re: Capturing Output from ASP.Net Pages
by Walter July 07, 2006 @ 10:22am
Thanks - this is at least the 3rd time I've solved an irritating problem with your blog. We must be tackling similar problems, only you are clearly smarter than me!
# re: Capturing Output from ASP.Net Pages
by Troy July 21, 2006 @ 4:42pm
I tried the below in the Render method and I get all of the output except any server side code on the aspx page. Do you get the same issue? If i write out a date through server side code it is not returned from the render method with the custom htmlwriter. If i pass the pages htmlwriter to the base.Render everything prints to the browser fine, but I don't have access to that stream of data. Any ideas?

// *** Write the HTML into this string builder
StringBuilder _sb = new StringBuilder();
StringWriter _sw = new StringWriter(_sb);

HtmlTextWriter _hWriter = new HtmlTextWriter(_sw);

base.Render(_hWriter);

// *** Write it back to the server
writer.Write(_htmlOutPut);
# re: mailmerge in ASP.Net
by sachin August 10, 2006 @ 2:45am
pls
# Scott on Writing
by Scott on Writing September 30, 2006 @ 9:35am
# ASP.NET Forums - Post-render parsing
by HttpHandlers and HttpModules October 04, 2006 @ 3:25am
# ASP.NET Forums - Reading what went to current page - HTTP Stuff?
by HttpHandlers and HttpModules October 05, 2006 @ 1:02pm
# A quick way to Object Serialization - Rick Strahl's Web Log
by Rick Strahl's Web Log October 15, 2006 @ 6:46am
Serialization in .Net is one of the more useful features in .Net that I use all the time. Serialization – especially XML Serialization – makes it essentially trivial to write out the content of an object to a file, stream very easily. This is useful to pass data between applications, but also a great simple mechanism for saving and reloading state of applications. In fact, I use Serialization for just about every application to store a number of configuration settings easily.
# Tech Talk: Capturing Page-output in ASPX pages
by Tech Talk October 16, 2006 @ 6:13am
# ASP.NET Forums - I generate a page that is a receipt and want to send a receipt to the person from the web page.
by Web Forms October 25, 2006 @ 4:43pm
# ASP.NET Sayfa Çýktýsýný Yakalama
by Ferruh Mavituna October 27, 2006 @ 9:25am
Ferruh Mavituna Blog, Web Application Security and Web Technologies. Guvenlik, Web Uygulamalari ve Development
# re: Capturing Output from ASP.Net Pages
by onkar November 01, 2006 @ 5:46am
is it possible to save Capturing Output from ASP.Net Pages in doc form by removing all css and header of html.
# re: Capturing Output from ASP.Net Pages
by Rick Strahl November 01, 2006 @ 12:43pm
Sure... if you look at the first block of code it does something like that by looking for an embedded filter string that delineates a block that should be retrieved. If you don't have the filter strings you can still extract but it's a little more work by extracting the string from between the <body> and </body> tags. Not quite as easy (because <body> may have other attributes), but you can do it with a RegEx expression...
# re: Capturing Output from ASP.Net Pages
by Dan December 09, 2006 @ 11:22am
A handy article but I seem to have a slight problem possibly the same as Troy's (above)

I've created a custom page class that inherits from the ui.Page and overridded render as per your example and I've got the caching engine working nicely.

Then I came to a page that uses some inline code :

<% response.Write("<p>hello world</p>") %>

for whatever reason this seems to render out of turn and it always appears at the top of the page. Then when I look at my cache file this inline HTML was missing.

So it would appear it rendered after the render method to the top of the page or something got confused in the render override / page lifecycle.

CAn you shed any light on this?
# re: Capturing Output from ASP.Net Pages
by Rick Strahl December 09, 2006 @ 12:19pm
Response.Write ouput cannot be captured in this way because the output goes directly into the Response stream immediately. IOW, it completely bypasses the rendering.

If you need to capture this sort of thing you can look into using a Response Filter which allows you to look at anything that gets written into the stream.
# re: Capturing Output from ASP.Net Pages
by Dan December 09, 2006 @ 2:34pm
Thanks, That explains it.
I also found this after some Googling
http://support.microsoft.com/default.aspx?scid=kb;en-us;306575
(ee troubleshooting section)

I think the easiest solution to this particular problem may be to set the innnerhtml value from the codebehind. Or maybe create a webrequest to grab the content.

Does the same apply to resource file values, how do they get rendered when inline?
# re: Capturing Output from ASP.Net Pages
by Dan December 10, 2006 @ 6:42am
In answer to my own somewhat dumb question it isnt a problem because I'm using the resource values in control properties and not the response method to write them out therefore they will render. duh!
# re: Capturing Output from ASP.Net Pages
by Ron Liu December 15, 2006 @ 11:44am
Hi Rick,
I am creating a simple survey form, uSurvey.aspx. Users visiting the page able to fill out the survey form and click save. I would like the the page, uSurvey.aspx to be saved (with all filled textbox) on the web server as something like Answer_UserID.html after the user click on "Save" button. The question is that using "override void Render(HtmlTextWriter writer)" method will only save the initial empty page or will it save the page with user entered data?


Thank you for your help!

-Ron
# re: Capturing Output from ASP.Net Pages
by Leblanc Meneses December 21, 2006 @ 10:33pm
I noticed the same effect as Dan.
so i just changed
<% Response.Write("string"); %>

to 

<%=@"

string

 " 
%>




If in my master page i setup an override Render method as a developer I mean assemble this whole page and send it to my render method for space removal - that is what i'm using it for.

Is this effect with response output not being captured in override render method a bug which may be fixed in the future?

Just doesn't make sense to me because I'm not fully overriding how the page is Rendered.
# re: Capturing Output from ASP.Net Pages
by Rick Strahl December 21, 2006 @ 11:11pm
This simply doesn't work. If you override the Render() method you are overriding the rendering of the form and it's Render() method. If you do a Response.Write it completely bypasses the form's rendering - the output goes directly into the Response.OutputStream.

If you want to capture the complete output you need to hook up a Response.Filter...
# ASP.NET Forums - scraping a form to send via email
by Web Forms January 05, 2007 @ 11:41am
# re: Capturing Output from ASP.Net Pages
by Natalia January 26, 2007 @ 7:43am
Works great for sending a current page ("Context.Server.Execute...")
Question: how to send the current page as a body output but also as an ATTACHMENT?
Please help or advise!
# ASP.NET Forums - forms authentication - email current page as html
by Security February 10, 2007 @ 5:20pm
# Havagan’s Mind Spew » Blog Archive » Hijacking ASP.NET Page HTML
by Havagan's Mind Spew February 17, 2007 @ 8:45am
# re: Capturing Output from ASP.Net Pages
by Robert March 18, 2007 @ 12:24pm
This is exactly what I've been looking for! Thanks Rick!
# Tech Talk: June 2005
by Tech Talk May 04, 2007 @ 11:26am
# re: Capturing Output from ASP.Net Pages
by AeyGee May 04, 2007 @ 10:24pm
Rick! you saved my weekend. Thanks for your clear explanations and this incredible post

AeyGee
# Post-render parsing - ASP.NET Forums
by ASP.NET Forums May 18, 2007 @ 9:11am
# I generate a page that is a receipt and want to send a receipt to the person from the web page. - ASP.NET Forums
by ASP.NET Forums May 18, 2007 @ 9:31am
# scraping a form to send via email - ASP.NET Forums
by ASP.NET Forums May 18, 2007 @ 1:12pm
# forms authentication - email current page as html - ASP.NET Forums
by ASP.NET Forums May 21, 2007 @ 6:39am
# All about creating asp.net pages dynamically - ASP.NET Forums
by ASP.NET Forums May 28, 2007 @ 11:47pm
# re: Capturing Output from ASP.Net Pages
by Bjorn June 03, 2007 @ 6:07am
This is a wonderfull post. I have been reading alot of your articles and I do believe you are clear in what you are doing because whenever I read your Post they are always on point and help full thank you keep up the good work.
# re: Capturing Output from ASP.Net Pages
by Eric June 25, 2007 @ 2:38am
Great article, I'm having a problem though in that a grid on my page is not centering correctly when the browser (ie6) is resizing. Now, using various tools I found that if I modify a css tag generated by the grid server side that I can fix it. However, via code, I can only get see this tag using your Render override technique but I'm unable to apply any changes I read from the writer.

The Render.Filter property does not work for me as it only returns partial HTML that's sent to the client and the code I need to change is not in it. Is there any way I can apply the modification within the Render override?
# re: Capturing Output from ASP.Net Pages
by gazeteler June 30, 2007 @ 10:35am
I was figuring you could use this method to index your aspx pages in DotLucene; that is, simply capture the output as explained above, parse the HTML, and index the page. ...
# Reading what went to current page - HTTP Stuff? - ASP.NET Forums
by ASP.NET Forums July 03, 2007 @ 8:01am
# Implementing 'printer-friendly version' page - ASP.NET Forums
by ASP.NET Forums July 10, 2007 @ 2:58am
# re: Capturing Output from ASP.Net Pages
by don o August 06, 2007 @ 7:01pm
I'm baffled on an error I'm getting screen scraping an asp classic app using DownloadData.

The URL I'm sending works fine in a separate browser window; when I try
to execute my asp.net 1.1 code to scrape the url, I'm getting
an exception "The remote server returned an error: (500) Internal Server Error."
I checked the IIS log and it looks like the error is 80020009|Exception_occurred.__ 500 .

Is there anything I can change in the asp.net app to set up the environment so it acts just like the standalone browser? I saw some posts that got similar results (but no ideas were given as to what could be changed on the asp.net side)

Thanks!
# re: Capturing Output from ASP.Net Pages
by todd August 08, 2007 @ 4:21pm
Hello,

Great article.

Is it possible to take the string and stuff it into a file on a hard drive asynchronously?

I would like to render the page and save the file via a business object in a background thread to speed up performance.

Is this possible in the Render method?

Any tips to increase performace of saving this file in the render method would be appreciated.
# re: Capturing Output from ASP.Net Pages
by Rick Strahl August 08, 2007 @ 4:58pm
I doubt that this would really yield much of a perf gain. Rather capturing hte output directly to file is probably more efficient. Otherwise you can capture to stream then write out to file using Async IO which is easy enough - just don't think it's worth it. The overhead will be in the additional CPU usage and there's probably more overhead in the thread context switches then just 'doing it'.
# re: Capturing Output from ASP.Net Pages
by Neil Craig January 30, 2008 @ 1:07am
Excellent article. Can one use the same approach to beautify the HTML output? Adding controls dynamically can mean that the HTML will look untidy. How would one do it?
# re: Capturing Output from ASP.Net Pages
by Farshad February 21, 2008 @ 11:06am
Hi, I have a problem and seems like you can help me.The following is a code scrap from my mail function written in VB2005/ASP.Net .

'Code scrap start
Dim strHTML As String
Dim ms As New IO.MemoryStream
Dim sw As New IO.StreamWriter(ms)
Dim tw As New HtmlTextWriter(sw)

---> Me.Render(tw)
sw.Flush()
Dim sr As New IO.StreamReader(ms)
strHTML = sr.ReadToEnd
'Code scrap end

In theory, this code should work.But when execution reaches the line specified with arrow the following message appears in VB developer IDE with green colored line and arrow.

"RegisterForEventValidation can only be called during Render();"

After I have the HTML source code, I will send it by putting that in a mail body.

Please tell me what I am doing wrong.A more practical solution will help me the most.
# re: Capturing Output from ASP.Net Pages
by Madelina April 25, 2008 @ 7:56pm
I created a asp.net Form and have database called my form using data string via url.
I need to create a PDFHtml embeded my form in it, then have user click on option then email to their customer.

Your method will work just fine with the email attachment. Do you have any source of create PDF form and email it?
# re: Capturing Output from ASP.Net Pages
by Ho June 25, 2008 @ 5:00am
Thanks, man
It's really what i want to know.
# re: Capturing Output from ASP.Net Pages
by Henry R July 19, 2008 @ 4:22pm
Rick, you are a lifesaver !. This item helps to solve the problem related to the asp.net dynamic pages and the Search Engine Optimization, since it helps to write the physical pages in order to let the search content spiders index them in an organic way.

Thanks a lot
# re: Capturing Output from ASP.Net Pages
by Morder VonAllem October 29, 2008 @ 4:52am
Way late to the party but I've been attempting to do the following (your post comes the closest to what I'm looking for)

Create page dynamically

 Dim page as New MySpecificPageClass
 page.MasterPageFile="path to masterpage"
 page.dostuffthataddscontrolsandsuch()
 dim Output as String = page.renderpage()


specifically renderpage
note i have no control over the masterpage only the dynamically generated page (MySpecificPageClass)

Any help would be greatly appreciated.

Morder
# re: Capturing Output from ASP.Net Pages
by Morder VonAllem October 29, 2008 @ 1:44pm
In case anybody else comes across this post I've found the method I need to utilize from another entry in your blog and combined them to produce the desired result.

This goes in the calling page
            Dim p As New PageThatIMessWithDynamically
            Dim sw As New System.IO.StringWriter
            p.AppRelativeVirtualPath = HttpContext.Current.Request.AppRelativeCurrentExecutionFilePath
            p.SetBody("Here is the body!")
            p.ProcessRequest(HttpContext.Current)
            Dim output As String = p.Output.ToString


This is the PageThatIMessWithDynamically
    Dim _sb As New System.Text.StringBuilder

    Public ReadOnly Property Output() As System.Text.StringBuilder
        Get
            Return _sb
        End Get
    End Property

    Protected Overrides Sub Render(ByVal writer As System.Web.UI.HtmlTextWriter)
        _sb = New System.Text.StringBuilder
        Dim sw As New IO.StringWriter(_sb)
        writer = New HtmlTextWriter(sw)
        MyBase.Render(writer)
    End Sub


SetBody() is a function i use to write data to the page

Obviously somewhere in the PageIMess... is where I put all the code to design the page I want before I call ProcessRequest

Hopefully this helps someone else out there and if there are ways to make it better feel free to post a reply here - Thanks Rick Strahl for your immense knowledge - hope I see you in vegas this year.
# re: Capturing Output from ASP.Net Pages
by Pawan Kumar January 28, 2009 @ 2:45am
yes this code is very very helpfull. I was struggling for this code for last three days. Finally i got it. There are so many examples of rendering control output but few with current page as an html output and email.

Thanks.
# re: Capturing Output from ASP.Net Pages
by shanwaj May 07, 2009 @ 3:51am
Hi Rick,
I am sendig a forms authentication report.aspx as a mail.I am getting the login.aspx page instead of report.aspx.

I tried in many ways to send mail but I successed here upto to do login programmatically.I am getting error like 'The remote server returned an error: (500) Internal Server Error.' at companyOpen.aspx page .
my report.aspx page root is
http://localhost/abc/xyz/lmn/report.aspx
In my application the user will redirect to companyOpen.aspx page after login.Then he should select the company from dropdown list then only he redirect to specified page.

Please help me that how can I send a web page as email which is forms authenticated.
Thanks in advance
# re: Capturing Output from ASP.Net Pages
by Ajit October 13, 2009 @ 3:25am
I am able to save the html design page to .html page rather than the code behind.
In code behind page if i am writing "Hello World" then it is not saved html page, But if i am writing "Hello World" in html page like <div>Hello World</div> then after running the page i am able to save my .aspx page to .html page.

Would you give me a solution for this?
# re: Capturing Output from ASP.Net Pages
by Billy falconer February 26, 2010 @ 6:56am
Hi Rick,

Very useful post, has been very helpful, thanks!

I need a little advice...I am using the idea for scraping the current page during the render phase. I was originally saving this output to session and then sending this in an email at a later phase which is ok until servers don't use session correctly. I am now using Viewstate instead for persisting data. this of course is already written in a previous phase. Is there another way to save this content for later use (without using session or viewstate)?

My scenario uses the Wizard Control which on the last but one captures review data, and the finish click is where the email is sent.

Your thoughts please!

Cheers,

Billy
# Find/Replace on Render
by {STATIC} hippo March 01, 2010 @ 9:10am
Find/Replace on Render
# RT @ibaumann: Capturing Output from ASP.Net Pages http://www.west-wind.com/weblog/posts/481.aspx
by Twitter Mirror March 29, 2010 @ 12:54pm
RT @ibaumann : Capturing Output from ASP.Net Pages http://www.west-wind.com/weblog/posts/481.aspx
# Capturing Output from ASP.Net Pages http://www.west-wind.com/weblog/posts/481.aspx
by Twitter Mirror March 29, 2010 @ 12:54pm
Capturing Output from ASP.Net Pages http://www.west-wind.com/weblog/posts/481.aspx
# Capturing Output from ASP.Net Pages http://www.west-wind.com/weblog/posts/481.aspx (via @ibaumann)
by Twitter Mirror March 29, 2010 @ 6:46pm
Capturing Output from ASP.Net Pages http://www.west-wind.com/weblog/posts/481.aspx (via @ibaumann )
# re: Capturing Output from ASP.Net Pages
by gsalunkhe June 11, 2010 @ 1:49am
Thanks for the help. After searching a Lot on net I got this article. Thank you very much.
# re: Capturing Output from ASP.Net Pages
by Madhanlal JM July 08, 2010 @ 2:08am
Very useful article. Thank you..
# re: Capturing Output from ASP.Net Pages
by Priyan Perera August 03, 2010 @ 9:03pm
Thanks...was looking for this article for some time...
# re: Capturing Output from ASP.Net Pages
by Mike November 19, 2010 @ 10:41am
Fantastically useful, even after years. Like one of the first posters said, legendary.
# re: Capturing Output from ASP.Net Pages
by Jon February 06, 2012 @ 8:38am
I just wanted to say thanks Rick. There have been a number of times that I've been trying to do this or that (usually obscure) and did a web search and came across one of your posts that have been very helpful. It's uncanny your posts always come up.
# re: Capturing Output from ASP.Net Pages
by snehasish chowdhury March 02, 2012 @ 11:17am
You save my 10000000 $ time
# re: Capturing Output from ASP.Net Pages
by Mark May 08, 2014 @ 5:41pm
After 4 days of banging my head against an IIS/ASP.NET/authentication brick wall I came across your post regarding server.execute... Thank you, thank you. I can finally sleep peacefully.
 


West Wind  © Rick Strahl, West Wind Technologies, 2005 - 2014