In the first part I showed the implementation of the backup logic.
This step I will show how the telerik RadFileExplorer is used to achieve what I need.
You remember:
- Backup functionality (make copies of deleted / overwritten files)
- Copy files with drag and drop (the control does a move for this)
- Protect files from being deleted
- Add server side events when a file / directory is selected (the control is almost pure client Ajax)
The first step is to provide backup functionality.
The control provides a Custom File Content Provider which allows to hook the functionality at file level.
So I derived a class from this provider and overloaded the functions I need.
I also added properties like “BakupEnabled” and “BackupPath”.
As an example (there are more of course) I handled the “DeleteFile” event like this:
Snippet created with CBEnhancer public override string DeleteFile(
string path) {
if (m_lProtectedFiles.Contains(path,
StringComparer.InvariantCultureIgnoreCase)) {
return (
"File is protected and can't be deleted!");
}
string strDidBackup =
"NO";
if(BackupEnabled && !
string.IsNullOrEmpty(m_strBackupPath)) {
//backup seems to be possible strDidBackup= TryToBackup(path);
if (strDidBackup!=
string.Empty) {
return (
"File not deleted because of backup error: " + strDidBackup);
}
}
string strRet =
base.DeleteFile(path);
if (strRet !=
string.Empty && strDidBackup !=
"NO") {
//failed to delete - undo backup UndoLastBackup();
}
return (strRet);
}
The first thing to notice here is the base function. It deletes the file – and if an error occurs it returns the error message as string.
The control then displays this error message via alert.
Since communication is done via strings I do the same. If the flag “BackupEnabled” is set and if there is also a valid backup path I try to backup the file.
This can fail due to many reasons – if it fails – I report the error and return – no delete happens.
If it works – the content of strDidBackup changes from NO to string.Empty.
Next (or first if backup was disabled) I call the base class to delete the file.
This can also fail – if it fail I undo my backup.
Simple and easy – as the code to backup the file:
private string TryToBackup(string path) {
m_strLastBackupSource = null; //use these strings to enable an undo later
m_strLastBackupDestination = null;
m_strLastBackupSource = HttpContext.Current.Server.MapPath(path);
if (!File.Exists(m_strLastBackupSource)) {
return ("File not found");
}
string strBackupName = BackupEntry.EncodeFileURL(path);
if (strBackupName == null) {
return ("Could not encode filename");
}
m_strLastBackupDestination = Path.Combine(m_strBackupPath, strBackupName);
try {
File.Copy(m_strLastBackupSource, m_strLastBackupDestination);
return (string.Empty);
}
catch (Exception eX) {
return (eX.Message);
}
}
Remember the paths – check for existence of the file – and finally try to copy it.
Since this is done (in the same kind for other functions) point one was finished – and the next step is was to implement the “File Protect” functionality.
This was also not to hard – I simply added a list of the protected files and change the DelteFile method to this:
public override string DeleteFile(string path) {
if (m_lProtectedFiles.Contains(path, StringComparer.InvariantCultureIgnoreCase)) {
return ("File is protected and can't be deleted!");
}
string strDidBackup = "NO";
if(BackupEnabled && !string.IsNullOrEmpty(m_strBackupPath)) { //and so on…..
Since Windows is not case sensitive at the file system I compare the thing case insensitive.
If the list contains a protected file I simply return with an “Error message”. Now about the parameters – how to pass them to the file system provider?
We have an Ajax control which creates the file system provider when needed. So the idea to pass in the settings via constructor is not possible – the telerik RadFileExplorer calls the constructor and
not my usercontrol.
But the settings are done via parameters to my usercontrol. Of course there could be a way to handle the things "somewhere in a page event” where everything meets – but I decided to go a simple way.
I created a helper class which holds the settings – instantiated it in PageLoad and stored it in a Session variable.
XManagerSettings xSettings = Session["MGSettings"] as XManagerSettings;
if (xSettings == null) {
xSettings = new XManagerSettings();
Session["MGSettings"] = xSettings;
TryToSetManagerSettings();
}
So now I have my settings in a session variable – and “TryToSetManagerSettings” simply tries to transfer the usercontrol properties to the manager Settings. This is also done when a property is changed – therefore the try in the function name :)
Snippet created with CBEnhancer
/// <summary>
/// tries to transfer the current settings to the manager (if one is bound)
/// </summary>
private void TryToSetManagerSettings() {
XManagerSettings xSettings = Session[
"MGSettings"]
as XManagerSettings;
if (xSettings !=
null) {
xSettings.BackupURL = m_strBackupURL;
xSettings.ProtectedFiles = m_strProtectedFiles;
if (!
string.IsNullOrEmpty(m_strDoCopy)) {
if (m_strDoCopy.ToUpper() ==
"TRUE" || m_strDoCopy ==
"1") {
xSettings.DoCopy =
true;
}
else if (m_strDoCopy.ToUpper() ==
"FALSE" || m_strDoCopy ==
"0") {
xSettings.DoCopy =
false;
}
}
if (!
string.IsNullOrEmpty(m_strBackupEnabled)) {
if (m_strBackupEnabled.ToUpper() ==
"TRUE" || m_strBackupEnabled ==
"1") {
xSettings.BackupEnabled =
true;
}
else if (m_strBackupEnabled.ToUpper() ==
"FALSE" || m_strBackupEnabled ==
"0") {
xSettings.BackupEnabled =
false;
}
}
}
}
The interesting part in this function the handling of the “boolean” properties. The reason for the False (0) checks is that I also provide settings via web.config. The settings on the usercontrol override them – but if there are none I avoid to set something.
When the telerik RadFileExplorer instantiates the File Content Provider I can access those settings in the constructor.
Snippet created with CBEnhancer
public MyFileSystemProvider(
HttpContext hContext,
string[] searchPatterns,
string[] viewPaths,
string[] uploadPaths,
string[] deletePaths,
string selectedURL,
string selectedTag) :
base(hContext, searchPatterns, viewPaths, uploadPaths, deletePaths, selectedURL, selectedTag) {
//take defaults from web.config
m_bDoCopy = m_bDefaultDoCopy;
BackupURL = m_strDefaultBackupURL;
BackupEnabled = m_bDefaultBackupEnabled;
m_lProtectedFiles =
new List<
string>();
XManagerSettings xSettings = hContext.Session[
"MGSettings"]
as XManagerSettings;
if (xSettings !=
null) {
xSettings.FSProvider =
this;
//assume it will set DoCopy, BackupEnabled, protectedFiles and BackupURL with this call if needed
}
}
The final “trick” is done with xSettings.FSProvider=this – this enables the settings class to set values in the File Content Provider.
Although this approach may look a bit dirty – it save me a lot of time messing around with timings (what is instantiated when).
Conclusion – my usercontrol gets the settings. These settings are transferred to a settings class.
This settings class is passed to FileSystemProvider – and the FSP “registers” itself with the settings.
So the settings act as a “man in the middle” – which is useful in cases where the telerik RadFileExplorer is hosted in a page or somewhere else instead of in a usercontrol.
The last thing here is to implement the “copy instead of move”. Also a simple thing:
public override string MoveFile(string path, string newPath) {
if (m_lProtectedFiles.Contains(path, StringComparer.InvariantCultureIgnoreCase) &&
!DoCopy) { //allow move if it is a copy
return ("File is protected and can't be moved!");
}
string strRet = base.MoveFile(path, newPath);
if (!DoCopy || strRet != string.Empty){//no need to copy - or error in MoveFile run away :)
return strRet;
}
//copy the file back to the original location
string strSource=HttpContext.Current.Server.MapPath(path);
string strDestination=HttpContext.Current.Server.MapPath(newPath);
File.Copy(strDestination, strSource);
return strRet;
}
This function does first check (protect files) if we will copy and if the file is protected.
A protected file must only be moved if copy is active.
Next we let the original handler do it’s work – and if Copy is set we simply copy the file back to it’s original location.
So there is only one point left – Events for the control. I’ll describe this in the next section.