Nota:
El acceso a esta página requiere autorización. Puede intentar iniciar sesión o cambiar directorios.
El acceso a esta página requiere autorización. Puede intentar cambiar los directorios.
El enfoque que se usa para implementar artefactos en un entorno de SharePoint es diferente en el nuevo modelo de complemento de SharePoint que con código de plena confianza. En un escenario típico de solución de granja o código de plena confianza (FTC), se agregaron módulos definidos en código declarativo (archivos XML del marco de características) a las características de SharePoint. Los módulos incluían la lista de artefactos que se van a implementar en el servidor de SharePoint. Los módulos se agregaron a las características de SharePoint e implementaron a través de soluciones de SharePoint. Tras la activación de características, los artefactos definidos en los módulos se implementaron en el entorno de SharePoint.
En un escenario de modelo de complemento de SharePoint, el patrón de aprovisionamiento remoto se usa para implementar artefactos en entornos de SharePoint.
Terminología
En este artículo se hace referencia al término artefactos . Los artefactos hacen referencia a elementos que normalmente se implementan en un entorno de SharePoint. Los artefactos suelen incluir:
- Archivos JavaScript
- archivos CSS
- Archivos de imagen (.jpg, .gif, .png, etc.)
- Páginas maestras
- Diseños de página
- Elementos de lista
Directrices importantes
Como regla general, nos gustaría proporcionar las siguientes directrices de alto nivel para implementar artefactos en entornos de SharePoint.
- Use el patrón de aprovisionamiento remoto (Modelo de objetos del lado cliente de SharePoint y API REST de SharePoint) para implementar artefactos en entornos de SharePoint.
- No use módulos de código declarativos ni archivos XML del marco de características para implementar artefactos en entornos de SharePoint.
Depuración
Una gran ventaja del uso de código para implementar artefactos es que puede depurar el proceso de implementación cuando se usa código. Es imposible depurar el proceso de implementación cuando se usan módulos de código declarativos o archivos XML del marco de características para implementar artefactos en entornos de SharePoint.
Introducción
Los siguientes ejemplos de código PnP de Microsoft 365 muestran cómo crear complementos de SharePoint que usan el patrón de aprovisionamiento remoto para implementar artefactos en un entorno de SharePoint.
En este ejemplo se muestra cómo crear una nueva carpeta en la biblioteca de estilos y agregar archivos e imágenes de JavaScript a los nuevos archivos.
-
Branding.ClientSideRendering (ejemplo de código PnP de Microsoft 365)
- Consulte los métodos UploadJSFiles y UploadFileToFolder en la clase Default.aspx.cs para obtener más información.
- Estos métodos también se muestran a continuación para obtener una referencia rápida.
Creación de una carpeta y carga de archivos JavaScript en la carpeta
void UploadJSFiles(Web web)
{
//Delete the folder if it exists
Microsoft.SharePoint.Client.List list = web.Lists.GetByTitle("Style Library");
IEnumerable<Folder> results = web.Context.LoadQuery<Folder>(list.RootFolder.Folders.Where(folder => folder.Name == "JSLink-Samples"));
web.Context.ExecuteQuery();
Folder samplesJSfolder = results.FirstOrDefault();
if (samplesJSfolder != null)
{
samplesJSfolder.DeleteObject();
web.Context.ExecuteQuery();
}
//Create new folder
samplesJSfolder = list.RootFolder.Folders.Add("JSLink-Samples");
web.Context.Load(samplesJSfolder);
web.Context.ExecuteQuery();
//Upload JavaScript files to folder
UploadFileToFolder(web, Server.MapPath("../Scripts/JSLink-Samples/Accordion.js"), samplesJSfolder);
UploadFileToFolder(web, Server.MapPath("../Scripts/JSLink-Samples/ConfidentialDocuments.js"), samplesJSfolder);
UploadFileToFolder(web, Server.MapPath("../Scripts/JSLink-Samples/DisableInput.js"), samplesJSfolder);
UploadFileToFolder(web, Server.MapPath("../Scripts/JSLink-Samples/HiddenField.js"), samplesJSfolder);
UploadFileToFolder(web, Server.MapPath("../Scripts/JSLink-Samples/PercentComplete.js"), samplesJSfolder);
UploadFileToFolder(web, Server.MapPath("../Scripts/JSLink-Samples/PriorityColor.js"), samplesJSfolder);
UploadFileToFolder(web, Server.MapPath("../Scripts/JSLink-Samples/ReadOnlySPControls.js"), samplesJSfolder);
UploadFileToFolder(web, Server.MapPath("../Scripts/JSLink-Samples/RegexValidator.js"), samplesJSfolder);
UploadFileToFolder(web, Server.MapPath("../Scripts/JSLink-Samples/SubstringLongText.js"), samplesJSfolder);
UploadFileToFolder(web, Server.MapPath("../Scripts/JSLink-Samples/DependentFields.js"), samplesJSfolder);
//Create another folder inside the folder that was just created
Folder imgsFolder = samplesJSfolder.Folders.Add("imgs");
web.Context.Load(imgsFolder);
web.Context.ExecuteQuery();
//Upload image files to folder
UploadFileToFolder(web, Server.MapPath("../Scripts/JSLink-Samples/imgs/Confidential.png"), imgsFolder);
}
Creación de una carpeta y carga de archivos de imagen en la carpeta
public static void UploadFileToFolder(Web web, string filePath, Folder folder)
{
//Create a FileStream to the file to upload
using (FileStream fs = new FileStream(filePath, FileMode.Open))
{
//Create FileCreationInformation object to set file metadata
FileCreationInformation flciNewFile = new FileCreationInformation();
flciNewFile.ContentStream = fs;
flciNewFile.Url = System.IO.Path.GetFileName(filePath);
flciNewFile.Overwrite = true;
//Upload file to SharePoint
Microsoft.SharePoint.Client.File uploadFile = folder.Files.Add(flciNewFile);
//Check in the file
uploadFile.CheckIn("CSR sample js file", CheckinType.MajorCheckIn);
folder.Context.Load(uploadFile);
folder.Context.ExecuteQuery();
}
}
En este ejemplo se muestra cómo cargar páginas maestras, establecer metadatos de página maestra y aplicar la página maestra al sitio estableciendo la CustomMasterUrl propiedad en el objeto Web.
-
Branding.ApplyBranding (ejemplo de código PnP de Microsoft 365)
- Vea los métodos UploadPageLayout, CreatePublishingPage y SetSupportCaseContent en la clase BrandingHelper.cs para obtener más detalles.
- Además de crear nuevos elementos en SharePoint, en este ejemplo se muestra cómo quitar elementos. Los métodos que quitan elementos se enumeran a continuación como referencia.
Eliminación de un archivo
private static void DeleteFile(Web web, string fileName, string serverPath, string serverFolder)
{
var fileUrl = string.Concat(serverPath, serverFolder, (string.IsNullOrEmpty(serverFolder) ? string.Empty : "/"), fileName);
var fileToDelete = web.GetFileByServerRelativeUrl(fileUrl);
fileToDelete.DeleteObject();
web.Context.ExecuteQuery();
}
Eliminar una carpeta
public static void RemoveFolder(ClientContext clientContext, string folder, string path)
{
var web = clientContext.Web;
var filePath = web.ServerRelativeUrl.TrimEnd(Program.trimChars) + "/" + path + "/";
var folderToDelete = web.GetFolderByServerRelativeUrl(string.Concat(filePath, folder));
Console.WriteLine("Removing folder {0} from {1}", folder, path);
folderToDelete.DeleteObject();
clientContext.ExecuteQuery();
}
Desasigne una página maestra y elimine la página maestra.
public static void RemoveMasterPage(ClientContext clientContext, string name, string folder)
{
var web = clientContext.Web;
clientContext.Load(web, w => w.AllProperties);
clientContext.ExecuteQuery();
Console.WriteLine("Deactivating and removing {0} from {1}", name, web.ServerRelativeUrl);
//set master pages back to the defaults that were being used
if (web.AllProperties.FieldValues.ContainsKey("OriginalMasterUrl"))
{
web.MasterUrl = (string)web.AllProperties["OriginalMasterUrl"];
}
if (web.AllProperties.FieldValues.ContainsKey("CustomMasterUrl"))
{
web.CustomMasterUrl = (string)web.AllProperties["CustomMasterUrl"];
}
web.Update();
clientContext.ExecuteQuery();
//now that the master page is set back to its default, re-reference the web from context and delete the custom master pages
web = clientContext.Web;
var lists = web.Lists;
var gallery = web.GetCatalog(116);
clientContext.Load(lists, l => l.Include(ll => ll.DefaultViewUrl));
clientContext.Load(gallery, g => g.RootFolder.ServerRelativeUrl);
clientContext.ExecuteQuery();
var masterPath = gallery.RootFolder.ServerRelativeUrl.TrimEnd(new char[] { '/' }) + "/";
DeleteFile(web, name, masterPath, folder);
}
Eliminación de un diseño de página
public static void RemovePageLayout(ClientContext clientContext, string name, string folder)
{
var web = clientContext.Web;
var lists = web.Lists;
var gallery = web.GetCatalog(116);
clientContext.Load(lists, l => l.Include(ll => ll.DefaultViewUrl));
clientContext.Load(gallery, g => g.RootFolder.ServerRelativeUrl);
clientContext.ExecuteQuery();
Console.WriteLine("Removing page layout {0} from {1}", name, clientContext.Web.ServerRelativeUrl);
var masterPath = gallery.RootFolder.ServerRelativeUrl.TrimEnd(Program.trimChars) + "/";
DeleteFile(web, name, masterPath, folder);
}
Este ejemplo tiene un poco de todo. Muestra cómo activar las características de publicación, cargar diseños de página, crear páginas de publicación, crear listas, tipos de contenido y elementos de lista, y crear páginas de publicación y agregar elementos web y elementos de complemento a las páginas. También se muestra cómo implementar elementos de lista tanto en la web host como en la web del complemento.
-
Branding.ClientSideRendering (ejemplo de código PnP de Microsoft 365)
- Consulte los métodos de la clase Utils.cs para obtener ejemplos de estas operaciones.
- Estos métodos se enumeran a continuación como referencia.
Activación de las características de publicación de la colección de sitios y el nivel de sitio
public static void ActivePublishingFeature(ClientContext ctx)
{
Guid publishingSiteFeatureId = new Guid("f6924d36-2fa8-4f0b-b16d-06b7250180fa");
Guid publishingWebFeatureId = new Guid("94c94ca6-b32f-4da9-a9e3-1f3d343d7ecb");
Site clientSite = ctx.Site;
ctx.Load(clientSite);
FeatureCollection clientSiteFeatures = clientSite.Features;
ctx.Load(clientSiteFeatures);
//Activate the site feature
clientSiteFeatures.Add(publishingSiteFeatureId, true, FeatureDefinitionScope.Farm);
ctx.ExecuteQuery();
FeatureCollection clientWebFeatures = ctx.Web.Features;
ctx.Load(clientWebFeatures);
//Activate the web feature
clientWebFeatures.Add(publishingWebFeatureId, true, FeatureDefinitionScope.Farm);
ctx.ExecuteQuery();
}
Creación de una lista
public static List CreateList(ClientContext ctx,
int templateType,
string title,
string url,
QuickLaunchOptions quickLaunchOptions)
{
ListCreationInformation listCreationInfo = new ListCreationInformation
{
TemplateType = templateType,
Title = title,
Url = url,
QuickLaunchOption = quickLaunchOptions
};
List spList = ctx.Web.Lists.Add(listCreationInfo);
ctx.Load(spList);
ctx.ExecuteQuery();
return spList;
}
Crear un tipo de contenido
public static ContentType CreateContentType(ClientContext ctx, string ctyName, string group, string ctyId)
{
ContentTypeCreationInformation contentTypeCreation = new ContentTypeCreationInformation();
contentTypeCreation.Name = ctyName;
contentTypeCreation.Description = "Custom Content Type";
contentTypeCreation.Group = group;
contentTypeCreation.Id = ctyId;
//Add the new content type to the collection
ContentType ct = ctx.Web.ContentTypes.Add(contentTypeCreation);
ctx.Load(ct);
ctx.ExecuteQuery();
return ct;
}
Carga de un diseño de página
public static void UploadPageLayout(ClientContext ctx, string sourcePath, string targetListTitle, string targetUrl)
{
using (FileStream fs = new FileStream(sourcePath, FileMode.Open, FileAccess.Read))
{
byte[] data = new byte[fs.Length];
fs.Read(data, 0, data.Length);
using (MemoryStream ms = new MemoryStream())
{
ms.Write(data, 0, data.Length);
var newfile = new FileCreationInformation();
newfile.Content = ms.ToArray();
newfile.Url = targetUrl;
newfile.Overwrite = true;
List docs = ctx.Web.Lists.GetByTitle(targetListTitle);
Microsoft.SharePoint.Client.File uploadedFile = docs.RootFolder.Files.Add(newfile);
uploadedFile.CheckOut();
uploadedFile.CheckIn("Data storage model", CheckinType.MajorCheckIn);
uploadedFile.Publish("Data storage model layout.");
ctx.Load(uploadedFile);
ctx.ExecuteQuery();
}
}
}
Creación de una página de publicación y establecimiento de su diseño de página
public static void CreatePublishingPage(ClientContext clientContext, string pageName, string pagelayoutname, string url, string queryurl)
{
var publishingPageName = pageName + ".aspx";
Web web = clientContext.Web;
clientContext.Load(web);
List pages = web.Lists.GetByTitle("Pages");
clientContext.Load(pages.RootFolder, f => f.ServerRelativeUrl);
clientContext.ExecuteQuery();
Microsoft.SharePoint.Client.File file =
web.GetFileByServerRelativeUrl(pages.RootFolder.ServerRelativeUrl + "/" + pageName + ".aspx");
clientContext.Load(file, f => f.Exists);
clientContext.ExecuteQuery();
if(file.Exists)
{
file.DeleteObject();
clientContext.ExecuteQuery();
}
PublishingWeb publishingWeb = PublishingWeb.GetPublishingWeb(clientContext, web);
clientContext.Load(publishingWeb);
if (publishingWeb != null)
{
List publishingLayouts = clientContext.Site.RootWeb.Lists.GetByTitle("Master Page Gallery");
ListItemCollection allItems = publishingLayouts.GetItems(CamlQuery.CreateAllItemsQuery());
clientContext.Load(allItems, items => items.Include(item => item.DisplayName).Where(obj => obj.DisplayName == pagelayoutname));
clientContext.ExecuteQuery();
ListItem layout = allItems.Where(x => x.DisplayName == pagelayoutname).FirstOrDefault();
clientContext.Load(layout);
PublishingPageInformation publishingpageInfo = new PublishingPageInformation()
{
Name = publishingPageName,
PageLayoutListItem = layout,
};
PublishingPage publishingPage = publishingWeb.AddPublishingPage(publishingpageInfo);
publishingPage.ListItem.File.CheckIn(string.Empty, CheckinType.MajorCheckIn);
publishingPage.ListItem.File.Publish(string.Empty);
clientContext.ExecuteQuery();
}
SetSupportCaseContent(clientContext, "SupportCasesPage", url, queryurl);
}
Crear elementos de lista
public static void AddDemoDataToSupportCasesList(ClientContext ctx, List list, string title,
string status, string csr, string customerID)
{
ListItemCreationInformation itemCreateInfo = new ListItemCreationInformation();
ListItem newItem = list.AddItem(itemCreateInfo);
newItem["Title"] = title;
newItem["FTCAM_Status"] = status;
newItem["FTCAM_CSR"] = csr;
newItem["FTCAM_CustomerID"] = customerID;
newItem.Update();
ctx.ExecuteQuery();
}
Aprovisionamiento de contenido en una página de publicación (elemento web Content By Search, elemento web Editor de scripts, elemento de complemento) y publicación de la página
public static void SetSupportCaseContent(ClientContext ctx, string pageName, string url, string queryurl)
{
List pages = ctx.Web.Lists.GetByTitle("Pages");
ctx.Load(pages.RootFolder, f => f.ServerRelativeUrl);
ctx.ExecuteQuery();
Microsoft.SharePoint.Client.File file =
ctx.Web.GetFileByServerRelativeUrl(pages.RootFolder.ServerRelativeUrl + "/" + pageName + ".aspx");
ctx.Load(file);
ctx.ExecuteQuery();
file.CheckOut();
LimitedWebPartManager limitedWebPartManager = file.GetLimitedWebPartManager(PersonalizationScope.Shared);
string quicklaunchmenuFormat =
@"<div><a href='{0}/{1}'>Sample Home Page</a></div>
<br />
<div style='font-weight:bold'>CSR Dashboard</div>
<div class='cdsm_mainmenu'>
<ul>
<li><a href='{0}/CSRInfo/{1}'>My CSR Info</a></li>
<li><a href='{0}/CallQueue/{1}'>Call Queue</a></li>
<li>
<span class='collapse_arrow'></span>
<span><a href='{0}/CustomerDashboard/{1}'>Customer Dashboard</a></span>
<ul>
<li><a href='{0}/CustomerDashboard/Orders{1}'>Recent Orders</a></li>
<li><a class='current' href='#'>Support Cases</a></li>
<li><a href='{0}/CustomerDashboard/Notes{1}'>Notes</a></li>
</ul>
</li>
</ul>
</div>
<div class='cdsm_submenu'>
</div>";
string quicklaunchmenu = string.Format(quicklaunchmenuFormat, url, queryurl);
string qlwebPartXml = "<?xml version=\"1.0\" encoding=\"utf-8\"?><webParts><webPart xmlns=\"http://schemas.microsoft.com/WebPart/v3\"><metaData><type name=\"Microsoft.SharePoint.WebPartPages.ScriptEditorWebPart, Microsoft.SharePoint, Version=15.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c\" /><importErrorMessage>Cannot import this web part.</importErrorMessage></metaData><data><properties><property name=\"Content\" type=\"string\"><![CDATA[" + quicklaunchmenu + "]]></property><property name=\"ChromeType\" type=\"chrometype\">None</property></properties></data></webPart></webParts>";
WebPartDefinition qlWpd = limitedWebPartManager.ImportWebPart(qlwebPartXml);
WebPartDefinition qlWpdNew = limitedWebPartManager.AddWebPart(qlWpd.WebPart, "SupportCasesZoneLeft", 0);
ctx.Load(qlWpdNew);
//Customer Dropdown List Script web part
string dpwebPartXml = System.IO.File.ReadAllText(System.Web.Hosting.HostingEnvironment.ApplicationPhysicalPath + "Assets/CustomerDropDownlist.webpart");
WebPartDefinition dpWpd = limitedWebPartManager.ImportWebPart(dpwebPartXml);
WebPartDefinition dpWpdNew = limitedWebPartManager.AddWebPart(dpWpd.WebPart, "SupportCasesZoneTop", 0);
ctx.Load(dpWpdNew);
//Support Case CBS Info web part
string cbsInfoWebPartXml = System.IO.File.ReadAllText(System.Web.Hosting.HostingEnvironment.ApplicationPhysicalPath + "Assets/SupportCaseCBSWebPartInfo.webpart");
WebPartDefinition cbsInfoWpd = limitedWebPartManager.ImportWebPart(cbsInfoWebPartXml);
WebPartDefinition cbsInfoWpdNew = limitedWebPartManager.AddWebPart(cbsInfoWpd.WebPart, "SupportCasesZoneMiddle", 0);
ctx.Load(cbsInfoWpdNew);
//Support Case Content By Search web part
string cbswebPartXml = System.IO.File.ReadAllText(System.Web.Hosting.HostingEnvironment.ApplicationPhysicalPath + "Assets/SupportCase CBS Webpart/SupportCaseCBS.webpart");
WebPartDefinition cbsWpd = limitedWebPartManager.ImportWebPart(cbswebPartXml);
WebPartDefinition cbsWpdNew = limitedWebPartManager.AddWebPart(cbsWpd.WebPart, "SupportCasesZoneMiddle", 1);
ctx.Load(cbsWpdNew);
//Support Cases App Part
string appPartXml = System.IO.File.ReadAllText(System.Web.Hosting.HostingEnvironment.ApplicationPhysicalPath + "Assets/SupportCaseAppPart.webpart");
WebPartDefinition appPartWpd = limitedWebPartManager.ImportWebPart(appPartXml);
WebPartDefinition appPartdNew = limitedWebPartManager.AddWebPart(appPartWpd.WebPart, "SupportCasesZoneBottom", 0);
ctx.Load(appPartdNew);
//Get Host Web Query String and show support case list web part
string querywebPartXml = System.IO.File.ReadAllText(System.Web.Hosting.HostingEnvironment.ApplicationPhysicalPath + "Assets/GetHostWebQueryStringAndShowList.webpart");
WebPartDefinition queryWpd = limitedWebPartManager.ImportWebPart(querywebPartXml);
WebPartDefinition queryWpdNew = limitedWebPartManager.AddWebPart(queryWpd.WebPart, "SupportCasesZoneBottom", 1);
ctx.Load(queryWpdNew);
file.CheckIn("Data storage model", CheckinType.MajorCheckIn);
file.Publish("Data storage model");
ctx.Load(file);
ctx.ExecuteQuery();
}
- Consulte los
FillHostWebSupportCasesToThresholdmétodos yFillAppWebNotesListToThresholdde la clase SharePointService.cs para obtener más información sobre cómo implementar elementos de lista tanto en la web host como en la web del complemento.
Importante
Los mismos enfoques web de host y web de complemento que se muestran en este ejemplo se pueden aplicar a cualquier tipo de artefacto para implementarlos en la ubicación adecuada.
Adición de elementos de lista a una lista en la web host
public string FillHostWebSupportCasesToThreshold()
{
using (var clientContext = SharePointContext.CreateUserClientContextForSPHost())
{
List supportCasesList = clientContext.Web.Lists.GetByTitle("Support Cases");
ListItemCreationInformation itemCreateInfo = new ListItemCreationInformation();
for (int i = 0; i < 500; i++)
{
ListItem newItem = supportCasesList.AddItem(itemCreateInfo);
newItem["Title"] = "Wrong product received." + i.ToString();
newItem["FTCAM_Status"] = "Open";
newItem["FTCAM_CSR"] = "bjones";
newItem["FTCAM_CustomerID"] = "thresholds test";
newItem.Update();
if (i % 100 == 0)
clientContext.ExecuteQuery();
}
clientContext.ExecuteQuery();
clientContext.Load(supportCasesList, l => l.ItemCount);
clientContext.ExecuteQuery();
if(supportCasesList.ItemCount>=5000)
return "The Host Web Support Cases List has " + supportCasesList.ItemCount + " items, and exceeds the threshold.";
else
return 500 + " items have been added to the Host Web Support Cases List. " +
"There are " + (5000 - supportCasesList.ItemCount) + " items left to add.";
}
}
Adición de elementos de lista a una lista en la web de complementos
public string FillAppWebNotesListToThreshold()
{
using (var clientContext = SharePointContext.CreateUserClientContextForSPAppWeb())
{
List notesList = clientContext.Web.Lists.GetByTitle("Notes");
var itemCreateInfo = new ListItemCreationInformation();
for (int i = 0; i < 500; i++)
{
ListIgit pushientContext.ExecuteQuery();
}
clientContext.ExecuteQuery();
clientContext.Load(notesList, l => l.ItemCount);
clientContext.ExecuteQuery();
if (notesList.ItemCount >= 5000)
return "The Add-in Web Notes List has " + notesList.ItemCount + " items, and exceeds the threshold.";
else
return 500 + " items have been added to the Add-in Web Notes List. " +
"There are " + (5000-notesList.ItemCount) + " items left to add.";
}
}
Vínculos relacionados
- Páginas maestras (receta de complemento de SharePoint)
- Artículos de orientación en https://aka.ms/OfficeDevPnPGuidance
- Referencias en MSDN en https://aka.ms/OfficeDevPnPMSDN
- Vídeos en https://aka.ms/OfficeDevPnPVideos
Ejemplos de PnP
- Branding.ClientSideRendering (ejemplo de código PnP de Microsoft 365)
- Branding.ApplyBranding (ejemplo de código PnP de Microsoft 365)
- Ejemplos y contenido en https://github.com/SharePoint/PnP
Se aplica a
- Multiinquilino de Microsoft 365 (MT)
- Microsoft 365 Dedicado (D) parcialmente
- SharePoint 2013 local parcial
Los modelos para Office 365 dedicado y local son idénticos a las técnicas del modelo de complemento de SharePoint, pero existen algunas diferencias en las posibles tecnologías que se pueden usar.