Erro de URL inválido ao implantar arquivos programaticamente na biblioteca de estilos usando um módulo

sharepoint.stackexchange https://sharepoint.stackexchange.com//questions/49447

  •  09-12-2019
  •  | 
  •  

Pergunta

Usamos um recurso para implantar arquivos comuns às nossas webparts na Biblioteca de estilos no SharePoint Server 2010 e recentemente nos deparamos com o problema em que os arquivos não estavam sendo atualizados quando implantamos uma versão atualizada do recurso.(Observação:Eu uso o termo "versão" livremente aqui - não estamos controlando nossas webparts).Depois de pesquisar, descobri que esse problema (ou seja,módulos implantarão a versão inicial de um arquivo, mas não o atualizarão) foi documentado em vários blogs.A conclusão de tudo foi que para atualizar os arquivos, é necessário fazê-lo programaticamente usando um FeatureReceiver.Encontrei algumas soluções diferentes:

Para soluções de webpart em área restrita:

http://stefan-stanev-sharepoint-blog.blogspot.com.au/2011/01/automatically-publishing-files.html

Para soluções webpart de farm:

http://johanleino.wordpress.com/2009/04/22/howto-handling-file-updates-in-sharepoint/

Tentei as duas soluções, mas acabei optando pela solução de Johan com alguns pequenos ajustes para o nosso cenário.

Encontrei uma NullReferenceException quando executei o código de Johan, mas isso ocorreu porque não temos um atributo Path em nosso elemento Module.Substituí a chamada para recuperar o atributo Path por uma chamada para recuperar o atributo Url.Encontrei então o seguinte erro:

The URL ‘[url]‘ is invalid. It may refer to a nonexistent file or folder, or refer to a valid file or folder that is not in the current Web

Encontrei vários blogs diferentes descrevendo soluções para esse erro, mas nenhum resolveu isso para mim:

* links removidos porque sou um novato que não pode postar mais de 2 links;) *

Alguém tem alguma outra sugestão além dos logs?

OBSERVAÇÃO:Estamos usando uma solução farm, não uma solução sandbox.

Foi útil?

Solução

