I have a VB.NET / ASP.NET web application (on .NET 4.7) that I'm trying to add a virtual folder, and have had no success. Perhaps I'm doing it wrong, or I'm missing something; I would greatly appreciate some help with this.
After some research, I created some classes based on VirtualPathProvider, using ~/Repository for the virtual folder, and a local folder on C: for the physical path (i.e. C:\Temp\Repository).
I can see that when the ~/Repository folder is accessed that my custom class (RepositoryPathProvider) is being accessed - such as the FileExists, DirectoryExists and the GetFile functions; however, I am getting a 404 not found error on the web page for elements within the virtual folder (i.e. images or css).
Can someone look at my code, and tell me what I might be doing wrong? Or, alternately, provide a better or easier method to do this. Thanks!
Global.asax.vb:
If Not settings.BMSRepositoryPath Is Nothing Then
Dim rpp As New RepositoryPathProvider("~/Repository", settings.BMSRepositoryPath)
HostingEnvironment.RegisterVirtualPathProvider(rpp)
End If
RepositoryPathProvider.vb:
Public Class RepositoryPathProvider : Inherits VirtualPathProvider
Private ReadOnly _virtualDir As String 'Virtual folder path, i.e. ~/VirtualFolder
Private ReadOnly _physicalPath As String 'Physical folder path, i.e. C:\PhysicalPath\MyFolder
Public Sub New(virtualDir As String, physicalPath As String)
MyBase.New()
_virtualDir = virtualDir
_physicalPath = physicalPath
End Sub
Public Overrides Function FileExists(virtualPath As String) As Boolean
If IsVirtualFolderPath(virtualPath) Then
Dim physicalPath As String = MapVirtualToPhysicalPath(virtualPath)
Return System.IO.File.Exists(physicalPath)
End If
Dim retval = Previous.FileExists(virtualPath)
Return retval
End Function
Public Overrides Function DirectoryExists(virtualPath As String) As Boolean
If IsVirtualFolderPath(virtualPath) Then
Dim physicalPath As String = MapVirtualToPhysicalPath(virtualPath)
Return System.IO.Directory.Exists(physicalPath)
End If
Return Previous.DirectoryExists(virtualPath)
End Function
Public Overrides Function GetFile(virtualPath As String) As VirtualFile
If IsVirtualFolderPath(virtualPath) Then
Dim physicalPath As String = MapVirtualToPhysicalPath(virtualPath)
Dim retval = New CustomVirtualFile(virtualPath, physicalPath)
Return retval
End If
Return Previous.GetFile(virtualPath)
End Function
Public Overrides Function GetDirectory(virtualPath As String) As VirtualDirectory
If IsVirtualFolderPath(virtualPath) Then
Dim physicalPath As String = MapVirtualToPhysicalPath(virtualPath)
Return New CustomVirtualDirectory(virtualPath, physicalPath)
End If
Return Previous.GetDirectory(virtualPath)
End Function
Private Function IsVirtualFolderPath(virtualPath As String) As Boolean
Dim appRelativePath As String = VirtualPathUtility.ToAppRelative(virtualPath)
Return appRelativePath.StartsWith(_virtualDir, StringComparison.OrdinalIgnoreCase)
End Function
Private Function MapVirtualToPhysicalPath(virtualPath As String) As String
Dim appRelativePath As String = VirtualPathUtility.ToAppRelative(virtualPath)
Dim relativePath As String = appRelativePath.Substring(_virtualDir.Length).Replace("/", "\")
If relativePath.StartsWith("\") Then relativePath = relativePath.Substring(1)
Dim retval As String = System.IO.Path.Combine(_physicalPath, relativePath)
Return retval
End Function
End Class
CustomVirtualFile.vb:
Public Class CustomVirtualFile
Inherits VirtualFile
Private ReadOnly _physicalPath As String
Public Sub New(virtualPath As String, physicalPath As String)
MyBase.New(virtualPath)
_physicalPath = physicalPath
End Sub
Public Overrides Function Open() As System.IO.Stream
Return System.IO.File.OpenRead(_physicalPath)
End Function
End Class
CustomVirtualDirectory.vb:
Public Class CustomVirtualDirectory
Inherits VirtualDirectory
Private ReadOnly _physicalPath As String
Public Sub New(virtualPath As String, physicalPath As String)
MyBase.New(virtualPath)
_physicalPath = physicalPath
End Sub
Public Overrides ReadOnly Property Children() As System.Collections.IEnumerable
Get
Return New List(Of Object)()
End Get
End Property
Public Overrides ReadOnly Property Files() As System.Collections.IEnumerable
Get
Dim m_files As New List(Of VirtualFile)()
If System.IO.Directory.Exists(_physicalPath) Then
For Each filePath As String In System.IO.Directory.GetFiles(_physicalPath)
Dim fileName As String = System.IO.Path.GetFileName(filePath)
Dim virtualPath As String = VirtualPathUtility.Combine(virtualPath, fileName)
m_files.Add(New CustomVirtualFile(virtualPath, filePath))
Next
End If
Return m_files
End Get
End Property
Public Overrides ReadOnly Property Directories() As System.Collections.IEnumerable
Get
Return New List(Of VirtualDirectory)()
End Get
End Property
End Class