2010-06-03 5 views
13

J'ai une liste SharePoint à laquelle j'ajoute de nouveaux éléments ListItems en utilisant le modèle objet client. Ajouter ListItems n'est pas un problème et fonctionne très bien.SharePoint 2010 - Modèle objet client - Ajouter une pièce jointe à ListItem

Maintenant, je veux ajouter des pièces jointes.

J'utilise le SaveBinaryDirect de la manière suivante:

File.SaveBinaryDirect(clientCtx, url.AbsolutePath + "/Attachments/31/" + fileName, inputStream, true); 

Il fonctionne sans aucun problème tant que l'élément que je suis en train d'ajouter la pièce jointe, a déjà une pièce jointe qui a été ajouté via le site SharePoint et n'utilisant pas le modèle d'objet client.

Lorsque je tente d'ajouter une pièce jointe à un élément qui ne marche pas avoir toutes les pièces jointes encore, je reçois les erreurs suivantes (les deux se passent, mais pas avec les mêmes fichiers - mais ces deux messages apparaissent toujours):

The remote server returned an error: (409) Conflict
The remote server returned an error: (404) Not Found

Je me suis dit que je devais peut-être d'abord créer le dossier des pièces jointes pour cet article. Lorsque je tente le code suivant:

clientCtx.Load(ticketList.RootFolder.Folders); 
clientCtx.ExecuteQuery(); 
clientCtx.Load(ticketList.RootFolder.Folders[1]);    // 1 -> Attachment folder 
clientCtx.Load(ticketList.RootFolder.Folders[1].Folders); 
clientCtx.ExecuteQuery(); 
Folder folder = ticketList.RootFolder.Folders[1].Folders.Add("33"); 
clientCtx.ExecuteQuery(); 

Je reçois un message d'erreur indiquant:

Cannot create folder "Lists/Ticket System/Attachment/33"

Je possède des droits d'administrateur complets sur le site SharePoint/liste.

Des idées sur ce que je pourrais faire de mal?

Merci, Thorben

Répondre

9

J'ai discuté cette question avec Microsoft. On dirait que c'est seulement un moyen de créer des pièces jointes à distance est le service Web List.asmx. J'ai essayé de créer ce sous-dossier aussi et sans succès.

+0

Merci pour la réponse, MaxBeard. Au moins savoir que ce n'est pas possible est mieux que d'essayer et d'échouer - il semble que cela devrait être possible. Au fait, bon blog. – Thorben

+0

Cela semble effectivement être le cas ... voir ma réponse pour un exemple de code complet sur la façon d'accomplir cela. –

4

Il reflète assez mal sur l'équipe Microsoft SharePoint pour ne pas avoir une reconnaissance du problème et une suggestion utilisable sur la façon de le résoudre. Voici comment je l'ai traité:

J'utilise le nouveau client géré SharePoint 2010 fourni avec le produit. Par conséquent, j'ai déjà un SharePoint ClientContext avec des informations d'identification. La fonction suivante ajoute une pièce jointe à un élément de la liste:

private void SharePoint2010AddAttachment(ClientContext ctx, 
            string listName, string itemId, 
            string fileName, byte[] fileContent) 
{ 
    var listsSvc = new sp2010.Lists(); 
    listsSvc.Credentials = _sharePointCtx.Credentials; 
    listsSvc.Url = _sharePointCtx.Web.Context.Url + "_vti_bin/Lists.asmx"; 
    listsSvc.AddAttachment(listName, itemId, fileName, fileContent); 
} 

La seule condition sine qua non pour le code ci-dessus est d'ajouter au projet (je Visual Studio 2008) un _web_reference_ j'ai appelé SP2010 qui est créée à partir de l'URL : http: // /_vti_bin/Lists.asmx

Bon Chance ...

12

Je me suis battu pendant longtemps avec ce problème, donc je pensais que je poste un exemple de code complet montrant comment pour créer avec succès un élément de liste et ajouter une pièce jointe. J'utilise l'API Client Object pour créer l'élément de liste et le service Web SOAP pour ajouter la pièce jointe. En effet, comme indiqué dans d'autres endroits sur le Web, l'API Client Object ne peut être utilisée que pour ajouter des pièces jointes à un élément dont le répertoire de téléchargement existe déjà (par exemple, si l'élément contient déjà une pièce jointe). Sinon, il échoue avec une erreur 409 ou quelque chose.Le service Web SOAP se contente de ce OK.

