Rick Strahl's Weblog  

Wind, waves, code and everything in between...
.NET • C# • Markdown • WPF • All Things Web
Contact   •   Articles   •   Products   •   Support   •   Advertise
Sponsored by:
West Wind WebSurge - Rest Client and Http Load Testing for Windows

Capturing Output from ASP.Net Pages


:P
On this page:

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…


The Voices of Reason


 

Rick Strahl
June 11, 2004

# re: Capturing Output from ASP.Net Pages

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.

Rich Quackenbush
July 12, 2004

# re: Capturing Output from ASP.Net Pages

Legendary post - Your example was clear and straightforward. This solved my problem for logging web page access!!!

Richard Greene
December 22, 2004

# re: Capturing Output from ASP.Net Pages

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

Andrew Hallock
February 17, 2005

# re: Capturing Output from ASP.Net Pages

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.

Tom Pester
June 20, 2005

# re: Capturing Output from ASP.Net Pages

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?

Johan
June 23, 2005

# re: Capturing Output from ASP.Net Pages

thanx this helped me solve my problem

Johan
June 25, 2005

# re: Capturing Output from ASP.Net Pages

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

Fritz Schenk
June 29, 2005

# re: Capturing Output from ASP.Net Pages

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.

David Imm
August 29, 2005

# re: Capturing Output from ASP.Net Pages

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)

jeff
September 29, 2005

# re: Capturing Output from ASP.Net Pages

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.

Jeff
September 30, 2005

# re: Capturing Output from ASP.Net Pages

**************
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.

**************

CJ
January 14, 2006

# re: Capturing Output from ASP.Net Pages

Rick, how are you passing a query string in Server.Execute()?

Rick Strahl
January 14, 2006

# re: Capturing Output from ASP.Net Pages

CJ, it's passed as the first parameter where you specify the application relative path. You pass page?querystring

Brez
February 15, 2006

# re: Capturing Output from ASP.Net Pages

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 :-)

Nick
March 15, 2006

# re: Capturing Output from ASP.Net Pages

Great Post, nice and clear, exactly what i was trying to google up.

A.V.Ebrahimi
July 04, 2006

# re: Capturing Output from ASP.Net Pages

Thanks, it was great.

I used it to cache result of a cube report.

Walter
July 07, 2006

# re: Capturing Output from ASP.Net Pages

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!

Troy
July 21, 2006

# re: Capturing Output from ASP.Net Pages

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);

sachin
August 10, 2006

# re: mailmerge in ASP.Net

pls

Scott on Writing
September 30, 2006

# Scott on Writing


HttpHandlers and HttpModules
October 04, 2006

# ASP.NET Forums - Post-render parsing


HttpHandlers and HttpModules
October 05, 2006

# ASP.NET Forums - Reading what went to current page - HTTP Stuff?


Rick Strahl's Web Log
October 15, 2006

# A quick way to Object Serialization - Rick Strahl's Web Log

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
October 16, 2006

# Tech Talk: Capturing Page-output in ASPX pages


Web Forms
October 25, 2006

# ASP.NET Forums - I generate a page that is a receipt and want to send a receipt to the person from the web page.


Ferruh Mavituna
October 27, 2006

# ASP.NET Sayfa Çýktýsýný Yakalama

Ferruh Mavituna Blog, Web Application Security and Web Technologies. Guvenlik, Web Uygulamalari ve Development

onkar
November 01, 2006

# re: Capturing Output from ASP.Net Pages

is it possible to save Capturing Output from ASP.Net Pages in doc form by removing all css and header of html.

Rick Strahl
November 01, 2006

# re: Capturing Output from ASP.Net Pages

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...

Dan
December 09, 2006

# re: Capturing Output from ASP.Net Pages

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?

Rick Strahl
December 09, 2006

# re: Capturing Output from ASP.Net Pages

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.

Dan
December 09, 2006

# re: Capturing Output from ASP.Net Pages

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?

Dan
December 10, 2006

# re: Capturing Output from ASP.Net Pages

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!

Ron Liu
December 15, 2006

# re: Capturing Output from ASP.Net Pages

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

Leblanc Meneses
December 21, 2006

# re: Capturing Output from ASP.Net Pages

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.

Rick Strahl
December 21, 2006

# re: Capturing Output from ASP.Net Pages

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...

Web Forms
January 05, 2007

# ASP.NET Forums - scraping a form to send via email


Natalia
January 26, 2007

# re: Capturing Output from ASP.Net Pages

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!

Security
February 10, 2007

# ASP.NET Forums - forms authentication - email current page as html


Havagan's Mind Spew
February 17, 2007

