Compatibilidad con % y # en archivos y carpetas con la API de ResourcePath
Se está implementando la compatibilidad con % y # en archivos y carpetas en SharePoint Online. Desafortunadamente, debido a los patrones de llamadas y las estructuras de las API existentes, puede que a veces trabajar con estos nombres de archivo sea ambiguo. Puede encontrar más información sobre esto en nuestro blog de desarrolladores.
En resumen, se han agregado nuevas API a la superficie del modelo de objetos del lado cliente (CSOM) de SharePoint Online para proporcionar compatibilidad con los caracteres # y %.
Nueva clase ResourcePath
Como resumen, tenga en cuenta que las API de SharePoint existentes basada en cadenas (como SPFileCollection.GetByUrl) controlan URL con o sin codificación asumiendo automáticamente que los caracteres % y # en una ruta de acceso implican que la dirección URL está codificada. Con la nueva compatibilidad con % y # en archivos y carpetas, este tratamiento automático es un problema porque puede causar que el código descendente omita o gestione de forma incorrecta los nombres de archivo que incluyan % y #.
Una nueva clase, Microsoft.SharePoint.Client.ResourcePath
, se ha agregado a las API. La clase ResourcePath es fundamental para la compatibilidad de estos nuevos caracteres. Proporciona una forma nueva e inequívoca para tratar un elemento dentro de SharePoint y OneDrive para la Empresa, ya que da por supuesto y sólo funciona con direcciones URL descodificadas. Reemplaza las rutas de acceso basadas en cadenas para representar una URL completa (absoluta) o parcial (relativa) para una colección de sitios, sitio, archivo, carpeta u otros artefactos y OneDrive para la Empresa. Para admitir correctamente % y # dentro de las direcciones URL, debe usar las API basadas en ResourcePath junto con direcciones URL descodificadas.
ResourcePath se puede construir simplemente llamando a una función estática ResourcePath.FromDecodedUrl(string)
. Se puede acceder al valor de entrada que se pasa desde el objeto ResourcePath mediante una llamada a la propiedad DecodedUrl.
En el caso de las llamadas existentes que tienen una dirección URL basada en cadena, necesita determinar si la ruta de código que conduce a las llamadas de URL basadas en cadena se proporcionaron con direcciones URL codificadas o descodificadas, y si las rutas de código también permiten vínculos delimitadores (es decir: adiciones #bookmark además de la dirección URL del archivo).
Nota:
No es suficiente con buscar y reemplazar los usos existentes de las API de URL basadas en cadena con ResourcePath.FromDecodedUrl
. Necesitará determinar correctamente la dirección URL y potencialmente descodificar las URL antes de utilizar la API de ResourcePath.FromDecodedUrl(string)
.
En los casos donde una ruta de código que conduce a una llamada de API de SharePoint usa URL descodificadas (por ejemplo, "FY17 Report.docx'"), puede reemplazar estas llamadas con ResourcePath.FromDecodedUrl(string)
y los métodos ResourcePath equivalentes que aparecen más adelante en este artículo.
Tenga en cuenta que, en muchos casos en los que lee la dirección URL de SharePoint a través de las API, también se proporciona el ResourcePath para hacer que estos patrones de código sean más coherentes, por lo que puede usar el ResourcePath en lugar de la dirección URL.
Tenga en cuenta que este cambio se aplica también a las llamadas basadas en REST de SharePoint. Revise los escenarios siguientes para ver ejemplos de estas nuevas API de REST.
Nuevas API basadas en ResourcePath que admiten # y %
La siguiente tabla muestra las nuevas API que hemos añadido para reemplazar las API existentes y admitir # y %. Se muestran las API antiguas junto a las nuevas para su comparación. La funcionalidad principal de estas API no cambia, pero la forma en que representan la ubicación del elemento sí lo hace.
Para obtener información sobre las nuevas API, vea la Referencia de la API de cliente .NET para SharePoint Online. Hemos enumerado las API del CSOM de .NET, pero los nuevos métodos también están disponibles en la forma equivalente en nuestras bibliotecas del CSOM de JavaScript.
Ensamblado Microsoft.SharePoint.Client.dll
Tipo | Método anterior | Nuevo método |
---|---|---|
Microsoft.SharePoint.SPList | AddItem(Microsoft.SharePoint.SPListItemCreationInformation) | AddItemUsingPath(parámetros SPListItemCreationInformationUsingPath) |
Microsoft.SharePoint.SPFile | MoveTo(System.String, Microsoft.SharePoint.SPMoveOperations) | MoveToUsingPath(SPResourcePath newPath, SPMoveOperations moveOperations) |
Microsoft.SharePoint.SPFile | CopyTo(System.String, Boolean) | CopyToUsingPath(SPResourcePath newPath, bool overwrite) |
Microsoft.SharePoint.SPFileCollection | GetByUrl(System.String) | GetByPath(SPResourcePath) |
Microsoft.SharePoint.SPFileCollection | Add(System.String, Microsoft.SharePoint.SPTemplateFileType) | AddUsingPath(SPResourcePath, SPFileCollectionAddWithTemplateParameters) |
Microsoft.SharePoint.SPFolder | MoveTo(System.String) | MoveToUsingPath(SPResourcePath newPath) |
Microsoft.SharePoint.SPFolder | AddSubFolder(System.String) | AddSubFolderUsingPath(SPResourcePath leafPath) |
Microsoft.SharePoint.SPFolderCollection | GetByUrl(System.String) | GetByPath(ruta de acceso SPResourcePath) |
Microsoft.SharePoint.SPFolderCollection | Add(System.String) | AddUsingPath(ruta de acceso SPResourcePath, parámetros SPFolderCreationInformation) |
AddWithOverwrite(url de cadena, bool overwrite) | ||
Microsoft.SharePoint.SPRemoteWeb | GetFileByServerRelativeUrl(System.String) | GetFileByServerRelativePath(ruta de acceso SPResourcePath) |
Microsoft.SharePoint.SPWeb | GetList(System.String) | GetListUsingPath(SPResourcePath) |
Microsoft.SharePoint.SPWeb | GetListItem(System.String) | GetListItemUsingPath(SPResourcePath) |
Los siguientes objetos CSOM devuelven propiedades ResourcePath que se pueden usar en estas API. Aunque la propiedad antigua también devuelve direcciones URL descodificadas, la nueva propiedad de ResourcePath se proporciona para una mayor comodidad, simplicidad y claridad al llamar a estas API. La única excepción es la propiedad SPFolder.WelcomePage, que anteriormente devolvía direcciones URL codificadas y descodificadas; ahora se devuelve sin ambigüedades a través de la propiedad WelcomePagePath.
Tipo | Propiedad anterior | Nueva propiedad |
---|---|---|
Microsoft.SharePoint.SPList | DefaultViewUrl | DefaultViewPath |
Microsoft.SharePoint.SPList | DefaultEditFormUrl | DefaultEditFormPath |
Microsoft.SharePoint.SPList | DefaultNewFormUrl | DefaultNewFormPath |
Microsoft.SharePoint.SPList | DefaultDisplayFormUrl | DefaultDisplayFormPath |
Microsoft.SharePoint.SPAttachment | ServerRelativeUrl | ServerRelativePath |
Microsoft.SharePoint.SPFile | ServerRelativeUrl | ServerRelativePath |
Microsoft.SharePoint.SPFolder | ServerRelativeUrl | ServerRelativePath |
Microsoft.SharePoint.SPFolder | WelcomePage | WelcomePagePath/ WelcomePageParameters |
Microsoft.SharePoint.SPView | ServerRelativeUrl | ServerRelativePath |
Microsoft.SharePoint.SPDocumentLibraryInformation | ServerRelativeUrl | ServerRelativePath |
API existentes que no son ambiguas con respecto al formato de dirección URL y pueden admitir # y %
Las siguientes API solo aceptan direcciones URL codificadas correctamente como entrada. También admiten URL sin codificar por completo mientras puedan consumirse sin ambigüedades. Es decir, al menos los caracteres # o % de la ruta de acceso de la dirección URL deberían codificarse. Estas API seguirán funcionando del mismo modo. #
en la dirección URL se trata como un delimitador de fragmento, pero no como parte de la dirección URL.
Tipo | Propiedad anterior |
---|---|
Microsoft.SharePoint.SPWeb | GetFileByUrl(System.String) |
Microsoft.SharePoint.SPWeb | GetFileByWOPIFrameUrl(System.String) |
Microsoft.SharePoint.SPWeb | GetFileByLinkingUrl(System.String) |
Los siguientes propiedades de C# se agregan para devolver System.Uri con codificación inequívoca para su uso con las API anteriores. Las variantes anteriores de las siguientes API devolvían direcciones URL descodificadas y, ya que nunca contenían caracteres # o %, la dirección URL no era ambigua. No queríamos interrumpir el comportamiento de las variantes anteriores para codificar caracteres % y # en la ruta de acceso. Por lo tanto, se crearon nuevas API.
Tipo | Propiedad anterior | Nueva propiedad |
---|---|---|
Microsoft.SharePoint.SPFile | LinkingUrl | LinkingUri |
Microsoft.SharePoint.SPFile | ServerRedirectedEmbedUrl | ServerRedirectedEmbedUri |
Código de ejemplo
Escenarios CSOM
Agregar un archivo a una carpeta (.net)
ClientContext context = new ClientContext("http://site");
Web web = context.Web;
// Get the parent folder
ResourcePath folderPath = ResourcePath.FromDecodedUrl("/Shared Documents");
Folder parentFolder = web.GetFolderByServerRelativePath(folderPath);
// Create the parameters used to add a file
ResourcePath filePath = ResourcePath.FromDecodedUrl("/Shared Documents/hello world.txt");
byte[] fileContent = System.Text.Encoding.UTF8.GetBytes("sample file content");
FileCollectionAddParameters fileAddParameters = new FileCollectionAddParameters();
fileAddParameters.Overwrite = true;
using (MemoryStream contentStream = new MemoryStream(fileContent))
{
// Add a file
Microsoft.SharePoint.Client.File addedFile = parentFolder.Files.AddUsingPath(filePath, fileAddParameters, contentStream);
// Select properties of added file to inspect
context.Load(addedFile, f => f.UniqueId, f1 => f1.ServerRelativePath);
// Perform the actual operation
context.ExecuteQuery();
// Print the results
Console.WriteLine(
"Added File [UniqueId:{0}] [ServerRelativePath:{1}]",
addedFile.UniqueId,
addedFile.ServerRelativePath.DecodedUrl);
}
Agregar una subcarpeta a una carpeta (.net)
ClientContext context = new ClientContext("http://site");
Web web = context.Web;
// Get the parent folder
ResourcePath folderPath = ResourcePath.FromDecodedUrl("Shared Documents");
Folder parentFolder = web.GetFolderByServerRelativePath(folderPath);
// Create the parameters used to add a folder
ResourcePath subFolderPath = ResourcePath.FromDecodedUrl("Shared Documents/sub folder");
FolderCollectionAddParameters folderAddParameters = new FolderCollectionAddParameters();
folderAddParameters.Overwrite = true;
// Add a sub folder
Folder addedFolder = parentFolder.Folders.AddUsingPath(subFolderPath, folderAddParameters);
// Select properties of added file to inspect
context.Load(addedFolder, f => f.UniqueId, f1 => f1.ServerRelativePath);
// Perform the actual operation
context.ExecuteQuery();
// Print the results
Console.WriteLine(
"Added Folder [UniqueId:{0}] [ServerRelativePath:{1}]",
addedFolder.UniqueId,
addedFolder.ServerRelativePath.DecodedUrl);
Obtener un archivo en la web (.net)
ClientContext context = new ClientContext("http://site");
Web web = context.Web;
// Get the file
ResourcePath filePath = ResourcePath.FromDecodedUrl("/Shared Documents/hello world.txt");
File file = web.GetFileByServerRelativePath(filePath);
// Select properties of the file
context.Load(file, f => f.UniqueId, f1 => f1.ServerRelativePath);
// Perform the actual operation
context.ExecuteQuery();
// Print the results
Console.WriteLine(
"File Properties [UniqueId:{0}] [ServerRelativePath:{1}]",
file.UniqueId,
file.ServerRelativePath.DecodedUrl);
Escenarios de REST
Obtener carpetas
url: http://site url/_api/web/GetFolderByServerRelativePath(decodedUrl='library name/folder name')
method: GET
headers:
Authorization: "Bearer " + accessToken
accept: "application/json;odata=verbose" or "application/atom+xml"
Crear carpeta
url: http://site url/_api/web/Folders/AddUsingPath(decodedurl='/document library relative url/folder name')
method: POST
headers:
Authorization: "Bearer " + accessToken
X-RequestDigest: form digest value
accept: "application/json;odata=verbose"
content-type: "application/json;odata=verbose"
Obtener archivos
url: http://site url/_api/web/GetFileByServerRelativePath(decodedUrl='folder name/file name')
method: GET
Headers:
Authorization: "Bearer " + accessToken
accept: "application/json;odata=verbose" or "application/atom+xml"
Agregar archivos
url: http://site url/_api/web/GetFolderByServerRelativePath(decodedUrl='folder name')/Files/AddStubUsingPath(decodedurl='testfile.txt')
methods: POST
Headers:
Authorization: "Bearer " + accessToken
X-RequestDigest: form digest value
accept: "application/json;odata=verbose"
content-type: "application/json;odata=verbose"
Content-Length: length