Share via


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
 

Vea también