Uploading Document to Document Set via Silverlight

Traitée Uploading Document to Document Set via Silverlight

  • jeudi 3 mai 2012 14:25
     
     

    Hello,

    My problem is as follows: I need to upload a document (word, excel, txt, etc) into a document set using Silverlight and C# client side code. I have managed to achieve this in VERY limited quantities using the Client OM. I will attach this code snippet below. I'm searching for a way to upload large files without the need for server side code. Regardless, what is the best way to achieve large file uploads? Furthermore, if I use some combination of Server side and Client side code how do I direct the document to the correct document set?

    Thank you in advance.

    My Client OM code:

                    Microsoft.SharePoint.Client.File uploadFile = docList.RootFolder.Files.Add(fileCreationInformation);
                    officeClientContext.Load(uploadFile);
                    officeClientContext.ExecuteQueryAsync(successfulUpload, failedUpload);


Toutes les réponses

  • jeudi 3 mai 2012 17:09
     
     
    Have you tried lists.asmx?  It's an OOB web service that you could use to upload content to SP.

    --Paul Galvin, Slalom
      Microsoft MVP - SharePoint
      Blogging @ http://www.mstechblogs.com/paul
      Twitter @ http://www.twitter.com/pagalvin

  • jeudi 3 mai 2012 19:54
     
     

    Paul,

    I tried to do so this afternoon, but it appears some of the classes I need to reference to utilize that service are beyond the scope of Silverlight's API.The example I followed used XMLDocument. In Silverlight I can use XDocument, but this functions in a drastically different manner.

    Charles

  • jeudi 3 mai 2012 20:28
     
     

    I think that it's pretty normal to work with SP and Silverlight via lists.asmx, but I just did a quick search and didn't exactly find a million functional examples.

    Here's something that might give you some ideas: http://www.rightpoint.com/community/blogs/viewpoint/archive/2011/09/01/using-silverlight-pivot-viewer-with-sharepoint-lists.aspx

    HTH,


    --Paul Galvin, Slalom
      Microsoft MVP - SharePoint
      Blogging @ http://www.mstechblogs.com/paul
      Twitter @ http://www.twitter.com/pagalvin

  • jeudi 3 mai 2012 20:41
     
     

    I'm not arguing that it's not normal/possible to facilitate the interaction of SharePoint and Silverlight through lists.asmx. I'm saying it's very difficult to facilitate file upload using Silverlight and the list.asmx service.

    I could be mistaken, I just haven't found a decent example of this variety of code.

  • jeudi 3 mai 2012 20:43
     
     
    Instead of using Client Object model you can also just emit a simple WebRequest (POST) with the blob file.... The browser will do the rest !

    Blog Sharepoint : www.paslatek.net Twitter : @LimozinLionel

  • jeudi 3 mai 2012 20:50
     
     
    Can a WebRequest handle larger data files? Would it provide reliable transfer from end to end?
  • jeudi 3 mai 2012 20:54
     
     

    Sorry!  I totally didn't mean to give the impression that it was easy.  The opposite :)  I did a search and expected to find lots of examples and I didn't find many at all.

    Once you figure it out, you should blog about it and get a bunch of internet money :)


    --Paul Galvin, Slalom
      Microsoft MVP - SharePoint
      Blogging @ http://www.mstechblogs.com/paul
      Twitter @ http://www.twitter.com/pagalvin

  • jeudi 3 mai 2012 20:58
     
     

    In my opinion yes, because it will be delegated to the browser.

    Today your issue is that the client object model is not aware of the big file size :(

    In fact the solution is that SharePoint support standard HTTP PUT

    so you need to search how you can create a file uploader with Silverlight (there is a lot of example if you remove "Sharepoint" from your search :) using multithreading, etc...) and then it must works for Sharepoint !


    Blog Sharepoint : www.paslatek.net Twitter : @LimozinLionel

  • vendredi 4 mai 2012 02:11
     
     Traitée A du code

    There is a 3mb upload limit using the client object model. Supposedly there is a powershell script to change this for the farm.

    http://msdn.microsoft.com/en-us/library/ff599489.aspx

    The following code can be used to upload a file to document set or folder.

    You should be able to convert this to use the Silverlight CSOM

       public static void UploadFile(string siteUrl,
                string listName,
                string contentTypeName,
                string targetFolder, string fileName)
    {
                ClientContext context = new ClientContext(siteUrl);
                Web web = context.Web;
                Folder folder = web.GetFolderByServerRelativeUrl(listName + "/" + targetFolder);
                
                context.ExecuteQuery();
                string documentUrl = "/" +listName + "/" + targetFolder + "/" + IO.Path.GetFileName(fileName);
                List list = context.Web.Lists.GetByTitle(listName);
                context.Load(list);
                ContentTypeCollection listContentTypes = list.ContentTypes;
                context.Load(listContentTypes, types => types.Include
                                                  (type => type.Id, type => type.Name,
                                                  type => type.Parent));
              
                var result = context.LoadQuery(listContentTypes.Where
                    (c => c.Name == contentTypeName));
                context.ExecuteQuery();
                bool checkOutRequired = list.ForceCheckout;
                try
                {
                    File existingFile = web.GetFileByServerRelativeUrl(documentUrl);
                    context.Load(existingFile);
                    context.ExecuteQuery();
                    existingFile.DeleteObject();
                    context.ExecuteQuery();
                }
                catch (Exception ex)
                {}
           
                ContentType targetContentType = result.FirstOrDefault();
                string contentTypeId = targetContentType.Id.ToString();
                FileCreationInformation fci = new FileCreationInformation();
                fci.Url = documentUrl;
                fci.Content = MasterHelper2010.GetByteArrayFromFile(fileName);
                fci.Overwrite = true;
               
                
                //get the folder's file collection
                FileCollection documentFiles = folder.Files;
                File newFile = documentFiles.Add(fci);
                
                
                //check out to make sure not to create multiple versions
                if(!list.ForceCheckout)
                    newFile.CheckOut();
                //start setting metadata here
                newFile.ListItemAllFields["ContentTypeId"] = contentTypeId;
                newFile.ListItemAllFields["Title"] = "whatever";
                newFile.ListItemAllFields.Update();
               
                context.Load(documentFiles);
                context.Load(newFile);    
                context.ExecuteQuery();
                //overwrite to make sure not to create multiple versions
                newFile.CheckIn(string.Empty, CheckinType.OverwriteCheckIn);
                context.Load(newFile);
                context.ExecuteQuery();
                 
            }


    Blog | SharePoint Field Notes Dev Tool | ClassMaster


  • vendredi 4 mai 2012 02:16
     
     Traitée A du code

    Ok here is the Silverlight version:

      public static void UploadFile(string siteUrl, string listName, string targetFolder, string fileName)
    {
                ClientContext context = new ClientContext(siteUrl);
                Web web = context.Web;
                Folder docSetFolder = web.GetFolderByServerRelativeUrl(listName + "/" + targetFolder);
                context.ExecuteQueryAsync((object eventSender, ClientRequestSucceededEventArgs eventArgs) =>
                {
                    string ret;
                    if (eventArgs.Request != null)
                        ret = eventArgs.Request.ToString();
                }, null);
                string documentUrl = "/" + listName + "/" + targetFolder + "/" + fileName;
                FileCreationInformation fci = new FileCreationInformation();
                fci.Url = documentUrl;
                fci.Content = new byte[] { }; //byte[] take your stream and convert to byte array
                
                //get the folder's file collection
                FileCollection documentFiles = docSetFolder.Files;
                context.Load(documentFiles);
                context.ExecuteQueryAsync((object eventSender, ClientRequestSucceededEventArgs eventArgs) =>
                {
                    string ret;
                    if (eventArgs.Request != null)
                        ret = eventArgs.Request.ToString();
                }, null);
                File newFile = documentFiles.Add(fci);
                
                context.Load(newFile);
                ListItem item = newFile.ListItemAllFields;
                context.ExecuteQueryAsync((object eventSender, ClientRequestSucceededEventArgs eventArgs) =>
                {
                    string ret;
                    if (eventArgs.Request != null)
                        ret = eventArgs.Request.ToString();
                }, null);
                //start setting metadata here
                item["Title"] = "myimage";
                item.Update();
                
                context.Load(item);
                context.ExecuteQueryAsync((object eventSender, ClientRequestSucceededEventArgs eventArgs) =>
                {
                    string ret;
                    if (eventArgs.Request != null)
                        ret = eventArgs.Request.ToString();
                }, null);
            
            
            }


    Blog | SharePoint Field Notes Dev Tool | ClassMaster

    • Marqué comme réponse Shimin Huang vendredi 11 mai 2012 07:49
    •  
  • lundi 7 mai 2012 12:31
     
     

    I attempted the above over the weekend. The context.ExecuteQueryAsync() calls were not completed before the code moved on...the items used in subsequent calls were then null whenever I attempted to use them. This whole Silverlight SP ordeal seems far overblown. Seems like there should be a quick and easy way to accomplish this as it would appear to be a fairly common task.

  • lundi 7 mai 2012 13:44
     
     Traitée A du code

    You are probably getting an error for some reason. Make sure to add an event hanlder to the ExecuteQueryAsync method for checking an error, like below.

     context.ExecuteQueryAsync((object eventSender, ClientRequestSucceededEventArgs eventArgs) =>
                {
    
                    string ret;
                    if (eventArgs.Request != null)
                        ret = eventArgs.Request.ToString();
    
                }, (object sender, ClientRequestFailedEventArgs eventArgs) =>
                {
                    string message = eventArgs.Message;
                });


    Blog | SharePoint Field Notes Dev Tool | ClassMaster

    • Marqué comme réponse Shimin Huang vendredi 11 mai 2012 07:49
    •  
  • lundi 7 mai 2012 13:48
     
     

    No, I am not getting an error. It is easy to see, but placing a break point inside the call, that my asynchronous call is being returned AFTER the UploadFile method is completed. I step through the method, line by line, checking each variable as I go. context, web, and docSetFolder all remain "null" for the duration of the method.

    After I have stepped out of the method, my breakpoints inside the async calls are hit.

  • lundi 7 mai 2012 15:09
     
     Traitée A du code

    Ok, sorry for the confusion. When using an Asychronous coding pattern and you have steps that need to execute in a particular order like we do here then you must insert every next sequential step into the success delegate. I revised the code from above to execute the next step after each successful previous step. This code is working in my environment. Hope this helps.

    public static void UploadFile(string siteUrl,
                string listName, string targetFolder, string fileName)
    {
    
                ClientContext context = new ClientContext(siteUrl);
                Web web = context.Web;
    
                Folder docSetFolder = web.GetFolderByServerRelativeUrl(listName + "/" + targetFolder);
    
                //STEP 1 GET FOLDER/DOCUMENTSET
                context.ExecuteQueryAsync((object eventSender, ClientRequestSucceededEventArgs eventArgs) =>
                {
                    string documentUrl = "/" + listName + "/" + targetFolder + "/" + fileName;
                    FileCreationInformation fci = new FileCreationInformation();
                    fci.Url = documentUrl;
                    fci.Content = new byte[] { }; //byte[] take your stream and convert to byte array
    
                    FileCollection documentFiles = docSetFolder.Files;
                    context.Load(documentFiles);
    
                    //STEP 2 ADD DOCUMENT
                    context.ExecuteQueryAsync((object eventSender2, ClientRequestSucceededEventArgs eventArgs2) =>
                    {
                        File newFile = documentFiles.Add(fci);
    
                        context.Load(newFile);
                        ListItem item = newFile.ListItemAllFields;
    
                        //STEP 3 SET METADATA
                        context.ExecuteQueryAsync((object eventSender3, ClientRequestSucceededEventArgs eventArgs3) =>
                        {
    
                            //start setting metadata here
                            item["Title"] = "myimage";
                            item.Update();
                            context.Load(item);
    
                            //STEP 4 UPDATE ITEM
                            context.ExecuteQueryAsync((object eventSender4, ClientRequestSucceededEventArgs eventArgs4) =>
                            {
    
                                string ret;
                                if (eventArgs.Request != null)
                                    ret = eventArgs.Request.ToString();
    
                            }, (object eventSender4, ClientRequestFailedEventArgs eventArgs4) =>
                            {
                                string message = eventArgs4.Message;
                            });
    
                        }, (object eventSender3, ClientRequestFailedEventArgs eventArgs3) =>
                        {
                            string message = eventArgs3.Message;
                        });
    
                    }, (object eventSender2, ClientRequestFailedEventArgs eventArgs2) =>
                    {
                        string message = eventArgs2.Message;
                    });
                   
    
                }, (object eventSender, ClientRequestFailedEventArgs eventArgs) =>
                {
                    string message = eventArgs.Message;
                });
       
    }


    Blog | SharePoint Field Notes Dev Tool | ClassMaster

    • Marqué comme réponse Shimin Huang vendredi 11 mai 2012 07:49
    •