The SharePoint Copy Service, DotNetNuke, and VB Haters

It seems like everything I work on these days is new technology and I guess there’s not a lot of love out there for VB.Net programmers.  I spend a lot of time looking for code and it’s always in C# which I have to convert and the converters don’t always get it right.  I know I’m not alone in this based on the number of updates a day I have to download to keep my third party software up to date.

So, my VB.Net brothers and sisters, if you’ve been trying to get a handle on uploading a document from your local machine through DotNetNuke to SharePoint using the SharePoint Copy Web Service, well, this is your lucky post.

Recently, I had to build an interface in DotNetNuke to upload files and save them in the SharePoint environment.  To accomplish this we used the Users and Roles from DotNetNuke, an authorization cookie, and the SharePoint Copy Service.  I was able to cobble together code from demo sites, but it was all in C#.  I’ve done the conversion to VB.Net for you.  Enjoy!

Prerequisites:

You’ve already built, or know how to build, a custom module and put the File Upload control on the page.

You’ve already set up your SharePoint site to use DotNetNuke security and Forms authentication.

For the sake of this project add the following controls to your page:

1. FileUpload; ID=fUpload
2. Button; ID=btnUpload, Text=”Upload”
3. Label; ID=lblErr

Part 1: Add the Web Service and Authentication Service

The services should be added as a Web References (not a References, or a Service References)

The authenication service will be located at http://{your SharePoint domain}//_vti_bin/Authentication.asmx.  When naming the service use your own naming conventions, but for this demo it’s called “AuthSvc”.  See the AuthenticateFBASite function in step 4.

The copy service will be located at http://{your SharePoint domain}//_vti_bin/Copy.asmx.  When naming the service use your own naming conventions, but for this demo it’s called “CopySvc”.  See the UploadService function in step 5.

Part 2: Upload the File to the Web Server

You don’t simply upload the file directly to SharePoint.  The file needs to be saved to the Web Server and then sent to SharePoint.

Create a dump folder, save the file from the Upload control to the dump folder.

Dim mErr as string = "" 'rudimentary error trapping

Function UploadDocument() as Boolean
    'Gather the username and password from DotNetNuke    
    Dim UserName = UserInfo.Username
    Dim objUser As MembershipUser
    objUser = Membership.GetUser(UserInfo.Username)
    Password = objUser.GetPassword()

    'Set up the document variables    
    Dim fDocName As String = ""
    Dim fDocExt As String = ""
    Dim fsourceURL As String = ""
    Dim fdumpFolder as string = "http://webdomain/subfolder/" 'DotNetNuke Domain

    'Share Point Folder Path
    Dim fFolderPath as string = "/YourSharePointLibraryName/SubFolder/

    Try    
        If fUpload.HasFile Then
            fDocName = System.IO.Path.GetFileNameWithoutExtension(fUpload.FileName).ToString
            fDocExt = System.IO.Path.GetExtension(fUpload.FileName).ToString
            fsourceURL = Server.MapPath(fdumpFolder & fDocName & fDocExt)
            fUpload.SaveAs(sourceURL)

            'Upload to SharePoint Code Goes Here
            If Not UploadToSharePoint({SharePoint Domain}, UserName, Password, fsourceURL, fFolderPath & "/" & fDocName & fDocExt) Then
                Throw New Exception(mErr)   
            Else
                'Successful move to SharePoint.  Delete temp file
                If System.IO.File.Exists(sourceURL) Then System.IO.File.Delete(sourceURL)
            End If
        End If
    Catch ex as Exception
        'report the error to your page
    End Try
End Function

3. Establish Authentication and Call the SharePoint Upload Service

