First, I've defined an IDownloadService interface that is implemented by the class that formats the plain text files and generates the HTML content (the RozpravaRaw class - see below):
Public Interface IDownloadService
Sub SendItemToBrowser( _
ByVal itemID As String, _
ByVal response As HttpResponse)
End Interface
The
itemID argument identifies what should be downloaded. In the case of transcript files, it is the file name. The
response argument references the current
HttpResponse instance.
Second, I've implemented a generic Download.aspx page, which expects two QueryString variables passed to it:
- The Type variable contains a type name of a class that would handle the download by implementing the
IDownloadServiceinterface. - The Ref variable is the name of an item to be downloaded (i.e. a transcript file), which is passed as the
itemIDargument in the call toIDownloadService.SendItemToBrowser.
Third, I've added the actual IDownloadService implementation to a RozpravaRaw class ("rozprava" is a Slovak term for "debate"), which already handled other aspects of the transcript files processing:
Public Class RozpravaRaw
Implements IDownloadService
...
Private Sub SendItemToBrowser( _
ByVal itemID As String, _
ByVal response As System.Web.HttpResponse) _
Implements IDownloadService.SendItemToBrowser
' Generate content dynamically (Response.Write etc.)
End Sub
End Class
The processing goes as follows:
- The user views a list of transcripts in her browser. Each transcript file link is generated using the Download.aspx page, for example
Download.aspx?Type=NRozprava.RozpravaRaw&Ref=XXX030909101042000_030909101500000.txt. - The user clicks the link, which activates the
Download.aspxpage. - The
Page_Loadevent handler in theDownload.aspxpage extracts the Type and Ref elements from the query string, instantiates the designated type and calls theIDownloadService.SendItemToBrowsermethod, passing the Ref element as theitemIDargument:
Private Sub Page_Load( _
ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles MyBase.Load
Try
...
' Parse the query string - "Ref" and "Type" variables are mandatory.
Dim TypeName, Ref As String
Me.ParseQueryString(TypeName, Ref)
' Create an IDownloadService dynamicaly and delegate to it.
Dim Service As IDownloadService = CreateDownloadService(TypeName)
Service.SendItemToBrowser(Ref, Response)
Catch ex As Exception
SetError(ex.ToString())
Trace.Warn(ex.ToString())
Diagnostics.Trace.WriteLine(ex.ToString())
End Try
End Sub
Private Sub ParseQueryString( _
ByRef typeName As String, _
ByRef ref As String)
typeName = Request.QueryString("Type")
If typeName Is Nothing Then
typeName = String.Empty
End If
' If typeName contains a space, it is just HTML-encoded "+" sign,
' which the CLR uses when naming nested classes.
typeName = typeName.Replace(" "c, "+"c)
ref = Request.QueryString("Ref")
If ref Is Nothing Then
ref = String.Empty
End If
End Sub
Private Shared Function CreateDownloadService( _
ByVal typeName As String) As IDownloadService
Try
Dim Assm As System.Reflection.Assembly = System.Reflection.Assembly.GetExecutingAssembly()
Return DirectCast(Assm.CreateInstance(typeName, True), IDownloadService)
Catch ex As Exception
Throw New ApplicationException( _
String.Format("Unknown request ({0}).",
typeName), ex)
End Try
End Function
I've designed it this way because, besides the dynamic transcript file download, the application had to support downloading other file types (namely .DOC and .MP3 files). This way, the download link is always the same and the actual download content generation logic is placed within the particular IDownloadService implementation.
Comments