Ketone Cops

July 31, 2008

Using the Clipboard to copy and paste files in ASP.NET

Filed under: ASP.NET 2.0,programming — delroger @ 9:27 pm

Before I start, I must admit I’m not entirely convinced this is a particularly useful thing to try and do, since you can accomplish the same results using System.IO and the various File methods, but anyway…

I guess I was trying to see if this was possible or not in a webpage, rather than in a Windows form – to copy a file (or files) to the server clipboard and then paste them in another location. So here’s how it’s done:

Let’s assume you have a Gridview where you have a list of files that the user can access, and they want to move them from one directory to another. They can tick a checkbox in each gridview row for the file, then click a button to ‘Copy Files’ and another button to ‘Paste Files’ to another directory.

In the code-behind, we have a Property set up called ClipboardFiles which uses a string array as its value, like this:

Property ClipboardFiles() As String()
        Get
            Dim o As Object = ViewState(“ClipboardFiles”)
            If o Is Nothing Then
                Return Nothing
            Else
                Return o
            End If
        End Get
        Set(ByVal value As String())
            ViewState(“ClipboardFiles”) = value
        End Set
    End Property

Now when the user clicks the button to Copy Files, all selected files are added to ClipboardFiles. Of course there are lots of ways you might get the names and paths of the files; in this case, I had a function that was returning an ArrayList (named ‘al’ here) of the complete path and name of the files. I then cast the ArrayList to a string array and set the ClipboardFiles property like this:

Dim strFiles As String() = CType(al.ToArray(GetType(String)), String()) 
ClipboardFiles = strFiles

Here’s the tricky bit: when the user clicks the button to Paste Files, we have to use Threading and set the Apartment State of the thread. There is a sub called PasteFiles, which we will reference in the button click, like this:

(note: needs Imports System.Threading)

Protected Sub imgPasteFile_Click(ByVal sender As Object, ByVal e As System.Web.UI.ImageClickEventArgs) Handles imgPasteFile.Click
        Dim pasteThread As Thread = New Thread(New ThreadStart(AddressOf PasteFiles))
        pasteThread.SetApartmentState(Threading.ApartmentState.STA)
        pasteThread.Start()
        pasteThread.Join()
    End Sub

Finally, the PasteFiles sub looks like the code below. It copies the files listed in the ClipboardFiles to the Clipboard, then pastes them in a location of your choice (in this case ‘C:\Temp’, but you’d almost certainly set this programmatically).

(note: needs Imports System.Windows.Forms)

Private Sub PasteFiles()
        ‘copy files to clipboard
        If Not ClipboardFiles Is Nothing Then
            Try
                Clipboard.SetDataObject(New DataObject(DataFormats.FileDrop, ClipboardFiles))
            Catch ex As Exception
                ‘your error handler
                Exit Sub
            End Try
        End If

        ‘paste to new location
        Try
            Dim iData As IDataObject = Clipboard.GetDataObject()
            If iData.GetDataPresent(DataFormats.FileDrop) Then
                Dim clipbrd As String() = DirectCast(iData.GetData(DataFormats.FileDrop), String())
                For Each strFile As String In clipbrd
                    System.IO.File.Copy(strFile, “C:\Temp\” & System.IO.Path.GetFileName(strFile))
                Next
            End If
        Catch ex As Exception
            ‘your error handler
        End Try
       
    End Sub

This code was put together from a few snippets I found here and there, including this:

http://www.telerik.com/community/forums/thread/b311D-dcdga.aspx

and this:

http://bytes.com/forum/thread356140.html

Like I said, I’m not entirely sure how useful it really is, but it may give someone an idea about how to accomplish something similar using the Clipboard functionality. If so, glad to have helped…

Advertisements

July 30, 2008

Postback occurring after Cancel clicked

Filed under: ASP.NET 2.0,Javascript,programming — delroger @ 10:06 pm

It’s quite common to use a Javascript function when you want a website user to confirm that they want to delete a file (for instance) or a database record. In ASP.NET, you would add code to OnClientClick for a button (for example), along the lines of:

return confirm(‘Are you sure?’);

