In the first part I showed the implementation of the backup logic, the second part was about integration with the a Custom File Content Provider and in the third part I showed the implementation of the server events.
You remember:
- Backup functionality (make copies of deleted / overwritten files) (DONE)
- Copy files with drag and drop (the control does a move for this) (DONE)
- Protect files from being deleted (DONE)
- Add server side events when a file / directory is selected (the control is almost pure client Ajax) (DONE)
So everything done?
No backup implies restore – and that’s the thing this post is about.
My design allows the user to restore multiple versions of a document in a specific folder.
When the users selects a folder I have to display a list of backup files for this folder.
The easiest way for me was to use a DataGrid. I used the telerik RadGrid for ASP.NET AJAX but this does not really matter.
The integrate grid would have done the same job – I use none of the extended features from this control (except “auto Ajax” and one special funtion).
Let me first show you how this looks on a folder where I have some deleted files.
There we have two version of aXFEStyles.css and one version of BLogin.png.
Just to remember the functionality here is how the backup folder looks.
You see there are other files from different folders which are not displayed in the grid.
The restore is very simple – I just call a method of the “BackupEntry” class.
//handle restore and delete from grid
protected void rgBackupFiles_ItemCommand(object source, Telerik.Web.UI.GridCommandEventArgs e) {
if (e.CommandName.ToUpper() == "RESTOREFILE" || e.CommandName.ToUpper() == "DODELETE") {
List<BackupEntry> bEL = Session["FileList"] as List<BackupEntry>;
if (bEL == null) {
//do not create a new file list here - files could have been changed!!
rgBackupFiles.Rebind();
return;
}
//get index of entry
int nIDX = (int)e.Item.OwnerTableView.DataKeyValues[e.Item.ItemIndex]["IDX"];
//retrieve object
BackupEntry bE = bEL[nIDX];
if (e.CommandName.ToUpper() == "RESTOREFILE") {
bE.RestoreFile();
//force grid to fire a refresh on FileExplorer
rgBackupFiles.ClientSettings.ClientEvents.OnGridCreated = "RefreshAfterFileRestore";
return;
}
bE.RemoveBackup(); //only delete left
//file list has changed - rebind
rgBackupFiles.Rebind(); //files have changed!!
return;
}
}
This is the handler for the grid. First I check if the command is one of these I’m handling.
Then I grab the object for the selected item – and if it is a restore I call restore – else I call delete.
public bool RestoreFile() {
try {
string strDestPath = HttpContext.Current.Server.MapPath(FullURL);
File.Copy(BackupFilePath, strDestPath, true);
return (true);
}
catch {
return (false);
}
}
/// <summary>
/// removes a file from the backup
/// </summary>
/// <returns></returns>
public bool RemoveBackup() {
try {
File.Delete(BackupFilePath);
return (true);
}
catch {
return (false);
}
}
These two methods must no be explained I guess :)
But what’s with this strange code line in the restore section?
if (e.CommandName.ToUpper() == "RESTOREFILE") {
bE.RestoreFile();
//force grid to fire a refresh on FileExplorer
rgBackupFiles.ClientSettings.ClientEvents.OnGridCreated = "RefreshAfterFileRestore";
return;
}
Looks strange? It is strange :)
Let me first explain the facts – I restore a file. This means that the content of the telerik RadFileExplorer has to be refreshed.
BUT – this control is pure Ajax – so it has no method to refresh a specific folder.
Of course I could do a full refresh of the page – but that is not what ajaxified means.
The telerik RadGrid for ASP.NET AJAX has an event which is fired when the grid is “created” (refilled with data) on the client.
And a attach a handler to this event in the case of a restore.
Now back to the JScript and the two functions which I did not explain in my last post.
<script language="javascript" type="text/javascript">
//<![CDATA[
var bIsRefreshing = false;
function RefreshAfterFileRestore(sender, args) {
setTimeout("TimerEnd()", 600); //used to avoid request while other request is still in progress
}
function TimerEnd() {
bIsRefreshing = true; //block double refreshes
var fX = $find("<%= rfxFiles.ClientID %>");
fX.refresh(fX.get_currentDirectory());
}
function OnFolderLoaded(sender, args) {
if (bIsRefreshing) { //avoid refresh when initiated from a refresh
bIsRefreshing = false;
return;
}
The first function (RefreshAfter…) it the one I attached to the GridCreated event. It set’s a timer – nothing more.
I do this because at the very moment I’m inside an Ajax call. – And what I have to do fires an other Ajax call.
So I simply wait a bit – and the TimerEnd does it’s job – it set’s a “lock” to prevent reentrance and calls a function of the FileExplorer.
This function refreshes the currently selected directory. This means it loads the folder.
And of course this ends in a “OnFolderLoaded” event – which has exactly the same data than before.
So there is no need to fire extra events for this.
By the way – it also selects the previously selected file if one was selected.
That’s it. Finally a screenshot of the example page
But wait – there are some things left out – I did some “tricks” – I did not show how to set the “defaults” and I did not tell where to get the complete example including source files.
I’ll do this in the next – and last post to this topic.