Introduction
Have you ever had the problem of having to repeatedly copy images, style sheets etc. for every new web application? Me, not anymore. I created some code to embed all these general items into a DLL and to get these items from the DLL easily.
Background
At our company, we are developing several web applications for internal and external usage. These applications need to meet the in-house standards. In the past, we had developed a template which we copy every time we start a new application. This template includes default images, style sheets, page templates etc.
As we all know, the standard layout of things tends to change in time. Therefore, I figured: we can put all these standard things inside a library, and then only update the library DLL with an updated one when the layout has to change.
To achieve more flexibility, I defined the following problems:
- How can I get all layout items in a library, without having to copy all the items every time I use them?
- How can I get all items from the library?
- How can I get all items to the internet browser?
Using the code
The solution
- Embedded resources
All VS.NET items like images, HTML pages, style sheets etc., can be marked as "embedded resource" by selecting the property page for that item and setting "Building action" to "embedded resource".
After marking an item as an embedded resource, it will be embedded into the generated DLL, so now the DLL will contain all the layout items we need.
- Get embedded resources
To use the embedded resources, we need some code, so I wrote two methods to get an embedded resource as a stream or as a string. The function needs the name of the embedded item and a type that is used to get the assembly where the embedded resource is located (the given type can be any type within the DLL containing the embedded resources).
Public Class Resources
Public Shared Sub GetEmbeddedResourceToStream(ByVal p_objTypeForNameSpace _
As Type, ByVal p_strFileName As String, ByRef p_objOutputStream As Stream)
Dim l_objAssemble As [Assembly] = _
[Assembly].GetAssembly(p_objTypeForNameSpace)
Dim l_objStreamReader As BinaryReader
Dim l_strAllResources As String() = l_objAssemble.GetManifestResourceNames()
l_objStreamReader = New _
BinaryReader(l_objAssemble.GetManifestResourceStream(_
p_objTypeForNameSpace, p_strFileName))
Dim p_objInputStream As Stream = _
l_objAssemble.GetManifestResourceStream(p_objTypeForNameSpace, _
p_strFileName)
p_objInputStream.Position = 0
Const BUFFER_SIZE As Integer = 2048
Dim l_objByteBuffer(BUFFER_SIZE) As Byte
Dim l_intLength As Integer = _
p_objInputStream.Read(l_objByteBuffer, 0, BUFFER_SIZE)
While l_intLength > 0
p_objOutputStream.Write(l_objByteBuffer, 0, l_intLength)
l_intLength = p_objInputStream.Read(l_objByteBuffer, 0, BUFFER_SIZE)
End While
End Sub
Public Shared Function GetEmbeddedResource(ByVal p_objTypeForNameSpace _
As Type, ByVal p_strScriptFileName As String) As String
Dim s As StringBuilder = New StringBuilder
Dim ass As [Assembly] = [Assembly].GetAssembly(p_objTypeForNameSpace)
Dim sr As StreamReader
sr = New StreamReader(ass.GetManifestResourceStream(p_objTypeForNameSpace, _
p_strScriptFileName))
s.Append(sr.ReadToEnd())
Return s.ToString()
End Function
End Class
- HTTPHandlers and some streaming code
So now, we have the resource embedded in a DLL, we can get the content programmatically, but how can we stream the item to a web client?
First, you have to have some piece of code that will transform the embedded resource to an HTTPResponse. After that, we will have to be able to get the response to the client. This is all done by using an HTTPhandler.
I created a class that looks like this:
Imports System.Text
Imports System.Reflection
Imports System.IO
Public Class MyResources
Implements IHttpHandler
Public ReadOnly Property IsReusable() As Boolean _
Implements System.Web.IHttpHandler.IsReusable
Get
Return True
End Get
End Property
Public Sub ProcessRequest(ByVal context As System.Web.HttpContext) _
Implements System.Web.IHttpHandler.ProcessRequest
Dim l_strEmbeddedResourceName As String
Try
If context.Request.QueryString.Count <> 1 Then
context.Response.Write("<HTML><HEAD><SCRIPT>" & _
"alert('Resource specified not found')</SCRIPT></HEAD></HTML>")
Else
l_strEmbeddedResourceName = context.Request.QueryString(0)
context.Response.ClearHeaders()
context.Response.AddHeader("Content-Type", _
GetContentType(l_strEmbeddedResourceName))
SystemFramework.Resources.GetEmbeddedResourceToStream(Me.GetType, _
l_strEmbeddedResourceName, context.Response.OutputStream)
End If
Catch ex As Exception
Throw ex
End Try
End Sub
End Class
When creating a new web application, all you have to do is add the library to the references, and add the following lines to the web.config (under system.web
):
<httpHandlers> <add verb="*" path="Resource.aspx" type="MyResources, General"/>
</httpHandlers>
To get the resource in your web site, just reference it like "Resource.aspx?<resourcename>", so do something like this:
<img src="Resource.aspx?cool.gif"/>
Hope this solution is helpful to others.
Points of interest
Mmm, the entire article, of course!
History