This can also be done in the code-behind under Page_Load or Page_PreRender as buttonname.Attributes.Add(“onclick”,”return confirm(‘Are you sure?’)”)

Similarly, you can also call a javascript function that does much the same thing, such as:

function confirm_delete()
    {
        if (confirm(“Are you sure?”)==true)
            return true;
        else
            return false;
    }

…and use:

 return confirm_delete(); 

for the onclick/onclientclick.

This would appear in the actual webpage as an OnClick event for the button. When the button is clicked, the user would see a javascript confirm window, with ‘Are you sure?’ and an OK and a Cancel button. Clicking OK would continue to process any code for the button; clicking Cancel would stop further processing.

It’s also common to find a lot of people have problems with this not working, and in the majority of cases it is because a javascript function is called that returns true or false, but the ‘return’ is missing. Using the example above, if you simply said

confirm(‘Are you sure?’); or confirm_delete();

without the ‘return’, the page would still postback, whatever had been clicked.

Today, I found that even with the ‘return’, postback was still occurring on a webpage I had created; in this case, a file delete still took place even when I clicked the ‘Cancel’ button and a value of false was being returned. 

So, just in case anyone else finds the same thing, this may well be a bug in Internet Explorer 7 (though I have not yet had chance to check this). The solution is to add some extra code to the return confirm, like this:

if (confirm(‘Are you sure?’) == false) {event.returnValue=false; return false; }else{ return true;};

It seems as though we have to specifically set the event.returnValue to be false to prevent further processing and postback.  This took me a few hours to work out, so hopefully this solution may save someone from wasting a similar amount of time, because it doesn’t seem to be very well documented so far.  And if it does help you, please leave a message and say ‘hi’!

July 7, 2008

Referencing page from Class file in App_Code

Filed under: ASP.NET 2.0,programming — delroger @ 1:02 pm

If you need to reference the Page control from a Class file (for instance, for adding a ClientScript) without passing the Page instance as a parameter to a Function or Sub, you can use the following: 

Dim pg As Page = HttpContext.Current.Handler 

You can then use this instance just as you would in the code-behind of the page itself.

For instance, I use this code to create Javascript alerts on my webpages:

Public Shared Sub CreateMessageAlert(ByRef clientScript As System.Web.UI.ClientScriptManager, ByVal strMessage As String, ByVal strKey As String)
 Dim context As HttpContext = HttpContext.Current
 Dim strScript As String = “”
 If (Not clientScript.IsStartupScriptRegistered(strKey)) Then
clientScript.RegisterStartupScript(context.GetType(), strKey, strScript)
 End If
End Sub

(This code was based on some found elsewhere – apologies for not referencing exactly where, since there are a few examples floating around and I don’t remember where I first saw it!)

From a Class file in the App_Code folder, this could then be called like so:

Dim newGuid As Guid = Guid.NewGuid()
Dim pg As Page = HttpContext.Current.Handler
CreateMessageAlert(pg.ClientScript, “Your message here”, newGuid.ToString())

Button event firing twice in ASP.NET

Filed under: ASP.NET 2.0,programming — delroger @ 12:42 pm

I’d got a File Upload control on one of my webpages which was causing a strange problem: when a user clicked the button to upload a file, the button’s click event was firing twice, so the file uploaded twice and a database insert query happened twice.

I’d initially thought that the Page_Load event was occurring twice, since this is quite well documented if, for instance, you have <img src=”#”>.  Debugging the code demonstrated that this was not happening; the Page_Load only fired once, while the btnUpload_Click fired twice.

The problem turned out to be that the code for my button was as follows:

<asp:Button ID=”btnUpload” runat=”server” OnClick=”btnUpload_Click” Text=”Upload File” />

 There are essentially two events for the button: both runat=”server” and OnClick fire the same event, hence everything happening twice.  The solution is simply to remove the OnClick command. 

But why was this happening in the first place? I think it is because I originally had an AJAX UpdatePanel on the page and the control had been part of that initially: the OnClick was created when the File Upload control was dragged into the UpdatePanel; after removing the UpdatePanel, the OnClick still remained.

Blog at WordPress.com.