Public Function UploadToSharePoint(siteURL As String, UserName As String, Password As String, docSourceURL As String, docDestinationFolder As String) As Boolean
    Try
        ' Call Auth Service And Get Cookie to autheticate
        Dim myAuthCookie As Cookie
        Dim myNetworkCredentials As New NetworkCredential()
        myAuthCookie = AuthenticateFBASite(siteURL, UserName, Password, myNetworkCredentials)

        ' Use Auth Cookie to call List Service
        Dim myCopySvcResponse As Boolean
        myCopySvcResponse = UploadService(myAuthCookie, docSourceURL, {siteURL & docDestinationFolder}) 

        If myCopySvcResponse > 0 Then Throw New Exception(ControllerError)

        Return True
   Catch ex As Exception
       mErr = "Upload Document error: " & ex.Message
       Return False
   End Try
End Function

4. Authentication

Private Function AuthenticateFBASite(AuthenticationSiteURL As String, UserName As String, Password As String, Credential As NetworkCredential) As Cookie
    Dim CurrentSiteCookie As Cookie = Nothing

    Using authSvc As New AuthSvc.Authentication()
    authSvc.Url = AuthenticationSiteURL + "/_vti_bin/authentication.asmx"

    'Create A New Cookie Container
    authSvc.CookieContainer = New System.Net.CookieContainer()

    ' Set the FBA Login Information
    authSvc.AllowAutoRedirect = True
    authSvc.PreAuthenticate = True
    authSvc.Credentials = Credential

    Dim result As AuthSvc.LoginResult
    result = authSvc.Login(UserName, Password)

    If result.ErrorCode = Pierson.SharePoint.AuthSvc.LoginErrorCode.NoError Then
        Try
            Dim cookies As New CookieCollection()
            cookies = authSvc.CookieContainer.GetCookies(New Uri(AuthenticationSiteURL))

            CurrentSiteCookie = cookies(result.CookieName)

            Return CurrentSiteCookie
        Catch ex As Exception
            Return CurrentSiteCookie
        End Try
    ElseIf result.ErrorCode = SharePoint.AuthSvc.LoginErrorCode.PasswordNotMatch Then
        Return CurrentSiteCookie
    Else
        Return CurrentSiteCookie
    End If
    End Using
End Function

5. Upload to SharePoint

Public Function UploadService(ByVal Cookie As Cookie, copySource As String, copyDest As String(), fileError As String) As Int32 ', fileBytes As Byte(), destinationMapPath As String
    Try
        Dim fErr As String = ""
        Dim fDocName As String = ""  'no extension
        Dim fDocExt As String = ""

        'Create Instance Of Lit Service
        Dim myCopyService As New CopySvc.Copy()

        'Create Cookie Container
        myCopyService.CookieContainer = New CookieContainer()

        ' Add Authentication Cookie to Container
        myCopyService.CookieContainer.Add(Cookie)

        Dim FirstResult As CopySvc.CopyResult = New CopySvc.CopyResult()
        Dim SecondResult As CopySvc.CopyResult = New CopySvc.CopyResult()
        Dim copyResultArray As CopySvc.CopyResult() = {FirstResult, SecondResult}
        Dim fieldInfo As CopySvc.FieldInformation = New CopySvc.FieldInformation()

        fieldInfo.DisplayName = "Description"
        fieldInfo.Type = CopySvc.FieldType.Text
        fieldInfo.Value = copySource
        Dim fieldInfoArray As CopySvc.FieldInformation() = {fieldInfo}

        Dim objStream As FileStream = New FileStream(copySource, FileMode.Open, FileAccess.Read)
        Dim Contents As Byte() = New [Byte](objStream.Length - 1) {}
        Dim r As Byte() = New [Byte](objStream.Length - 1) {}
        Dim Read As Integer = objStream.Read(Contents, 0, Convert.ToInt32(objStream.Length))

        Dim copyresult As UInteger = myCopyService.CopyIntoItems(copySource, copyDest, fieldInfoArray, Contents, copyResultArray)

        Return copyresult
    Catch ex As Exception
        mErr = "Upload Service error: " & ex.Message
        Return False
    End Try
End Function

That should get you most of the way there.  If you find a bug, drop me a line in the comments.

2 comments for “The SharePoint Copy Service, DotNetNuke, and VB Haters

Leave a Reply

Your email address will not be published. Required fields are marked *