SharePoint 2010 - клиентская объектная модель-добавление вложения в ListItem



У меня есть список SharePoint, в который я добавляю новые ListItems, используя клиентскую объектную модель. Добавление ListItems не является проблемой и отлично работает.

Теперь я хочу добавить вложения.

Я использую SaveBinaryDirect следующим образом:

File.SaveBinaryDirect(clientCtx, url.AbsolutePath + "/Attachments/31/" + fileName, inputStream, true);
Это работает без каких-либо проблем, пока элемент, к которому я пытаюсь добавить вложение, уже имеет вложение, добавленное через сайт SharePoint и не использующее клиентскую объектную модель.

Когда Я попробуйте добавить вложение к элементу, который еще не имеет вложений, я получу следующие ошибки (оба случаются, но не с теми же файлами - но эти два сообщения появляются последовательно):

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

Я подумал, что, возможно, мне нужно сначала создать папку вложений для этого элемента. Когда я пробую следующий код:

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();

Я получаю сообщение об ошибке, говорящее::

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

У меня есть полные права администратора для сайта/списка SharePoint.

Любые идеи, что я может, я делаю что-то не так?

Спасибо, Торбен

160   6  

6 ответов:

Я обсуждал этот вопрос с Microsoft. Похоже, что только один способ создать вложения удаленно-Это список.служба ASMX. Я также пытался создать эту подпапку, но безуспешно.

Я долго боролся с этой проблемой, поэтому решил опубликовать полный пример кода, показывающий, как успешно создать элемент списка и добавить вложение.

Я использую API объекта клиента для создания элемента списка и веб-службу SOAP для добавления вложения. Это связано с тем, что, как отмечалось в других местах в интернете, API объекта клиента можно использовать только для добавления вложений к элементу, где каталог загрузки элемента уже существует (например. если элемент уже имеет привязанность). В противном случае он терпит неудачу с ошибкой 409 или что-то в этом роде. Однако веб-служба SOAP справляется с этим нормально.

Обратите внимание, что еще одна вещь, которую я должен был преодолеть, заключалась в том, что, хотя я добавил ссылку SOAP, используя следующий URL:

Https://my.служба SharePoint.установка / персональный / тест/_vti_bin / списки.asmx

URL, который VS фактически добавил в приложение.конфиг:

Https://my.служба SharePoint.установка/_vti_bin / списков.asmx

Мне пришлось вручную изменить приложение.config возвращается к правильному URL, иначе я получу ошибку:

Список не существует. Выбранная страница содержит несуществующий список. Возможно, он был удален другим пользователем. 0x82000006

Вот код:

    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));
    }

Надеюсь, это кому-то поможет.

В Sharepoint 2010 не было возможности загрузить первое вложение в элемент списка с помощью COM. Было рекомендовано использовать веб-сервис списков inmstead.

С Sharepoint 2013 это работает.

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

Этот метод используется в http://www.mailtosharepoint.net/

Это довольно плохо отражается на команде Microsoft SharePoint за то, что она не пришла с подтверждением проблемы и полезным предложением о том, как ее решить. Вот как я справился с этим:

Я использую новый управляемый клиент SharePoint 2010, который поставляется вместе с продуктом. Следовательно, у меня уже есть клиентский текст SharePoint с учетными данными. Следующая функция добавляет вложение к элементу списка:

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);
}

Единственным предварительным условием для приведенного выше кода является добавление проекта (я использовал Visual Studio 2008 С) в _web_reference_ я позвонил sp2010, который создается из URL: протокол HTTP:///_vti_bin сопоставляется/списки.asmx

Бон Шанс...

Я использовал и пробовал это в моем приложении COM, и оно работает для меня

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);
                }

Примечание: работает только в том случае, если папка item уже создана

HTML:

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

Событие в коде позади:

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;
}
    Ничего не найдено.

Добавить ответ:
Отменить.