Link to home
Start Free TrialLog in
Avatar of r79abc
r79abc

asked on

Save a ASPX page to file/disk

People using my tool via WEB need to save the .aspx page to disk and see it to another pc (offline).
So, imagine that the user sees a page.aspx, that is a report containing only stupid html, now I'm looking for something like
- user clicks a button
- a offline version of page.aspx (pageoff.html) is send as file to the user


Is it possible?
Thanks
Avatar of Edward Diaz
Edward Diaz
Flag of United States of America image

If they did save it to their computers for running remember that they would have to install the .net framework and IIS if they even have it at all...as an aspx page is compiled at runtime by the .net framework. Otherwise they could just go to file--> save as in their browser
you could also look into making your app a webservice, so it eliminates the hassle of everyone having a copy because it would run off your server.
if it's a report, they could even copy and paste it to excel
from the webpage itself I mean. Sorry I posted several times...I have ideas flowing.
Avatar of esteban_felipe
esteban_felipe

Hi r79abc,

All you need to do is to call Page.Render and pass it a Html32TextWriter that's under your control. That's exactly what the framework does. Check out this sample (in C#.. i don't do VB)

using System;
using System.Collections;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Web;
using System.Web.SessionState;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.HtmlControls;
using System.IO;
namespace WebApplication1
{
      public class WebForm1 : System.Web.UI.Page
      {
            protected System.Web.UI.WebControls.Button Button1;
            protected System.Web.UI.WebControls.Label Label1;
      
            private void Page_Load(object sender, System.EventArgs e)
            {
                  if(!Page.IsPostBack)
                  {
                        Label1.Text="Hello world!";
                  }
            }

            #region Web Form Designer generated code
            override protected void OnInit(EventArgs e)
            {
                  //
                  // CODEGEN: This call is required by the ASP.NET Web Form Designer.
                  //
                  InitializeComponent();
                  base.OnInit(e);
            }
            
            /// <summary>
            /// Required method for Designer support - do not modify
            /// the contents of this method with the code editor.
            /// </summary>
            private void InitializeComponent()
            {    
                  this.Button1.Click += new System.EventHandler(this.Button1_Click);
                  this.Load += new System.EventHandler(this.Page_Load);

            }
            #endregion

            private void Button1_Click(object sender, System.EventArgs e)
            {
                  Button1.Visible = false;
                  MemoryStream renderedPage = new MemoryStream();
                  Html32TextWriter myWriter = new Html32TextWriter(new StreamWriter(renderedPage));
                  this.Render(myWriter);
                  myWriter.Close();
                  Response.Clear();
                  Response.AddHeader("Content-Disposition", "attachment; filename=yourpage.html");
                  Response.ContentType = "applicationoctet-stream";
                  Response.BinaryWrite(renderedPage.GetBuffer());
                  Response.End();
            }
      }
}

Just a final advice. Don't use Response.Write in the page you want to be rendered-downloadable. I hope this could help. Good luck

Esteban Felipe
www.estebanf.com
r79abc,

Here's the HMTL of that page:

<%@ Page language="c#" Codebehind="WebForm1.aspx.cs" AutoEventWireup="false" Inherits="WebApplication1.WebForm1" %>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" >
<HTML>
      <HEAD>
            <title>WebForm1</title>
            <meta name="GENERATOR" Content="Microsoft Visual Studio .NET 7.1">
            <meta name="CODE_LANGUAGE" Content="C#">
            <meta name="vs_defaultClientScript" content="JavaScript">
            <meta name="vs_targetSchema" content="http://schemas.microsoft.com/intellisense/ie5">
      </HEAD>
      <body MS_POSITIONING="GridLayout">
            <form id="Form1" method="post" runat="server">
                  <asp:Label id="Label1" style="Z-INDEX: 101; LEFT: 8px; POSITION: absolute; TOP: 8px" runat="server">Label</asp:Label>
                  <asp:Button id="Button1" style="Z-INDEX: 102; LEFT: 16px; POSITION: absolute; TOP: 56px" runat="server"
                        Text="Get Rendered page without this button"></asp:Button>
            </form>
      </body>
</HTML>


Esteban Felipe
www.estebanf.com
Avatar of r79abc

ASKER

That is really nice code. It works really well.
But:
- in my code there are images (from webchart graph dll) and these (at least the link) are not copied
- A used things like Panel1.Controls.Add ( new Label .... ) and the result is not visible.

Is it possible to solve also these problems?
Thanks




-------------- Here there is your code modified
<%@ Page Language="C#" autoeventwireup="false" %>
<%@ Register TagPrefix="Web" Namespace="WebChart" Assembly="WebChart, Version=1.1.1.3, Culture=neutral, PublicKeyToken=eac822d9c4196ba1" %>
<%@ import Namespace="System" %>
<%@ import Namespace="System.Collections" %>
<%@ import Namespace="System.ComponentModel" %>
<%@ import Namespace="System.Data" %>
<%@ import Namespace="System.Drawing" %>
<%@ import Namespace="System.Web" %>
<%@ import Namespace="System.Web.SessionState" %>
<%@ import Namespace="System.Web.UI" %>
<%@ import Namespace="System.Web.UI.WebControls" %>
<%@ import Namespace="System.Web.UI.HtmlControls" %>
<%@ import Namespace="System.IO" %>
<script runat="server">

    private void Page_Load(object sender, System.EventArgs e)
    {
         if(!Page.IsPostBack)
         {
              Label1.Text="Hello world!";
                ColumnChart chart = new ColumnChart();
   
                chart.Fill.Color = Color.FromArgb(50, Color.SteelBlue);
                chart.Line.Color = Color.SteelBlue;
                chart.Line.Width = 2;
   
                chart.Legend = "WebChart information";
                chart.Data.Add( new ChartPoint("Jan", 10) );
   
                ChartControl1.Charts.Add(chart);
                ChartControl1.RedrawChart();
   
                Label l2=new Label();
                l2.Text = "TEST";
                Panel1.Controls.Add(l2);
         }
    }
   
    #region Web Form Designer generated code
    override protected void OnInit(EventArgs e)
    {
         //
         // CODEGEN: This call is required by the ASP.NET Web Form Designer.
         //
         InitializeComponent();
         base.OnInit(e);
    }
   
    /// <summary>
    /// Required method for Designer support - do not modify
    /// the contents of this method with the code editor.
    /// </summary>
    private void InitializeComponent()
    {
         this.Button1.Click += new System.EventHandler(this.Button1_Click);
         this.Load += new System.EventHandler(this.Page_Load);
   
    }
    #endregion
   
    private void Button1_Click(object sender, System.EventArgs e)
    {
         Button1.Visible = false;
         MemoryStream renderedPage = new MemoryStream();
         Html32TextWriter myWriter = new Html32TextWriter(new StreamWriter(renderedPage));
         this.Render(myWriter);
         myWriter.Close();
         Response.Clear();
         Response.AddHeader("Content-Disposition", "attachment; filename=yourpage.html");
         Response.ContentType = "applicationoctet-stream";
         Response.BinaryWrite(renderedPage.GetBuffer());
         Response.End();
    }

</script>
<html>
<head>
    <title>WebForm1</title>
    <meta content="Microsoft Visual Studio .NET 7.1" name="GENERATOR" />
    <meta content="C#" name="CODE_LANGUAGE" />
    <meta content="JavaScript" name="vs_defaultClientScript" />
    <meta content="http://schemas.microsoft.com/intellisense/ie5" name="vs_targetSchema" />
</head>
<body ms_positioning="GridLayout">
    <form id="Form1" method="post" runat="server">
        <p>
            <asp:Label id="Label1" style="Z-INDEX: 101; LEFT: 550px; POSITION: absolute; TOP: 281px" runat="server">Label</asp:Label>
            <asp:Button id="Button1" style="Z-INDEX: 102; LEFT: 64px; POSITION: absolute; TOP: 407px" runat="server" Text="Get Rendered page without this button"></asp:Button>
            <Web:ChartControl id="ChartControl1" runat="Server" Width="500" Height="350"></Web:ChartControl>
            <asp:Panel id="Panel1" runat="server">Panel</asp:Panel>
        </p>
    </form>
</body>
</html>

Avatar of r79abc

ASKER

Used all points...
Avatar of r79abc

ASKER

I've seen that I need to ovveride the render for all control inserted on the page... but I've no idea of what it means...
no... you don-t need to override nothing... just call Page.Render with your own Html32Writer.... my sample should work with any page.
Avatar of r79abc

ASKER

I konw that your example works well.
BUT when I write something like

Label l2=new Label();
l2.Text = "TEST";
Panel1.Controls.Add(l2);

then Button1_Click function doen't display in .html document the label2

Why? There is a soluton?
are you doing that in the same request than button1_click?. If not your problem is about dinamic controls created at runtime. Those controls are not stored between postbacks automaticly, so you will have to do it yourself.
Avatar of r79abc

ASKER

Sorry, I'm a newbie...
This is your code that I've modified..
Label2 is not displayed.. could you give me the final help?

---------------
<%@ Page Language="C#" autoeventwireup="false" %>
<%@ import Namespace="System" %>
<%@ import Namespace="System.Collections" %>
<%@ import Namespace="System.ComponentModel" %>
<%@ import Namespace="System.Data" %>
<%@ import Namespace="System.Drawing" %>
<%@ import Namespace="System.Web" %>
<%@ import Namespace="System.Web.SessionState" %>
<%@ import Namespace="System.Web.UI" %>
<%@ import Namespace="System.Web.UI.WebControls" %>
<%@ import Namespace="System.Web.UI.HtmlControls" %>
<%@ import Namespace="System.IO" %>
<script runat="server">

    private void Page_Load(object sender, System.EventArgs e)
         {
              if(!Page.IsPostBack)
              {
                   Label1.Text="Hello world!";
                   Label l2=new Label();
                   l2.Text = "THIS SHOULD BE DISPLAYED ALSO IN yourpage.html ";
                   Panel1.Controls.Add(l2);
              }
         }

         #region Web Form Designer generated code
         override protected void OnInit(EventArgs e)
         {
              //
              // CODEGEN: This call is required by the ASP.NET Web Form Designer.
              //
              InitializeComponent();
              base.OnInit(e);
         }

         /// <summary>
         /// Required method for Designer support - do not modify
         /// the contents of this method with the code editor.
         /// </summary>
         private void InitializeComponent()
         {
              this.Button1.Click += new System.EventHandler(this.Button1_Click);
              this.Load += new System.EventHandler(this.Page_Load);

         }
         #endregion

         private void Button1_Click(object sender, System.EventArgs e)
         {
              Button1.Visible = false;
              MemoryStream renderedPage = new MemoryStream();
              Html32TextWriter myWriter = new Html32TextWriter(new StreamWriter(renderedPage));
              this.Render(myWriter);
              myWriter.Close();
              Response.Clear();
              Response.AddHeader("Content-Disposition", "attachment; filename=yourpage.html");
              Response.ContentType = "applicationoctet-stream";
              Response.BinaryWrite(renderedPage.GetBuffer());
              Response.End();
         }

</script>
<html>
<head>
    <title>WebForm1</title>
    <meta content="Microsoft Visual Studio .NET 7.1" name="GENERATOR" />
    <meta content="C#" name="CODE_LANGUAGE" />
    <meta content="JavaScript" name="vs_defaultClientScript" />
    <meta content="http://schemas.microsoft.com/intellisense/ie5" name="vs_targetSchema" />
</head>
<body ms_positioning="GridLayout">
    <form id="Form1" method="post" runat="server">
        <p>
            <asp:Label id="Label1" style="Z-INDEX: 101; LEFT: 240px; POSITION: absolute; TOP: 23px" runat="server">Label</asp:Label>
            <asp:Button id="Button1" style="Z-INDEX: 102; LEFT: 28px; POSITION: absolute; TOP: 117px" runat="server" Text="Get Rendered page without this button"></asp:Button>
            <asp:Panel id="Panel1" runat="server">Panel</asp:Panel>
        </p>
    </form>
</body>
</html>
ASKER CERTIFIED SOLUTION
Avatar of esteban_felipe
esteban_felipe

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of r79abc

ASKER

OK.. it works.
There are others task opened..For example if the page has an image.. what I need to do?

But or now it's enough.. (but.. if u have a quick solution.. you are welcome!)
Anyway you did for me a great work.


Thank you!
ohh... with images it will be much harder. I can think in several solutions but none it's easy. You will need to produce your rendered html page, then will need to parse it to find the images tags, transform them to target local images and include those images in your download (maybe in a zip file).... Another approach that I would take would be to use a commercial or open source component to generate pdf files with my report. Maybe this way is more expensive, but i'm sure it will be easier...