none
Problem while trying to Upload a Document to a Folder inside a Doc Lib using Web service

    Question

  • Hi

    We are facing problem while trying to upload a File to a Folder inside a Doc Lib of MOSS portal site. We are using a .Net application to upload and the MOSS application is using Form based Authentication and is on remote server.

    Kindly provide us a way to upload the file, if the MOSS portal site is on Remote Server and using Form Based Authentication.

    We are using .Net C# code.

    Regards
    Nikhil

    Wednesday, June 03, 2009 4:51 AM

Answers

  • The easiest and most effecient way to upload a document into a particular folder in a document library is to use the Copy.asmx web service. I have attached a code example including code to set certain metadata including the "Modified By" field. Just make sure your destinationUrl is set to the url of the folder.

     public static void CreateNewDocumentWithCopyService(string fileName)
            {
                copyservice.Copy c = new copyservice.Copy();
                c.Url = "http://basesmcdev2/sites/tester1/_vti_bin/copy.asmx";
                c.UseDefaultCredentials = true;
    
                byte[] myBinary = File.ReadAllBytes(fileName);
                string destination = "http://basesmcdev2/sites/tester1/tester2/folderName/" + Path.GetFileName(fileName);
                string[] destinationUrl = { destination };
    
                copyservice.FieldInformation info1 = new copyservice.FieldInformation();
                info1.DisplayName = "Title";
                info1.InternalName = "Title";
                info1.Type = copyservice.FieldType.Text;
                info1.Value = "whateverForMe2";
    
                copyservice.FieldInformation info2 = new copyservice.FieldInformation();
                info2.DisplayName = "Modified By";
                info2.InternalName = "Editor";
                info2.Type = copyservice.FieldType.User;
                info2.Value = "-1;#BASESMCDEV2\\testmoss";
    
    
                copyservice.FieldInformation[] info = { info1, info2 };
                copyservice.CopyResult resultTest = new copyservice.CopyResult();
                copyservice.CopyResult[] result = { resultTest };
    
                try
                {
                    //You use same URL in the SourceURI as in the Destination URL
                    c.CopyIntoItems(destination, destinationUrl, info, myBinary, out result);
                }
                catch (Exception ex)
                {
    
                }
    
               
            }

    http://www.certdev.com
    Wednesday, June 03, 2009 3:20 PM
  • Ok, the copy web service will not overwrite an existing document if the sourceUrl arguement is the same as the destinationUrl. You can overwrite it if you set your sourceUrl to the file name or something different than the destinationUrl. So the code I had posted previously is really only good for creating new documents. If you want something that works even if the document already exists make sure the sourceUrl is anything but the destinatlionUrl. However, it cannot be an empty string because the code sets the _copySource property of the SPListItem with this value and it will throw an error if it is an empty string.

      try
      {
         //You use anything other than Destination URL
        c.CopyIntoItems(sourceUrl, destinationUrl, info, myBinary, out result);
      }
      catch (Exception ex)
      {
    
      }

    certdev.com
    • Marked as answer by Nikhil001 Sunday, June 21, 2009 11:30 AM
    Saturday, June 20, 2009 10:26 PM