Depois de ler bastante e depurar o receptor de recursos, descobri duas coisas:

  1. Um de nossos arquivos (que foi introduzido após a implantação da versão original, mas antes da versão atual) não existia na Biblioteca de Estilos no site do SharePoint.ou sejanunca havia sido implantado.Verifiquei alguns de nossos servidores de teste e o arquivo também não estava lá, então isso confirmou que não estava isolado em minha máquina de desenvolvimento.Este arquivo "ausente" era o arquivo que gerava o erro de URL inválido quando SPWeb.Files.Add foi chamado.Confirmei que o arquivo existia no hive e que o método Add poderia criar novos arquivos.Dei uma olhada no que SPWeb.GetFile() estava retornando.Curiosamente, o objeto SPFile retornado ao recuperar o "arquivo virtual" tinha Exists = true...mas...o arquivo não existe no servidor???(Postagem interessante aqui no SPWeb.GetFile(): http://blog.mastykarz.nl/inconvenient-spwebgetfilestring/).Passei a usar GetFileOrFolder() e transmitir para SPFile, mas meu problema ainda não foi resolvido.

  2. Depois de examinar novamente o código de Johan, decidi ver se havia algo mais na chamada para Add que pudesse estar causando o problema.Reexaminei nosso arquivo elements.xml para ver se a entrada do arquivo "ausente" era diferente das outras entradas do arquivo.Acabou sendo aí que estava meu problema...a entrada do arquivo "ausente" não tinha todos os atributos que outras entradas tinham.Em particular, faltavam os atributos Type e IgnoreIfExists.

    <File Path="Style Library\Assets\Scripts\JQuery\JQueryDollarFix.js" Url="Assets/Scripts/JQuery/JQueryDollarFix.js" />
    

    Atualizei a entrada para ser:

    <File Path="Style Library\Assets\Scripts\JQuery\JQueryDollarFix.js" Url="Assets/Scripts/JQuery/JQueryDollarFix.js" Type="GhostableInLibrary" IgnoreIfAlreadyExists="True"/>
    

    Reimplantei o wsp no site do SharePoint e ativei o recurso.O código do FeatureReceiver foi executado com êxito e os arquivos foram atualizados e verificados na Biblioteca de estilos.

    Extensão de propriedades do receptor de recurso (coloquei isso em sua própria classe no mesmo projeto do recurso):

    using System.Collections;
    using System.Globalization;
    using System.IO;
    using System.Linq;
    using System.Xml.Linq;
    
    using Microsoft.SharePoint;
    using Microsoft.SharePoint.Administration;
    
    /// <summary>
    /// Extension methods for SPFeatureReceiverProperties
    /// </summary>
    public static class SPFeatureReceiverPropertiesExtension
    {
        /// <summary>
        /// Updates the files in module.
        /// </summary>
        /// <param name="instance">The instance.</param>
        public static void UpdateFilesInModule(this SPFeatureReceiverProperties instance)
        {
            var modules = (from SPElementDefinition element in instance.Feature.Definition.GetElementDefinitions(CultureInfo.CurrentCulture)
                           where element.ElementType == "Module"
                           let xmlns = XNamespace.Get(element.XmlDefinition.NamespaceURI)
                           let module = XElement.Parse(element.XmlDefinition.OuterXml)
                           select new
                               {
                                   Url = module.Attribute("Url").Value,
                                   Path = Path.Combine(element.FeatureDefinition.RootDirectory, module.Attribute("Url").Value), // don't have a Path attribute on our Module so changed Path to URL
                                   Files = (from file in module.Elements(xmlns.GetName("File"))
                                            select new
                                                {
                                                    Url = file.Attribute("Url").Value,
                                                    Properties = (from property in file.Elements(xmlns.GetName("Property"))
                                                                  select property).ToDictionary(
                                                                      n => n.Attribute("Name").Value,
                                                                      v => v.Attribute("Value").Value)
                                                }).ToList()
                               }).ToList();
    
            using (SPWeb web = (instance.Feature.Parent as SPSite).OpenWeb())
            {
                modules.ForEach(module =>
                    {
                        module.Files.ForEach(file =>
                            {
                                string hivePath = Path.Combine(module.Path, file.Url); // in 14-hive
                                string virtualPath = string.Concat(web.Url, "/", module.Url, "/", file.Url); // in SPFS
    
                                if (File.Exists(hivePath))
                                {
                                    using (StreamReader streamReader = new StreamReader(hivePath))
                                    {
                                        object obj = web.GetFileOrFolderObject(virtualPath);
    
                                        if (obj is SPFile)
                                        {
                                            SPFile virtualFile = (SPFile)obj;
                                            bool checkOutEnabled = virtualFile.Item == null
                                                                       ? virtualFile.ParentFolder.Item.ParentList.
                                                                             ForceCheckout
                                                                       : virtualFile.Item.ParentList.ForceCheckout;
                                            bool needsApproval = virtualFile.Item == null
                                                                     ? virtualFile.ParentFolder.Item.ParentList.
                                                                           EnableModeration
                                                                     : virtualFile.Item.ParentList.EnableModeration;
    
                                            if (checkOutEnabled)
                                            {
                                                if (virtualFile.CheckOutType != SPFile.SPCheckOutType.None)
                                                {
                                                    virtualFile.UndoCheckOut();
                                                }
                                                virtualFile.CheckOut();
                                            }
    
                                            virtualFile = web.Files.Add(
                                                virtualPath,
                                                streamReader.BaseStream,
                                                new Hashtable(file.Properties),
                                                true);
    
                                            if (checkOutEnabled)
                                            {
                                                virtualFile.CheckIn(
                                                    "Checked in by deployment.", SPCheckinType.MajorCheckIn);
                                            }
    
                                            if (needsApproval)
                                            {
                                                virtualFile.Approve("Approved by deployment.");
                                            }
    
                                            virtualFile.Update();
                                        }
                                    }
                                }
                            });
                    });
            }
        }
    }
    

Um trecho do arquivo elements.xml para nosso Módulo:

<?xml version="1.0" encoding="utf-8"?>
<Elements xmlns="http://schemas.microsoft.com/sharepoint/">
  <Module Name="Style Library" Url="Style Library">
    <File Path="Style Library\Assets\Scripts\JQuery\UI\jquery-ui-1.8.16.custom.js" Url="Assets/Scripts/JQuery/UI/jquery-ui-1.8.16.custom.js" Type="GhostableInLibrary" IgnoreIfAlreadyExists="TRUE" />
    <File Path="Style Library\Assets\Scripts\JQuery\UI\jquery-ui-1.8.16.custom.min.js" Url="Assets/Scripts/JQuery/UI/jquery-ui-1.8.16.custom.min.js" Type="GhostableInLibrary" IgnoreIfAlreadyExists="TRUE" />
    <File Path="Style Library\Assets\Resources\search.png" Url="Assets/Resources/search.png" Type="GhostableInLibrary" IgnoreIfAlreadyExists="TRUE" />
    <File Path="Style Library\Assets\Scripts\Common.js" Url="Assets/Scripts/Common.js" Type="GhostableInLibrary" IgnoreIfAlreadyExists="TRUE" />   
    <File Path="Style Library\Assets\Styles\Common.css" Url="Assets/Styles/Common.css" Type="GhostableInLibrary" IgnoreIfAlreadyExists="TRUE" />
    <File Path="Style Library\Assets\Styles\Pager.css" Url="Assets/Styles/Pager.css" Type="GhostableInLibrary" IgnoreIfAlreadyExists="TRUE" />
    <File Path="Style Library\Assets\Styles\sharepoint.theme.overrides.css" Url="Assets/Styles/sharepoint.theme.overrides.css" Type="GhostableInLibrary" IgnoreIfAlreadyExists="TRUE" />
    <File Path="Style Library\Assets\Scripts\JQuery\JQueryDollarFix.js" Url="Assets/Scripts/JQuery/JQueryDollarFix.js" Type="GhostableInLibrary" IgnoreIfAlreadyExists="True"/>
    <File Path="Style Library\Assets\Styles\images\arrow.gif" Url="Assets/Styles/images/arrow.gif" Type="GhostableInLibrary" IgnoreIfAlreadyExists="True"/>
  </Module>
</Elements>

Links Úteis:

* Removido porque não é possível adicionar mais de 2 links *

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