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
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
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
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:
This should probably become:
"
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:
Shaun.
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 Object, ByVal 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 String, ByVal 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 String, ByVal 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 String, ByVal name As String, ByVal 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 String) As 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 String) As 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, True, Me.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 String) As 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 String) As 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 String, ByVal location As String, ByVal fullPath As String, ByVal tag As String) As DirectoryItem |
Dim permissions As PathPermissions = Me.GetPermissions(fullPath) |
Dim flag As Boolean = IIf(IsListMode, True, Me.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 String) As 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 String, ByVal name As String) As 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 String) As 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 String) As 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.ReadOnly) Then |
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.
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.