Notez qu'une autre chose que je devais surmonter était que même si j'ajouté la référence SOAP en utilisant l'adresse suivante:

https://my.sharepoint.installation/personal/test/_vti_bin/lists.asmx

L'URL VS effectivement ajouté à la app.config était:

https://my.sharepoint.installation/_vti_bin/lists.asmx

je devais changer manuellement le app.config vers l'URL correcte, sinon je recevrais l'erreur:

List does not exist. The page you selected contains a list that does not exist. It may have been deleted by another user. 0x82000006

Voici le code:

void CreateWithAttachment() 
    { 
     const string listName = "MyListName"; 
     // set up our credentials 
     var credentials = new NetworkCredential("username", "password", "domain"); 

     // create a soap client 
     var soapClient = new ListsService.Lists(); 
     soapClient.Credentials = credentials; 

     // create a client context 
     var clientContext = new Microsoft.SharePoint.Client.ClientContext("https://my.sharepoint.installation/personal/test"); 
     clientContext.Credentials = credentials; 

     // create a list item 
     var list = clientContext.Web.Lists.GetByTitle(listName); 
     var itemCreateInfo = new ListItemCreationInformation(); 
     var newItem = list.AddItem(itemCreateInfo); 

     // set its properties 
     newItem["Title"] = "Created from Client API"; 
     newItem["Status"] = "New"; 
     newItem["_Comments"] = "here are some comments!!"; 

     // commit it 
     newItem.Update(); 
     clientContext.ExecuteQuery(); 

     // load back the created item so its ID field is available for use below 
     clientContext.Load(newItem); 
     clientContext.ExecuteQuery(); 

     // use the soap client to add the attachment 
     const string path = @"c:\temp\test.txt"; 
     soapClient.AddAttachment(listName, newItem["ID"].ToString(), Path.GetFileName(path), 
            System.IO.File.ReadAllBytes(path)); 
    } 

Espérons que cela aide quelqu'un.

+1

Merci. Cela l'a fait pour moi. –

+0

J'utilise Visual Studio 2012 et je tente de sauvegarder les pièces jointes d'une liste dans SharePoint 2010. Je ne trouve aucun service Web sur mon serveur SharePoint 2010 dont les classes et méthodes proxy correspondent à l'exemple ci-dessus. – Zarepheth

+2

Ok, j'ai trouvé mon problème. Dans Visual Studio 2012, il faut ajouter un 'Web Reference' plutôt qu'un' Service Reference'. Dans la boîte de dialogue "Ajouter une référence de service", cliquez sur le bouton "Avancé ...". Cliquez ensuite sur le bouton "Ajouter une référence Web ...". Maintenant, la boîte de dialogue familière "Ajouter une référence Web" des versions antérieures de Visual Studio est affichée. – Zarepheth

0

Je l'ai utilisé et essayé celui-ci sur mon application COM et il fonctionne pour moi

using (ClientContext context = new ClientContext("http://spsite2010")) 
       { 

        context.Credentials = new NetworkCredential("admin", "password"); 
        Web oWeb = context.Web; 
        List list = context.Web.Lists.GetByTitle("Tasks"); 
        CamlQuery query = new CamlQuery(); 
        query.ViewXml = "<View><Where><Eq><FieldRef Name = \"Title\"/><Value Type=\"String\">New Task Created</Value></Eq></Where></View>"; 
        ListItemCollection listItems = list.GetItems(query); 
        context.Load(listItems); 
        context.ExecuteQuery(); 
        FileStream oFileStream = new FileStream(@"C:\\sample.txt", FileMode.Open); 
        string attachmentpath = "/Lists/Tasks/Attachments/" + listItems[listItems.Count - 1].Id + "/sample.txt"; 
        Microsoft.SharePoint.Client.File.SaveBinaryDirect(context, attachmentpath, oFileStream, true); 
       } 

Note: Fonctionne uniquement si le dossier de l'élément a été créé déjà

5

Avec Sharepoint 2010 il n'y avait aucun moyen pour télécharger une première pièce jointe à un élément de liste en utilisant le COM. La recommandation était d'utiliser le service web Lists inmstead.

Avec Sharepoint 2013 cela fonctionne.

AttachmentCreationInformation newAtt = new AttachmentCreationInformation(); 
newAtt.FileName = "myAttachment.txt"; 
// create a file stream 
string fileContent = "This file is was ubloaded by client object meodel "; 
System.Text.ASCIIEncoding enc = new System.Text.ASCIIEncoding(); 
byte[] buffer = enc.GetBytes(fileContent); 
newAtt.ContentStream = new MemoryStream(buffer); 

