How It Works
Figure 5 shows the basic template used for the construction of the ExportPanel
custom Web control. If you’ve been following this column, this code should look
quite familiar. After importing some common namespaces and establishing some basic
toolbox support, the class is declared to inherit from the Panel control.
Imports System.ComponentModel
Imports System.Web.UI
<ToolboxData("<{0}:ExportPanel
runat=server>" _
+ "</{0}:ExportPanel>")>
_
Public Class
ExportPanel
Inherits System.Web.UI.WebControls.Panel
'TODO: Properties
'TODO: Methods
End Class
Figure 5. Every custom web control starts
out with a template very similar to this.
Figure 6 lists the definitions for the public properties of the ExportPanel
control, and a public enum named AppType. The ExportType property encapsulates a
private variable named m_ExportType, which is of type AppType. The attributes specify
that the ExportType property will be bindable, and will be displayed in the Behavior
section of the property window when being used at design time.
'Contains the
list of supported export applications
Public Enum
AppType
HTML
Word
Excel
PowerPoint
WordPerfect
End Enum
'Manage the
requested export type
Private m_ExportType
As AppType
<Bindable(True),
Category("Behavior")> _
Public Property
ExportType() As AppType
Get
Return m_ExportType
End Get
Set(ByVal Value As
AppType)
m_ExportType = Value
End Set
End Property
'Filename property
Dim m_FileName
As String = "File1"
<Bindable(True),
Category("Appearance"), _
DefaultValue("File1")>
_
Public Property
FileName() As String
Get
Return m_FileName
End Get
Set(ByVal Value As
String)
m_FileName = Value
End Set
End Property
'Open the application
externally or host in the browser?
Private m_OpenInBrowser
As Boolean = True
<Bindable(True),Category("Behavior"),DefaultValue("True")>
_
Public Property
OpenInBrowser() As Boolean
Get
If ExportType = AppType.WordPerfect
Then
'WordPerfect can't be hosted inside IE
Return False
Else
If ExportType = AppType.HTML Then
'HTML will always be displayed
'on the current page.
Return
True
Else
Return m_OpenInBrowser
End If
End If
End Get
Set(ByVal Value As
Boolean)
m_OpenInBrowser = Value
End Set
End Property
Figure 6: The AppType enum is used by
the ExportType property to list and control the applications supported for export.
FileName is a fairly standard string property, and OpenInBrowser is a Boolean property
that handles a couple of special cases.
FileName is a fairly standard string whose job is to hold the file name that will
be given to the application handling the export. The final property (named OpenInBrowser)
controls whether the application will be hosted inside the browser or not. Because
WordPerfect can’t be hosted inside Internet Explorer, the property will always return
False when this ExportType is chosen. Additionally, the HTML ExportType signifies
that the control will be displayed as a standard panel in the current page, so it
returns True in this case.
Finally, the Panel control’s Render method is overridden, as shown in Figure 7.
This is where all the real work is done. As mentioned previously, if the HTML ExportType
is selected, the control should act as a standard Panel control. The easiest way
to accomplish this is to have the underlying Panel control do its usual rendering,
so MyBase.Render is called to do all the work. Otherwise, some fancy rendering will
be necessary.
Protected Overrides
Sub Render(ByVal
output As _
System.Web.UI.HtmlTextWriter)
If ExportType = AppType.HTML Then
MyBase.Render(output)
Else
'get rid of all the junk that's been
'rendered to the page so far
Page.Response.Clear()
'start a very simple html document
Page.Response.Write("<html><head></head><body>")
'determine whether to open the document inside
'the browser or to an launch external app
Dim OpenType As String
= "inline"
If OpenInBrowser = False
Then OpenType = "attachment"
'determine the content type and file extension
Dim FileExtension As
String
With Page.Response
Select Case ExportType
Case AppType.Excel
.ContentType = "application/ms-excel"
FileExtension = ".xls"
Case AppType.Word
.ContentType = "application/ms-word"
FileExtension = ".doc"
Case AppType.Powerpoint
.ContentType = "application/ms-powerpoint"
FileExtension = ".ppt"
Case AppType.WordPerfect
.ContentType = "application/wordperfect9"
FileExtension = ".wpd"
End Select
End With
'build full filename with extension (if necessary)
Dim FullFileName As
String = FileName.Trim().ToLower
If Not FullFileName.EndsWith(FileExtension)
Then
FullFileName
+= FileExtension
End If
'Output the HTML header
Page.Response.AddHeader("Content-Disposition",
_
OpenType
+ ";filename=" + FullFileName)
'Output the contents of the panel
MyBase.RenderChildren(output)
'End the HTML document
Page.Response.Write("</body></html>")
Page.Response.End()
End If
End Sub
Figure 7: The Render method is where
all the real work is done. A very basic HTML page is rendered and handed off to
the requested application.
Customized Rendering
By the time the Render method of the ExportPanel is executed, the Page_Load event
has already been called and ASP.NET has automatically added a bunch of headers and
ViewState junk that will only confuse the applications that are about to receive
the output from this page. (Also, other controls may be on the page outside the
borders of the ExportPanel, and these should not be exported.) Therefore, it is
best to simplify things so the resulting HTML is as basic as possible, resulting
in more standard rendering no matter which application is used. So everything dumped
into the Page so far is cleared, and only the most basic HTML elements are added
to begin the new page.
Next, a final check is done to determine whether the application will be opened
within the browser or not. The string “inline” or “attachment” will be added to
a header further along in the code. This is what tells the browser how to open the
resulting document.
The Select Case block in the center of the method determines the ContentType that
many browsers require, as well as the file extension, which is also usually necessary
for the browser to interpret the type of application required to open the document.
The next code block simply ensures the file name actually ends up using that file
extension.
Next, a header is output to the Page’s Response stream. This header gives the browser
the file name and gives it the final request to open the application within the
document or not.
After all that preparation, the contents of the ExportPanel are finally ready to
be added to the output stream. It only takes a single line of code to do all that
work, by calling the RenderChildren method of the base Panel object.
To wrap things up, the closing tags of this basic HTML page are rendered, and the
Response is ended to help ensure no other controls on the page are exported besides
the ones inside the ExportPanel.
Design-time Details
After all the preceding code has been put into a Web control library project, it
can be compiled into a DLL and added to the Visual Studio.NET toolbox. Then it can
be dropped onto a Web form in any ASP.NET Web application and used just like any
other control in the toolbox.
Drag the ExportPanel onto a Web form, size it to the height and width of your liking,
and fill it with stuff. As mentioned earlier, input controls don’t tend to work
well in the resulting exports, so stick with standard reporting output such as grids,
labels, and other static text. My experimentations have also suggested that setting
the Web form’s PageLayout property to FlowLayout tends to display better results
than the default GridLayout.
You can set any of the standard Panel properties to make it look nice if you wish
to use it as a standard Panel. Then, by setting the ExportType property (either
at design time or run time) it will spring to life, providing seamless exporting
capabilities to your data presentations. As the resulting file arrives in the browser,
a dialog box will be presented to the user asking if they wish to save or open the
file. This browser security feature cannot be disabled via ASP.NET.
In essence, it all boils down to setting the appropriate content type, specifying
the file name, and requesting that the application be opened either inside the browser
or externally. It also helps to simplify the HTML so the various applications will
be able to display the resulting file easily and consistently.
|