This is a migrated thread and some comments may be shown as answers.

tag vs. fullPath in custom FileBrowserContentProvider

3 Answers 161 Views
Editor
This is a migrated thread and some comments may be shown as answers.
Carl
Top achievements
Rank 1
Carl asked on 08 Jul 2008, 12:11 PM
I'm tring to implement a custom FileBrowserContentProvider, but i have a few questions.

Why does "selectedUrl" and "selectedItemTag" never differ? Even though I set "fullPath" and "tag" different when i create DirectoryItems. I would like the fullPath to be viewed to the user, but the tag do be an ID for my internal representation.

Also, you should point out more in the documentation that you shall look up "selectedItemTag" and not "path", when ResolveRootDirectoryAsTree(string path) is exectued. (which indeed is very non-logic too)

greetings /Carl

3 Answers, 1 is accepted

Sort by
0
Axe
Top achievements
Rank 1
answered on 10 Jul 2008, 01:22 PM
I was going to ask a similar question as Carl. I have implemented a custom FileBrowserContentProvider to browse files from a non-virtual path and although it works I can't really work out the difference between some members in the DirectoryItem class constructor and what effect they would have it different contexts as they seem to have different behaviors particularly in the ResolveDirectory Method (I will need to confirm that. I will check my code again and post another thread). If you could elaborate a bit more on the differences between location, fullPath & tag that would be great. In my ResolveDirectory method I pass string.Empty to all 3 and it still works but can have strange side effects in the visible path textbox. It seems to add the sub folders regardless of what I put in either of those 3.

Regards
Axe
0
Shaun Peet
Top achievements
Rank 2
answered on 19 Aug 2008, 02:31 AM
This is funny.  I just opened a bug report about the exact same thing.  Seems we're all working on the same problems!

What I was doing for my implementation was trying to get a way for my users to know which folders were "uploadable" and which ones weren't.  I decided that the best way was to append the text " (upload)" next to the names of the folders (which should be obvious enough).  This caused all kinds of problems until I used the full path as the "Tag" instead of String.Empty.  But it all seems a little irrelevant in the end because the GenericFileLister control ignores the Tag anyway when sending arguments to the DeleteDirectory / DeleteFile methods.

I've even done all the grunt work for Telerik and fixed their code for them:

"Using Reflector, I've found exactly where this needs to be changed.  In Telerik.Web.UI.Widgets.FileManager:

Private Sub FileLister_DeleteItem(ByVal sender As Object, ByVal e As FileListerDeleteEventArgs)
    If (e.SelectedItem.Type = FileItemType.Directory) Then
        Me.ContentProvider.DeleteDirectory(e.SelectedItem.Path)
    Else
        Me.ContentProvider.DeleteFile(e.SelectedItem.Path)
    End If
End Sub

This should probably become:

Private Sub FileLister_DeleteItem(ByVal sender as ObjectByVal e As FileListerDeleteEventArgs)  
  Dim path As String = IIf(e.SelectedItem.Tag = String.Empty, e.SelectedItem.Path, e.SelectedItem.Tag)  
  If e.SelectedItem.Type = FileItemType.Directory Then 
    Me.ContentProvider.DeleteDirectory(path)  
  Else 
    Me.ContentProvider.DeleteFile(path)  
  End If 
End Sub 

"
I've asked for a custom build with the fix but at the very least hopefully this will be changed for the Q2 2008 SP1 release.

Here's my complete custom provider class, for those who are interested:

Public Class MyFileSystemContentProvider     
    Inherits FileSystemContentProvider     
    
  Public Sub New(ByVal context As HttpContext, ByVal searchPatterns As String(), ByVal viewPaths As String(), ByVal uploadPaths As String(), ByVal deletePaths As String(), ByVal selectedUrl As StringByVal selectedItemTag As String)     
    MyBase.New(context, searchPatterns, viewPaths, uploadPaths, deletePaths, selectedUrl, selectedItemTag)     
    Me.ProcessPaths(MyBase.ViewPaths)     
    Me.ProcessPaths(MyBase.UploadPaths)     
        Me.ProcessPaths(MyBase.DeletePaths)     
        MyBase.SelectedUrl = FileBrowserContentProvider.RemoveProtocolNameAndServerName(Me.GetAbsolutePath(MyBase.SelectedUrl))     
    End Sub    
    
  Public Overrides Function StoreBitmap(ByVal bitmap As System.Drawing.Bitmap, ByVal url As StringByVal format As System.Drawing.Imaging.ImageFormat) As String    
    Dim quant As OctreeQuantizer = New OctreeQuantizer(128, 8)     
    Return MyBase.StoreBitmap(quant.Quantize(bitmap), url, format)     
  End Function    
    
  Public Overrides Function StoreFile(ByVal file As UploadedFile, ByVal path As StringByVal name As StringByVal ParamArray arguments As String()) As String    
    Dim relFolder As String = path     
    Dim relFull = IO.Path.Combine(relFolder, name)     
    Dim mapFolder As String = MyBase.Context.Server.MapPath(relFolder)     
    Dim mapFull As String = MyBase.Context.Server.MapPath(relFull)     
    If file.GetExtension = ".zip" Then    
      Dim lastValidFile As String = ""    
      Using ZIS As New ZipInputStream(file.InputStream)     
        Dim ZE As ZipEntry = ZIS.GetNextEntry     
        While Not IsNothing(ZE)     
          Dim strDir As String = IO.Path.GetDirectoryName(ZE.Name)     
          Dim strFil As String = IO.Path.GetFileName(ZE.Name)     
          If strDir.Length > 0 Then    
            IO.Directory.CreateDirectory(mapFolder & strDir)     
          End If    
          If strFil <> String.Empty Then    
            If IsValidFileTypeAfterUnZip(ZE.Name) Then    
              DeleteFileIfAlreadyExists(mapFolder & ZE.Name)     
              lastValidFile = relFolder & ZE.Name     
              Using FS As FileStream = IO.File.Create(mapFolder & ZE.Name)     
                Dim i As Integer = 2048     
                Dim b As Byte() = New Byte(2048) {}     
                While True    
                  i = ZIS.Read(b, 0, b.Length)     
                  If i > 0 Then    
                    FS.Write(b, 0, i)     
                  Else    
                    Exit While    
                  End If    
                End While    
              End Using     
            End If    
          End If    
          ZE = ZIS.GetNextEntry     
        End While    
      End Using     
      DeleteEmptyDirectoriesAfterZip(mapFolder)     
      Return lastValidFile     
    Else    
      DeleteFileIfAlreadyExists(mapFull)     
      file.SaveAs(mapFull)     
      Return relFull     
    End If    
    End Function    
    
  Private Sub DeleteFileIfAlreadyExists(ByVal mapFull As String)     
    If IO.File.Exists(mapFull) Then    
      IO.File.Delete(mapFull)     
    End If    
  End Sub    
    
  Private Sub DeleteEmptyDirectoriesAfterZip(ByVal mapFolder As String)     
    For Each Dir As String In IO.Directory.GetDirectories(mapFolder)     
      DeleteEmptyDirectoriesAfterZip(Dir)     
      If IO.Directory.GetFiles(Dir).Count = 0 And IO.Directory.GetDirectories(Dir).Count = 0 Then    
        IO.Directory.Delete(Dir)     
      End If    
    Next    
  End Sub    
    
  Private Function IsValidFileTypeAfterUnZip(ByVal fileName As StringAs Boolean    
    Dim strExt As String = Right(fileName, fileName.Length - fileName.LastIndexOf(".")).ToLower     
    If strExt = ".zip" Then    
      Return False    
    Else    
      For Each s As String In MyBase.SearchPatterns     
        s = Right(s, s.Length - s.LastIndexOf(".")).ToLower     
        If s = strExt Then Return True    
      Next    
    End If    
    Return False    
    End Function    
    
    Public Overrides Function ResolveRootDirectoryAsTree(ByVal path As StringAs DirectoryItem     
        Dim dir As New DirectoryInfo(MyBase.Context.Server.MapPath(path))     
        If Not dir.Exists Then    
            Return Nothing    
        End If    
        Dim virtualName As String = IIf((path = "/"), String.Empty, VirtualPathUtility.GetFileName(path))     
        Dim location As String = IIf((path = "/"), "/", VirtualPathUtility.AppendTrailingSlash(VirtualPathUtility.GetDirectory(path)))     
        Dim fullPath As String = path     
        Dim tag As String = path     
        Dim permissions As PathPermissions = Me.GetPermissions(fullPath)     
        Dim flag As Boolean = IIf(IsListMode, TrueMe.IsParentOf(fullPath, Me.SelectedUrl))     
        Dim flag2 As Boolean = Me.IsParentOf(fullPath, Me.SelectedUrl)     
        Dim directories As DirectoryItem() = IIf(flag, GetDirectories(dir, fullPath), New DirectoryItem(0 - 1) {})     
        Dim files As FileItem() = IIf(flag2, GetFiles(dir, permissions, (fullPath & "/")), New FileItem(0 - 1) {})     
        'If CanUpload(path) Then virtualName = "<span style=""color:green;"">" & virtualName & "</span>"      
        If CanUpload(path) Then virtualName += " (upload)"    
        If path.ToLower.Contains("secure/documents"Then virtualName += " (secure)"    
        Return New DirectoryItem(virtualName, location, fullPath, tag, permissions, files, directories)     
    End Function    
    
    Protected Function GetDirectories(ByVal directory As DirectoryInfo, ByVal parentPath As StringAs DirectoryItem()     
        Dim directories As DirectoryInfo() = directory.GetDirectories     
        Dim list As New ArrayList     
        Dim i As Integer    
        For i = 0 To directories.Length - 1     
            Dim info As DirectoryInfo = directories(i)     
            If Me.IsValid(info) Then    
                list.Add(GetDirectory(info, (VirtualPathUtility.AppendTrailingSlash(parentPath) & info.Name)))     
            End If    
        Next i     
        Return DirectCast(list.ToArray(GetType(DirectoryItem)), DirectoryItem())     
    End Function    
    
    Public Function GetDirectory(ByVal dir As DirectoryInfo, ByVal fullPath As StringAs DirectoryItem     
        Dim virtualName As String = dir.Name     
        If CanUpload(fullPath) Then virtualName += " (upload)"    
        If fullPath.ToLower.Contains("secure/documents"Then virtualName += " (secure)"    
        Return GetDirectory(dir, virtualName, String.Empty, fullPath, fullPath)     
    End Function    
    
    Public Function GetDirectory(ByVal dir As DirectoryInfo, ByVal virtualName As StringByVal location As StringByVal fullPath As StringByVal tag As StringAs DirectoryItem     
        Dim permissions As PathPermissions = Me.GetPermissions(fullPath)     
        Dim flag As Boolean = IIf(IsListMode, TrueMe.IsParentOf(fullPath, Me.SelectedUrl))     
        Dim flag2 As Boolean = Me.IsParentOf(fullPath, Me.SelectedUrl)     
        Dim directories As DirectoryItem() = IIf(flag, GetDirectories(dir, fullPath), New DirectoryItem(0 - 1) {})     
        Return New DirectoryItem(virtualName, location, fullPath, tag, permissions, IIf(flag2, GetFiles(dir, permissions, (fullPath & "/")), New FileItem(0 - 1) {}), directories)     
    End Function    
    
    Protected Function GetFiles(ByVal directory As DirectoryInfo, ByVal permissions As PathPermissions, ByVal location As StringAs FileItem()     
        Dim list As New ArrayList     
        Dim hashtable As New Hashtable     
        Dim str As String    
        For Each str In Me.SearchPatterns     
            Dim info As FileInfo     
            For Each info In directory.GetFiles(str)     
                If (Not hashtable.ContainsKey(info.FullName) AndAlso Me.IsValid(info)) Then    
                    hashtable.Add(info.FullName, String.Empty)     
                    Dim tag As String = IIf(Me.IsListMode, (location & info.Name), String.Empty)     
                    list.Add(New FileItem(info.Name, info.Extension, info.Length, String.Empty, String.Empty, tag, permissions))     
                End If    
            Next    
        Next    
        Return DirectCast(list.ToArray(GetType(FileItem)), FileItem())     
    End Function    
    
    Public Overrides Function CreateDirectory(ByVal path As StringByVal name As StringAs String    
        If (name.IndexOfAny(IO.Path.GetInvalidPathChars) >= 0) Then    
            Return "InvalidCharactersInPath"    
        End If    
        Dim str As String = MyBase.Context.Server.MapPath((VirtualPathUtility.AppendTrailingSlash(path) & name))     
        Try    
            Directory.CreateDirectory(str)     
        Catch exception1 As UnauthorizedAccessException     
            Return "NoPermissionsToCreateFolder"    
        End Try    
        Return String.Empty     
    End Function    
    
    Public Overrides Function DeleteDirectory(ByVal path As StringAs String    
        path = path.Replace(" (upload)""").Replace(" (secure)""")     
        Dim str As String = MyBase.Context.Server.MapPath(path)     
        Try    
            If Directory.Exists(str) Then    
                Directory.Delete(str, True)     
            End If    
        Catch exception1 As UnauthorizedAccessException     
            Return "NoPermissionsToDeleteFolder"    
        End Try    
        Return String.Empty     
    End Function    
    
    Public Overrides Function DeleteFile(ByVal path As StringAs String    
        path = path.Replace(" (upload)""").Replace(" (secure)""")     
        Dim str As String = MyBase.Context.Server.MapPath(path)     
        Try    
            If File.Exists(str) Then    
                If ((File.GetAttributes(str) And FileAttributes.ReadOnly) = FileAttributes.ReadOnlyThen    
                    Return "FileReadOnly"    
                End If    
                File.Delete(str)     
            End If    
        Catch exception1 As UnauthorizedAccessException     
            Return "NoPermissionsToDeleteFile"    
        End Try    
        Return String.Empty     
    End Function    
    
    Public Function IsListMode() As Boolean    
        If Me.DisplayMode = FileBrowserDisplayMode.List Then Return True Else Return False    
    End Function    
    
End Class    
 


Shaun.
0
Shaun Peet
Top achievements
Rank 2
answered on 19 Aug 2008, 03:13 PM
I've also learned that injecting *anything* into the virtualName of the DirectoryItem causes a whole slew of other problems - the biggest one being that the virtual name is part of the path returned to the editor when a file is selected (oops).  It also causes the image previewer to not work in the Image Manager, and I'm sure it throws off the file type settings for the other dialogs as well.

Add 5 more votes for separating the tag from the virtualName.

I would also like to propose another option.  Namely, adding another property to the DirectoryItem called "ImageUrl".  The default wold be the folder icon that is currently in use, but it would allow us to specify another icon instead if we want to give the end-user a visual clue as to the permissions of the folder.  In my case, a folder can be read-only or "uploadable", and may or may not be in a password-protected section of the site.  So I'll want to have four icons that represent the different possibilities.  That is essentially what I was trying to do by injecting html into the virtualName, but like I said, that breaks alot of other things with the dialog.

Anybody else think that might be a good idea?  Telerik, would that even be possible with all the javascript serialization that is going on?

Shaun.
Tags
Editor
Asked by
Carl
Top achievements
Rank 1
Answers by
Axe
Top achievements
Rank 1
Shaun Peet
Top achievements
Rank 2
Share this question
or