Pergunta

Tenho uma lista do SharePoint (não uma biblioteca) que aceita a criação de pastas.

Eu escrevi um pequeno método utilitário que me permite criar uma hierarquia de pastas, caso ela ainda não exista:

    public static SPFolder EnsureFolder(SPList list, string subFolderPath)
    {
        var folderPaths = subFolderPath.Split('/');

        var currentFolder = list.RootFolder;
        for (int i = 0; i < folderPaths.Length; i++)
        {
            var subFolder = currentFolder.SubFolders.Cast<SPFolder>().FirstOrDefault(f => f.Name == folderPaths[i]);
            if (subFolder == null)
            {                   
                var newFolderItem = list.Items.Add(currentFolder.ServerRelativeUrl, SPFileSystemObjectType.Folder, folderPaths[i]);
                newFolderItem.Update();
                currentFolder.Update();
                subFolder = newFolderItem.Folder;
                list.Update();
            }
            currentFolder = subFolder;
        }
        return currentFolder;
    }

Este código está funcionando na primeira vez, mas se eu fizer duas chamadas sucessivas, ele falhará:

var myList = web.Lists["some list"];
EnsureFolder(myList, "folder");
EnsureFolder(myList, "folder"); // same as 1st call

As segundas chamadas falham na linha:

newFolderItem.Update();

com este erro:

Un fichier ou un dossier nommé http://server/sites/coll/wen/Lists/somelist/folder existe déjà.     at Microsoft.SharePoint.SPGlobal.HandleComException(COMException comEx)
   at Microsoft.SharePoint.Library.SPRequest.AddOrUpdateItem(String bstrUrl, String bstrListName, Boolean bAdd, Boolean bSystemUpdate, Boolean bPreserveItemVersion, Boolean bPreserveItemUIVersion, Boolean bUpdateNoVersion, Int32& plID, String& pbstrGuid, Guid pbstrNewDocId, Boolean bHasNewDocId, String bstrVersion, Object& pvarAttachmentNames, Object& pvarAttachmentContents, Object& pvarProperties, Boolean bCheckOut, Boolean bCheckin, Boolean bMigration, Boolean bPublish, String bstrFileName, ISP2DSafeArrayWriter pListDataValidationCallback, ISP2DSafeArrayWriter pRestrictInsertCallback, ISP2DSafeArrayWriter pUniqueFieldCallback)
   at Microsoft.SharePoint.SPListItem.AddOrUpdateItem(Boolean bAdd, Boolean bSystem, Boolean bPreserveItemVersion, Boolean bNoVersion, Boolean bMigration, Boolean bPublish, Boolean bCheckOut, Boolean bCheckin, Guid newGuidOnAdd, Int32& ulID, Object& objAttachmentNames, Object& objAttachmentContents, Boolean suppressAfterEvents, String filename, Boolean bPreserveItemUIVersion)
   at Microsoft.SharePoint.SPListItem.UpdateInternal(Boolean bSystem, Boolean bPreserveItemVersion, Guid newGuidOnAdd, Boolean bMigration, Boolean bPublish, Boolean bNoVersion, Boolean bCheckOut, Boolean bCheckin, Boolean suppressAfterEvents, String filename, Boolean bPreserveItemUIVersion)
   at Microsoft.SharePoint.SPListItem.Update()
   at somewhere in my project

Isso pode ser traduzido como "Já existe uma pasta XXX".

Ao depurar, posso ver isso var subFolder = currentFolder.SubFolders.Cast<SPFolder>().FirstOrDefault(f => f.Name == folderPaths[i]); vai sempre retornar nulo.Parece que a propriedade SubFolders não está atualizada.

O que devo fazer para corrigir meu código?Estou chamando a sequência correta de .Update() chamadas?

Foi útil?

Solução

Encontrei uma solução simples.

Eu reescrevi o método assim:

public static SPFolder EnsureFolder(SPList list, string subFolderPath)
{
    var folderPaths = subFolderPath.Split('/');

    var currentFolder = list.RootFolder;
    for (int i = 0; i < folderPaths.Length; i++)
    {
        currentFolder = list.ParentWeb.GetFolder(currentFolder.Url); // hacky refresh
        var subFolder = currentFolder.SubFolders.Cast<SPFolder>().FirstOrDefault(f => string.Compare(f.Name, folderPaths[i], true) == 0);
        if (subFolder == null)
        {
            var newFolderItem = list.Items.Add(currentFolder.ServerRelativeUrl, SPFileSystemObjectType.Folder, folderPaths[i]);
            newFolderItem.SystemUpdate();

            subFolder = newFolderItem.Folder;
        }
        currentFolder = subFolder;
    }
    return currentFolder;
}

O truque está nesta linha:

 currentFolder = list.ParentWeb.GetFolder(currentFolder.Url); // hacky refresh

Esta linha realmente recarrega a pasta, em vez de depender dos dados ainda carregados.

Não sei se isso terá efeitos colaterais, mas resolveu meu problema.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a sharepoint.stackexchange
scroll top