# Havagan&#8217;s Mind Spew &raquo; Blog Archive &raquo; Hijacking ASP.NET Page HTML


Robert
March 18, 2007

# re: Capturing Output from ASP.Net Pages

This is exactly what I've been looking for! Thanks Rick!

Tech Talk
May 04, 2007

# Tech Talk: June 2005


AeyGee
May 04, 2007

# re: Capturing Output from ASP.Net Pages

Rick! you saved my weekend. Thanks for your clear explanations and this incredible post

AeyGee

ASP.NET Forums
May 18, 2007

# Post-render parsing - ASP.NET Forums


ASP.NET Forums
May 18, 2007

# I generate a page that is a receipt and want to send a receipt to the person from the web page. - ASP.NET Forums


ASP.NET Forums
May 18, 2007

# scraping a form to send via email - ASP.NET Forums


ASP.NET Forums
May 21, 2007

# forms authentication - email current page as html - ASP.NET Forums


ASP.NET Forums
May 28, 2007

# All about creating asp.net pages dynamically - ASP.NET Forums


Bjorn
June 03, 2007

# re: Capturing Output from ASP.Net Pages

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.

Eric
June 25, 2007

# re: Capturing Output from ASP.Net Pages

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?

gazeteler
June 30, 2007

# re: Capturing Output from ASP.Net Pages

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. ...

ASP.NET Forums
July 03, 2007

# Reading what went to current page - HTTP Stuff? - ASP.NET Forums


ASP.NET Forums
July 10, 2007

# Implementing 'printer-friendly version' page - ASP.NET Forums


don o
August 06, 2007

# re: Capturing Output from ASP.Net Pages

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!

todd
August 08, 2007

# re: Capturing Output from ASP.Net Pages

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.

Rick Strahl
August 08, 2007

# re: Capturing Output from ASP.Net Pages

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'.

Neil Craig
January 30, 2008

# re: Capturing Output from ASP.Net Pages

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?

Farshad
February 21, 2008

# re: Capturing Output from ASP.Net Pages

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.

Madelina
April 25, 2008

# re: Capturing Output from ASP.Net Pages

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?

Ho
June 25, 2008

# re: Capturing Output from ASP.Net Pages

Thanks, man
It's really what i want to know.

Henry R
July 19, 2008

# re: Capturing Output from ASP.Net Pages

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

Morder VonAllem
October 29, 2008

# re: Capturing Output from ASP.Net Pages

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

Morder VonAllem
October 29, 2008

# re: Capturing Output from ASP.Net Pages

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.

Pawan Kumar
January 28, 2009

# re: Capturing Output from ASP.Net Pages

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.

shanwaj
May 07, 2009

# re: Capturing Output from ASP.Net Pages

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

Ajit
October 13, 2009

# re: Capturing Output from ASP.Net Pages

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?

Billy falconer
February 26, 2010

# re: Capturing Output from ASP.Net Pages

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

{STATIC} hippo
March 01, 2010

# Find/Replace on Render

Find/Replace on Render

Twitter Mirror
March 29, 2010

# RT @ibaumann: Capturing Output from ASP.Net Pages http://www.west-wind.com/weblog/posts/481.aspx

RT @ibaumann : Capturing Output from ASP.Net Pages http://www.west-wind.com/weblog/posts/481.aspx

Twitter Mirror
March 29, 2010

# 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

Twitter Mirror
March 29, 2010

# Capturing Output from ASP.Net Pages http://www.west-wind.com/weblog/posts/481.aspx (via @ibaumann)

Capturing Output from ASP.Net Pages http://www.west-wind.com/weblog/posts/481.aspx (via @ibaumann )

gsalunkhe
June 11, 2010

# re: Capturing Output from ASP.Net Pages

Thanks for the help. After searching a Lot on net I got this article. Thank you very much.

Madhanlal JM
July 08, 2010

# re: Capturing Output from ASP.Net Pages

Very useful article. Thank you..

Priyan Perera
August 03, 2010

# re: Capturing Output from ASP.Net Pages

Thanks...was looking for this article for some time...

Mike
November 19, 2010

# re: Capturing Output from ASP.Net Pages

Fantastically useful, even after years. Like one of the first posters said, legendary.

Jon
February 06, 2012

# re: Capturing Output from ASP.Net Pages

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.

snehasish chowdhury
March 02, 2012

# re: Capturing Output from ASP.Net Pages

You save my 10000000 $ time

Mark
May 08, 2014

# re: Capturing Output from ASP.Net Pages

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.

Sachin
December 29, 2016

# re: Capturing Output from ASP.Net Pages

Does this work in static class as well? As I'm getting assertion failure error. Please help. Thanks 😃


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