// att new item or get existing one 
ListItem itm = list.GetItemById(itemId); 
ctx.Load(itm); 
// do not execute query, otherwise a "version conflict" exception is rised, but the file   is uploaded 
// add file to attachment collection 
newAtt.ContentStream = new MemoryStream(buffer); 
itm.AttachmentFiles.Add(newAtt); 
AttachmentCollection attachments = itm.AttachmentFiles; 
ctx.Load(attachments); 
ctx.ExecuteQuery(); 
// see all attachments for list item 
// this snippet works if the list item has no attachments 

Cette méthode est utilisée dans http://www.mailtosharepoint.net/

+0

Wow, merci beaucoup. Cela fonctionne très bien avec SharePoint (2013) Online et une application MVC. –

+0

@sam À moins de manquer quelque chose, cela ne semble pas fonctionner à moins d'utiliser un ListItem existant. Si vous créez un nouvel élément via la méthode AddItem, cela ne fonctionne pas. Cela génère une erreur indiquant que vous devez d'abord enregistrer l'élément, puis enregistrer la pièce jointe. – Thierry

+0

@sam, je le reprends, ça marche :) mais pas tout à fait comme vous l'avez décrit dans votre extrait de code. Vous devez d'abord ajouter l'élément en appelant AddItem, puis appeler le code à partir de 'GetItemById' et cela fonctionne très bien. – Thierry

0

HTML:

<asp:FileUpload ID="FileUpload1" runat="server" AllowMultiple="true" /> 

événement dans le code derrière:

protected void UploadMultipleFiles(object sender, EventArgs e) 
{ 
    Common.UploadDocuments(Common.getContext(new Uri(Request.QueryString["SPHostUrl"]), 
    Request.LogonUserIdentity), FileUpload1.PostedFiles, new CustomerRequirement(), 5); 
} 

public static List<string> UploadDocuments<T>(ClientContext ctx,IList<HttpPostedFile> selectedFiles, T reqObj, int itemID) 
{ 
    List<Attachment> existingFiles = null; 
    List<string> processedFiles = null; 
    List<string> unProcessedFiles = null; 
    ListItem item = null; 
    FileStream sr = null; 
    AttachmentCollection attachments = null; 
    byte[] contents = null; 
    try 
    { 
     existingFiles = new List<Attachment>(); 
     processedFiles = new List<string>(); 
     unProcessedFiles = new List<string>(); 
     //Get the existing item 
     item = ctx.Web.Lists.GetByTitle(typeof(T).Name).GetItemById(itemID); 
     //get the Existing attached attachments 
     attachments = item.AttachmentFiles; 
     ctx.Load(attachments); 
     ctx.ExecuteQuery(); 
     //adding into the new List 
     foreach (Attachment att in attachments) 
      existingFiles.Add(att); 
     //For each Files which user has selected 
     foreach (HttpPostedFile postedFile in selectedFiles) 
     { 
      string fileName = Path.GetFileName(postedFile.FileName); 
      //If selected file not exist in existing item attachment 
      if (!existingFiles.Any(x => x.FileName == fileName)) 
      { 
       //Added to Process List 
       processedFiles.Add(postedFile.FileName); 
      } 
      else 
       unProcessedFiles.Add(fileName); 
     } 
     //Foreach process item add it as an attachment 
     foreach (string path in processedFiles) 
     { 
      sr = new FileStream(path, FileMode.Open); 
      contents = new byte[sr.Length]; 
      sr.Read(contents, 0, (int)sr.Length); 
      var attInfo = new AttachmentCreationInformation(); 
      attInfo.FileName = Path.GetFileName(path); 
      attInfo.ContentStream = sr; 
      item.AttachmentFiles.Add(attInfo); 
      item.Update(); 
     } 
     ctx.ExecuteQuery(); 
    } 
    catch (Exception ex) 
    { 
     throw ex; 
    } 
    finally 
    { 
     existingFiles = null; 
     processedFiles = null; 
     item = null; 
     sr = null; 
     attachments = null; 
     contents = null; 
     ctx = null; 

    } 
    return unProcessedFiles; 
} 
+0

Juste poster un bloc de code ne fait pas une bonne réponse à une question. Veuillez expliquer * comment * votre solution résout la tâche de l'OP et ce qu'elle ajoute aux autres réponses déjà présentes sur la question. – TZHX

Questions connexes