Não autorizado em XDocument.Load no Sharepoint
-
10-12-2019 - |
Pergunta
Estou tentando abrir um arquivo XML da minha biblioteca de documentos.Estou executando um código como "Privilégio Elevado" em um arquivo que sei que existe.
O código que anotei é este:
SPSecurity.RunWithElevatedPrivileges(() =>
{
using (SPSite sito = new SPSite("SITE URL"))
{
using (SPWeb web = sito.OpenWeb())
{
SPList lista = web.Lists.TryGetList("DOCUMENT LIBRARY NAME");
foreach (SPFile file in lista.RootFolder.Files)
{
String fileUrl = web.Url + "/" + lista.RootFolder.Url + "/" + file.Url;
var ret = XDocument.Load(fileUrl);
}
}
}
});
Quando alcanço o comando XDocument.Load, recebo a exceção "401 Unauthorized".
Há algo errado com meu código?O XDocument está sendo executado com privilégios errados?
Muito obrigado
Solução
Acho que a implementação de XDocument.Load(string) não suporta uma solicitação autenticada para recuperar o arquivo XML.
No entanto, existe outra maneira porque a abordagem que você está adotando significa que cada vez que um documento é aberto, duas solicitações da web serão feitas.
- Um para construir o URL usando o objeto SPFile
- Para acessar o objeto SPFile usando o URL criado na etapa 1.
Que tal em vez de construir a variável fileUrl você usar outra sobrecarga do XDocument.Load()?Desta vez, em vez do Uri passar em um objeto Stream.
Você tem todas as informações de que precisa e pode fazer algo assim: -
SPFileCollection filesInFolder = lista.RootFolder.Files;
foreach(SPFile file in filesInFolder)
{
using(Stream fileStream = file.OpenBinaryStream())
{
XDocument xmlDocument = XDocument.Load(fileStream);
fileStream.Close()
}
}
Não tentei o código, mas deixe-nos saber como você se saiu.Execute também SPDisposeCheck para garantir que isso não esteja causando vazamentos de memória.
Outras dicas
Descobri que, com as conversões certas, posso gerenciar o stream como se estivesse em um aplicativo "normal".
O código que uso agora (e funciona é:
SPSecurity.RunWithElevatedPrivileges(() =>
{
using (SPSite sito = new SPSite("SITE URL"))
{
using (SPWeb web = sito.OpenWeb())
{
SPList lista = web.Lists.TryGetList("DOCUMENT LIBRARY NAME");
foreach (SPFile file in lista.RootFolder.Files)
{
MemoryStream mStream = new MemoryStream(file.OpenBinary());
StreamReader reader = new StreamReader(mStream, true);
XDocument documento = XDocument.Load(reader, LoadOptions.None);
//MY CODE
}
}
}
});
O método de Simon Doy não funcionou para mim - eu recebo erros se eu ler em um fluxo em um método XDocument.Load() - "A melhor correspondência de método sobrecarregado para 'System.Xml.Linq.XDocument.Load(System.Xml.XmlReader)' tem alguns argumentos inválidos" e "Argumento '1':não é possível converter de 'System.IO.Stream' para 'System.Xml.XmlReader'"
Certo, eu estava tentando extrair um arquivo XML que acabei de adicionar à estrutura de pastas de um site do SharePoint usando o SharePoint Designer, em vez de um arquivo em uma biblioteca de documentos, mas me parece que a diferença de passar um StreamReader é muito importante, pois consegui fazê-lo funcionar usando o método do Ziba, mas ele não aceitava um Stream - ele só possui as opções uri, TextReader ou XmlReader (que pode ser na forma de StreamReader).
string siteUrl = SPContext.Current.Site.Url;
string xmlpath = siteUrl + @"/includes/XML/myFile.xml";
SPSecurity.RunWithElevatedPrivileges(delegate()
{
using (SPSite site = new SPSite(siteUrl))
{
using (SPWeb web = site.OpenWeb())
{
SPFile file = web.GetFile(xmlpath);
MemoryStream mStream = new MemoryStream(file.OpenBinary());
StreamReader reader = new StreamReader(mStream, true);
XDocument doc = XDocument.Load(reader, LoadOptions.None);
//MY CODE
}
}
});
Isso foi testado e funciona.