All replies

  • The built in SharePoint webservices will work with FBA, you just have to do a few extra steps.  Check out these 2 links to see what I am talking about, basically you have to use an authentication.asmx webservice first, then you can use the other web services.

    Once your authenticated, you can i believe use the cookie that you get in your calls to other web services.

    To add files, I would suggest doing the above, then making a simple HTTP PUT request and putting the file up in to the library you want.  This will only put the file, not set the metadata and to do that you would then have to make a call to the lists.asmx and the updatelistitems method to set the metadata of the item you just added.  The lists.asmx DOES have an AddAttachment method but I find that the HTTP PUT is a bit easier and gets down to the barebones so you cna just put up a file and not have extra overhead.

    To add folders, etc. you can again use the authentication mechanism above and use the lists.asmx web service to add a folder to your list.  Here is an example of the xml you'd pass to the UpdateListItems method of the lists.asmx web service in order to add a folder :
    <Method ID='1' Cmd='New'><Field Name='FSObjType'>1</Field><Field Name='BaseName'>MyFolder</Field> 
    <Field Name='ID'>New</Field>
    </Method>



    Tony Testa www.tonytestasworld.com
    • Proposed as answer by Tony Testa2 Friday, June 05, 2009 12:49 AM
    • Marked as answer by Aaron Han - MSFT Friday, June 12, 2009 2:09 AM
    • Unmarked as answer by Nikhil001 Saturday, June 20, 2009 2:18 PM
    Wednesday, June 03, 2009 2:18 PM
  • The easiest and most effecient way to upload a document into a particular folder in a document library is to use the Copy.asmx web service. I have attached a code example including code to set certain metadata including the "Modified By" field. Just make sure your destinationUrl is set to the url of the folder.

     public static void CreateNewDocumentWithCopyService(string fileName)
            {
                copyservice.Copy c = new copyservice.Copy();
                c.Url = "http://basesmcdev2/sites/tester1/_vti_bin/copy.asmx";
                c.UseDefaultCredentials = true;
    
                byte[] myBinary = File.ReadAllBytes(fileName);
                string destination = "http://basesmcdev2/sites/tester1/tester2/folderName/" + Path.GetFileName(fileName);
                string[] destinationUrl = { destination };
    
                copyservice.FieldInformation info1 = new copyservice.FieldInformation();
                info1.DisplayName = "Title";
                info1.InternalName = "Title";
                info1.Type = copyservice.FieldType.Text;
                info1.Value = "whateverForMe2";
    
                copyservice.FieldInformation info2 = new copyservice.FieldInformation();
                info2.DisplayName = "Modified By";
                info2.InternalName = "Editor";
                info2.Type = copyservice.FieldType.User;
                info2.Value = "-1;#BASESMCDEV2\\testmoss";
    
    
                copyservice.FieldInformation[] info = { info1, info2 };
                copyservice.CopyResult resultTest = new copyservice.CopyResult();
                copyservice.CopyResult[] result = { resultTest };
    
                try
                {
                    //You use same URL in the SourceURI as in the Destination URL
                    c.CopyIntoItems(destination, destinationUrl, info, myBinary, out result);
                }
                catch (Exception ex)
                {
    
                }
    
               
            }

    http://www.certdev.com
    Wednesday, June 03, 2009 3:20 PM
  • I think its important to note in Steve's code sample above, it doesn't take into account FBA.  You'll have to authenticate first with FBA to be able to use the Copy.asmx web service, then call the copy web service.

    Another thing that I think is worth mentioning is that typically, if I have an FBA site, I make sure that I also have a NTLM "backdoor" extended site that I use for instances just like this.  I let all the users hit the FBA site, and then for custom code, services, integration, etc. I use the NTLM site to make things easier on myself and not have to jump through the hurdles of doing FBA authentication to use the web services.  Obviously if you don't have control of the environment, this isn't really an option, but if you do have control, I would suggest extending the web app and create an NTLM zone.

    Tony Testa www.tonytestasworld.com
    • Proposed as answer by Tony Testa2 Friday, June 05, 2009 12:49 AM
    Thursday, June 04, 2009 3:15 AM
  • thanks Tony
    Thursday, June 04, 2009 4:55 AM
  • Hi Steve

    I just used the same code , i am still facing issue: the code executes without error but there is no file copied in to the repective folder of the Doccument Library.

    thanks
    Nikhil
    Friday, June 05, 2009 6:56 AM
  • Can you paste in your modified code so we can see what might be going on?
    Tony Testa www.tonytestasworld.com
    Friday, June 05, 2009 1:09 PM
  • Hi Tony
     
    please  find the code below

            //Source file name



    filename = @"E:\Data\test.html"; copyservice.Copy c = new copyservice.Copy(); c.Url = "http://IP:PortNumber/sites/ABCSites/_vti_bin/copy.asmx"; c.UseDefaultCredentials = true; byte[] myBinary = File.ReadAllBytes(fileName); string destination = @"http://IP:PortNumber/sites/ABCSites/TempoSite/PRDocLib/Report X/" + Path.GetFileName(fileName); string[] destinationUrl = { destination }; copyservice.FieldInformation info1 = new copyservice.FieldInformation(); info1.DisplayName = "Title"; info1.InternalName = "Title"; info1.Type = copyservice.FieldType.Text; info1.Value = "whateverForMe2"; copyservice.FieldInformation info2 = new copyservice.FieldInformation(); info2.DisplayName = "Modified By"; info2.InternalName = "Editor"; info2.Type = copyservice.FieldType.User; info2.Value = "-1;#BASESMCDEV2\\testmoss"; copyservice.FieldInformation[] info = { info1, info2 }; copyservice.CopyResult resultTest = new copyservice.CopyResult(); copyservice.CopyResult[] result = { resultTest }; try { //You use same URL in the SourceURI as in the Destination URL c.CopyIntoItems(destination, destinationUrl, info, myBinary, out result); } catch (Exception ex) { Response.Write("Error:" + ex.Message.ToString()); }
    Kindly reply ,, we are not receiveing any error but the file is also uploaded in the Folder inside the Doc lib.

    Thanks
    Nikhil Choudhary
    Friday, June 05, 2009 1:56 PM
  • How are you checking for an error? Are you checking the result out argument? Does the CopyResult.ErrorCode = "Success"?


    certdev.com
    Friday, June 05, 2009 2:14 PM
  • Hi Steve

    please find the error details as under

    Dest URL: http://IP:PortNumber/sites/ABCSites/TempoSite/PRDocLib/Report X/test.html

    Error Code: Unknown

    Error Message: Object reference not set to an instance of an object.

    ToString Value: copyservice.CopyResult


    Kindly provide us the assitiance ,


    thanks
    Nikhil choudhary
    • Edited by Nikhil001 Friday, June 05, 2009 2:27 PM Updated URL
    Friday, June 05, 2009 2:26 PM
  • Does the "Report X" folder already exist? If it does not, then you will recieve "Object reference not set to an instance of an object" error. The copy web service does not support folder creation. It must exists before you upload content to it.
    certdev.com
    Friday, June 05, 2009 2:56 PM
  • Hi Steve

    the Folder named "Report X" is present ...


    kindly reply ...


    Nikhil
    Friday, June 05, 2009 3:07 PM
  • The only way I can reproduce the error is where there is something wrong with the destination url

    @"http://IP:PortNumber/sites/ABCSites/TempoSite/PRDocLib/Report X/

    Either the subsite, document library or folder do not exist or the credentials you are using do not allow access to either the subsite, document library or folder.
    certdev.com
    Friday, June 05, 2009 3:41 PM
  • Hi Steve


    The folder is present and i also tried accessing the URL by direct hitting in the browser

    The URL is working fine and Folder inside Doc Lib is opening

    Also i  update the Code by statment below

    c.Credentials =

    new NetworkCredential(sUserName, sPassword, sDomain);


    here i provided the Super Admin Credentials .

    still facing the same issue

    please help

    if you want i can paste the exact code here


    thanks
    Nikhil

    Friday, June 05, 2009 3:55 PM
  • Out of answers. However, you can try removing the following code since you probably do not have a user by the name of "basesmcdev2\testmoss

    copyservice.FieldInformation info2 = new copyservice.FieldInformation();
            info2.DisplayName = "Modified By";
            info2.InternalName = "Editor";
            info2.Type = copyservice.FieldType.User;
            info2.Value = "-1;#BASESMCDEV2\\testmoss";

    certdev.com
    Friday, June 05, 2009 3:58 PM


  • Hi

    I have added one more line

    c.PreAuthenticate =

    true;

    it started wokring now ....thanks a ton Steve for the prompt help

    Now i am testing for uploading more than 20 files ....will get back to you incase i get stuck..:)

    thanks
    Nikhil

    Friday, June 05, 2009 4:18 PM
  • I thought that your original question was how to access web services on an FBA site?  With the code your using now, is the web service your trying to hit using FBA?
    Tony Testa www.tonytestasworld.com
    • Marked as answer by Aaron Han - MSFT Friday, June 12, 2009 2:12 AM
    • Unmarked as answer by Nikhil001 Saturday, June 20, 2009 2:19 PM
    Friday, June 05, 2009 4:18 PM
  • Are you using an ISA firewall?
    certdev.com
    Friday, June 05, 2009 4:26 PM
  • Hi


    yes tony you are correct , we are using FBA, we extended the MOSS site and are able to use the web services.
    I have gone thriugh the code for Cookies and will be implementing in our application but due to dead line constrains i have extended the application to be in a hybrid form .

    Steve : I am not sure steve we are using ISA or not  but the the code worked when i passed Super admin and added the extra line of code .


    Thanks a lot ..

    Nikhil
    Friday, June 05, 2009 5:11 PM
  • Hi Steve/Tony ...

    The code is working fine if the file does not exists in the Dco Lib but when the file already exists we are unable to upload the
    file [Overwriting] to the document library.

    The error code retrun is as below

    Error Code: DestinationInvalid

    Can you suggest us some property where in we can use overwriting feature thru the same above code mention.

    waiting
    thanks
    Nikhil
    Friday, June 19, 2009 10:36 AM
  • The code posted I have tested and it will overwrite an existing document without any problems. Is the document library you are posting to a "Record Center" library?
    certdev.com
    Friday, June 19, 2009 1:36 PM
  • Hi

    It is a List of type Document Library where in we are trying to upload the files .Also when we created the Doc Lib we used

    the option "Yes"  for the " Create a version each time you edit a file in this document library?" - Yes [selected]

    When we try to upload the code fails if the file already exists in the Doc lib and Output returned is
    'Error Code: DestinationInvalid '


    Although while creating the Document Lib if we select "No" for the version the code works fine and overwrites.

    How can we overwrite and keep versions ?

    Can you please try to upload a HTML file with same name and try to change the content at the second time you are executing the code. also verify the time stamp in the Doc lib for both times of upload.


    waiting for reply !!!

    Thanks
    Nikhil
    • Edited by Nikhil001 Saturday, June 20, 2009 10:19 AM
    Friday, June 19, 2009 2:03 PM
  • Hi Steve

    We are still unable to  copy the existing file , do you have any suggestion for us ..

    waiting
    thanks
    Nikhil
    Saturday, June 20, 2009 9:17 AM
  • Hi Steve

    Kindly provide us a way out for the issue

    thanks
    Nikhil
    Saturday, June 20, 2009 2:19 PM
  • In the past I've run into errors if the document is checked out and I try to overwrite it.  Try making sure that the document is checked in, then try and overwrite it and see if it works  If it does work, that means you'll need to make sure the documents are checked in first, then upload them..which can be done with the lists.asmx

    Let me know if checking in the document makes a difference or not
    Tony Testa www.tonytestasworld.com
    Saturday, June 20, 2009 5:59 PM
  • Ok, the copy web service will not overwrite an existing document if the sourceUrl arguement is the same as the destinationUrl. You can overwrite it if you set your sourceUrl to the file name or something different than the destinationUrl. So the code I had posted previously is really only good for creating new documents. If you want something that works even if the document already exists make sure the sourceUrl is anything but the destinatlionUrl. However, it cannot be an empty string because the code sets the _copySource property of the SPListItem with this value and it will throw an error if it is an empty string.

      try
      {
         //You use anything other than Destination URL
        c.CopyIntoItems(sourceUrl, destinationUrl, info, myBinary, out result);
      }
      catch (Exception ex)
      {
    
      }

    certdev.com
    • Marked as answer by Nikhil001 Sunday, June 21, 2009 11:30 AM
    Saturday, June 20, 2009 10:26 PM
  • Hi Steve

    Yes, you are correct the code is working fine now after changing the Source and Dest URls.

    Earlier both were same. We are also able to keep the versions now .


    thanks a lot for the added help


    thanks
    Nikhil
    Sunday, June 21, 2009 11:31 AM