Ersetzen von SharePoint-Inhaltstypen und Websitespalten in Farmlösungen
In diesem Artikel wird der Transformationsprozess beschrieben, der beim Ersetzen von Inhaltstypen und Websitespalten, beim Hinzufügen von Websitespalten zu neuen Inhaltstypen und beim anschließenden Ersetzen vorheriger Inhaltstypen durch neue Inhaltstypen mithilfe des clientseitigen SharePoint-Objektmodells (CSOM) verwendet werden soll.
Wichtig
Farm-Lösungen können nicht zu SharePoint Online migriert werden. Durch Anwenden der in diesem Artikel beschriebenen Techniken und Code können Sie eine neue Lösung erstellen, die aktualisierte Inhaltstypen und Websitespalten verwendet und ähnliche Funktionen wie Ihre Farmlösungen oder deklarative Sandboxlösungen bereitstellt. Die neue Lösung kann dann in SharePoint Online bereitgestellt werden.
Der Code in diesem Artikel erfordert zusätzlichen Code für die Bereitstellung einer vollständig funktionierenden Lösung. Beispielsweise wird in diesem Artikel nicht erläutert, wie Sie sich bei Office 365 authentifizieren, wie die erforderliche Ausnahmenbehandlung implementiert wird und so weiter. Weitere Codebeispiele, finden Sie unter Office 365 Developer Patterns and Practices Project.
Hinweis
Der Code in diesem Artikel wird wie besehen und ohne jegliche Garantie zur Verfügung gestellt, gleich ob ausdrücklich oder konkludent, einschließlich jedweder stillschweigenden Gewährleistung der Eignung für einen bestimmten Zweck, Marktgängigkeit oder Nichtverletzung von Rechten.
So ersetzen Sie Inhaltstypen und Websitespalten mithilfe von CSOM:
Erstellen Sie einen neuen Inhaltstyp.
Erstellen Sie eine neue Websitespalte (auch als Feld bezeichnet).
Fügen Sie dem neuen Inhaltstyp die neue Websitespalte hinzu.
Ersetzen Sie alte Inhaltstypverweise durch den neuen Inhaltstyp.
Im folgenden Code zeigt Main die Reihenfolge der Vorgänge an, die ausgeführt werden müssen, um Inhaltstypen und Websitespalten mithilfe von CSOM zu ersetzen.
static void Main(string[] args)
{
using (var clientContext = new ClientContext("http://contoso.sharepoint.com"))
{
Web web = clientContext.Web;
CreateContentType(clientContext, web);
CreateSiteColumn(clientContext, web);
AddSiteColumnToContentType(clientContext, web);
// Replace the old content type with the new content type.
ReplaceContentType(clientContext, web);
}
}
Im folgenden Code ruft GetContentTypeByName einen Inhaltstyp von der aktuellen Website ab:
Verwenden der Web.ContentTypes-Eigenschaft zum Abrufen einer ContentTypeCollection, bei der es sich um eine Sammlung von Inhaltstypen auf der aktuellen Website handelt.
Suchen und anschließendes Zurückgeben eines Inhaltstyps von der Website, indem der Name des Websiteinhaltstyps mit dem Namen des vorhandenen Inhaltstyps abgegleicht wird, der vom Parameter name übermittelt wird.
private static ContentType GetContentTypeByName(ClientContext cc, Web web, string name)
{
ContentTypeCollection contentTypes = web.ContentTypes;
cc.Load(contentTypes);
cc.ExecuteQuery();
return contentTypes.FirstOrDefault(o => o.Name == name);
}
Erstellen eines neuen Inhaltstyps
Im folgenden Code erstellt CreateContentType einen neuen Inhaltstyp wie folgt:
Erstellen sie eine Konstante namens contentTypeName , um den Namen des Inhaltstyps zu speichern. Der Name des neuen Inhaltstyps wird auf den Namen des vorherigen Inhaltstyps festgelegt.
Aufrufen von GetContentTypeByName , um einen übereinstimmenden Inhaltstyp auf der Website zu finden.
Wenn der Inhaltstyp bereits vorhanden ist, ist keine weitere Aktion erforderlich, und die Steuerung wird an Main zurückgegeben, wenn die Rückgabe aufgerufen wird.
Wenn der Inhaltstyp nicht vorhanden ist, werden Inhaltstypeigenschaften mithilfe eines ContentTypeCreationInformation-Objekts namens newCt festgelegt.
Die neue Inhaltstyp-ID wird newCt.Id mithilfe der Inhaltstyp-ID des Basisdokuments 0x0101 zugewiesen. Weitere Informationen finden Sie unter Basisinhaltstyphierarchie.
Hinzufügen des neuen Inhaltstyps mithilfe von ContentTypeCollection.Add.
private static void CreateContentType(ClientContext cc, Web web)
{
// The new content type will be created using this name.
const string contentTypeName = "ContosoDocumentByCSOM";
// Determine whether the content type already exists.
var contentType = GetContentTypeByName(cc, web, contentTypeName);
// The content type exists already. No further action required.
if (contentType != null) return;
// Create the content type using the ContentTypeInformation object.
ContentTypeCreationInformation newCt = new ContentTypeCreationInformation();
newCt.Name = "ContosoDocumentByCSOM";
// Create the new content type based on the out-of-the-box document (0x0101) and assign the ID to the new content type.
newCt.Id = "0x0101009189AB5D3D2647B580F011DA2F356FB2";
// Assign the content type to a specific content type group.
newCt.Group = "Contoso Content Types";
ContentType myContentType = web.ContentTypes.Add(newCt);
cc.ExecuteQuery();
}
Erstellen einer neuen Websitespalte
Im folgenden Code erstellt CreateSiteColumn eine neue Websitespalte wie folgt:
Erstellen sie eine Konstante namens fieldName , um den Namen des Felds zu speichern. Der Name des neuen Felds wird auf den Namen des vorherigen Felds festgelegt.
Abrufen der auf der Website definierten Websitespalten mithilfe der Web.Fields-Eigenschaft .
Suchen eines übereinstimmenden Felds auf der Website durch Abgleichen der Feldnamen auf der Website mit fieldName. Wenn das Feld bereits vorhanden ist, ist keine weitere Aktion erforderlich, und die Steuerung wird an Main zurückgegeben, wenn die Rückgabe aufgerufen wird. Wenn das Feld nicht vorhanden ist, wird FieldAsXML eine CAML-Zeichenfolge zugewiesen, die das Feldschema angibt, und dann wird das Feld mit FieldCollection.AddFieldAsXml erstellt.
private static void CreateSiteColumn(ClientContext cc, Web web)
{
// The new field will be created using this name.
const string fieldName = "ContosoStringCSOM";
// Load the list of fields on the site.
FieldCollection fields = web.Fields;
cc.Load(fields);
cc.ExecuteQuery();
// Check fields on the site for a match.
var fieldExists = fields.Any(f => f.InternalName == fieldName);
// The field exists already. No further action required.
if (fieldExists) return;
// Field does not exist, so create the new field.
string FieldAsXML = @"<Field ID='{CB8E24F6-E1EE-4482-877B-19A51B4BE319}'
Name='" + fieldName + @"'
DisplayName='Contoso String by CSOM'
Type='Text'
Hidden='False'
Group='Contoso Site Columns'
Description='Contoso Text Field' />";
Field fld = fields.AddFieldAsXml(FieldAsXML, true, AddFieldOptions.DefaultValue);
cc.ExecuteQuery();
}
Hinzufügen der neuen Websitespalte zum neuen Inhaltstyp
Im folgenden Code erstellt AddSiteColumnToContentType eine Verbindung zwischen dem Inhaltstyp und dem Feld durch:
Laden sie den Inhaltstyp, und dann verweist das Feld mithilfe der ContentType.FieldLinks-Eigenschaft auf diesen Inhaltstyp.
Das Feld wird geladen.
Bestimmen, ob der Inhaltstyp auf das Feld verweist, indem contentType.FieldLinks.Any(f => f.Name == fieldName) verwendet wird, um mit dem Feldnamen abzugleichen.
Wenn der Inhaltstyp bereits auf das Feld verweist, ist keine weitere Aktion erforderlich, und die Steuerung wird an Main zurückgegeben, wenn die Rückgabe aufgerufen wird. Wenn der Inhaltstyp nicht auf das Feld verweist, werden Feldverweiseigenschaften für ein FieldLinkCreationInformation-Objekt festgelegt.
Hinzufügen des FieldLinkCreationInformation-Objekts zur ContentType.FieldLinks-Eigenschaft .
private static void AddSiteColumnToContentType(ClientContext cc, Web web)
{
// The name of the content type.
const string contentTypeName = "ContosoDocumentByCSOM";
// The field name.
const string fieldName = "ContosoStringCSOM";
// Load the content type.
var contentType = GetContentTypeByName(cc, web, contentTypeName);
if (contentType == null) return; // content type was not found
// Load field references in the content type.
cc.Load(contentType.FieldLinks);
cc.ExecuteQuery();
// Load the new field.
Field fld = web.Fields.GetByInternalNameOrTitle(fieldName);
cc.Load(fld);
cc.ExecuteQuery();
// Determine whether the content type refers to the field.
var hasFieldConnected = contentType.FieldLinks.Any(f => f.Name == fieldName);
// A reference exists already, no further action is required.
if (hasFieldConnected) return;
// The reference does not exist, so we have to create the reference.
FieldLinkCreationInformation link = new FieldLinkCreationInformation();
link.Field = fld;
contentType.FieldLinks.Add(link);
contentType.Update(true);
cc.ExecuteQuery();
}
Ersetzen Sie alte Inhaltstypverweise durch den neuen Inhaltstyp.
Im folgenden Code überprüft ReplaceContentType alle Elemente in allen Bibliotheken auf Inhalt, der auf den alten Inhaltstyp verweist, und ersetzt diese Verweise dann durch den neuen Inhaltstyp (ContosoDocumentByCSOM):
Zuweisen der alten Inhaltstyp-ID zu einer Konstante.
Abrufen des neuen Inhaltstyps mithilfe von GetContentTypeByName.
Abrufen aller Listen auf der Website mithilfe von Web.Lists.
Laden aller Listen auf der Website und aller Inhaltstypen in jeder Liste mithilfe von cc.Load(lists, l => l.Include(list = list => list. ContentTypes).
Durchsuchen Sie für jede zurückgegebene Liste mithilfe von list die Inhaltstypen der Liste, um einen Inhaltstyp mit der alten Inhaltstyp-ID abzugleichen. ContentTypes.Any(c => c.StringId.StartsWith(oldContentTypeId))). Wenn eine Übereinstimmung gefunden wird, wird die Liste mit dem alten Inhaltstyp zu listsWithContentType hinzugefügt.
Für jede Liste in listsWithContentType:
Bestimmt, ob der neue Inhaltstyp an die Liste angefügt ist. Wenn der neue Inhaltstyp nicht an die Liste angefügt ist, verwenden Sie ContentTypeCollection.AddExistingContentType , um den neuen Inhaltstyp an die Liste anzufügen.
Abrufen aller Listenelemente in der Liste.
Abrufen der Inhaltstyp-ID des Listenelements für jedes Listenelement. Bestimmen Sie, ob die Inhaltstyp-ID des Listenelements der alten Inhaltstyp-ID entspricht. Wenn die Inhaltstyp-IDs nicht gleich sind, fahren Sie mit dem nächsten Listenelement fort. Wenn die Inhaltstyp-IDs gleich sind, verwenden Sie ContentType.StringId , um dem Listenelement die neue Inhaltstyp-ID zuzuweisen.
Hinweis
Der alte Inhaltstyp ist noch in der Liste enthalten, wird aber nicht mehr verwendet. Sie können jetzt den alten Inhaltstyp aus den Listen löschen und dann zurückziehen. In diesem Artikel wird beschrieben, wie Sie nur Dokumentinhaltstypen ersetzen. Wenn Sie Inhaltstypen in Seitenlayouts ersetzen, stellen Sie sicher, dass Sie die AssociatedContentType-Eigenschaft für jedes Seitenlayout in der Websitesammlung aktualisieren.
private static void ReplaceContentType(ClientContext cc, Web web)
{
// The old content type.
const string oldContentTypeId = "0x010100C32DDAB6381C44868DCD5ADC4A5307D6";
// The new content type name.
const string newContentTypeName = "ContosoDocumentByCSOM";
// Get the new content type and lists on the site.
ContentType newContentType = GetContentTypeByName(cc, web, newContentTypeName);
ListCollection lists = web.Lists;
// Load the new content type and the content types on all lists on the site.
cc.Load(newContentType);
cc.Load(lists,
l => l.Include(list => list.ContentTypes));
cc.ExecuteQuery();
var listsWithContentType = new List<List>();
foreach (List list in lists)
{
bool hasOldContentType = list.ContentTypes.Any(c => c.StringId.StartsWith(oldContentTypeId));
if (hasOldContentType)
{
listsWithContentType.Add(list);
}
}
foreach (List list in listsWithContentType)
{
// Determine whether the new content type is already attached to the list.
var listHasContentTypeAttached = list.ContentTypes.Any(c => c.Name == newContentTypeName);
if (!listHasContentTypeAttached)
{
// Attach content type to list.
list.ContentTypes.AddExistingContentType(newContentType);
cc.ExecuteQuery();
}
// Get all list items.
CamlQuery query = CamlQuery.CreateAllItemsQuery();
ListItemCollection items = list.GetItems(query);
cc.Load(items);
cc.ExecuteQuery();
// For each list item, determine whether the old content type is used, and then update to the new content type.
foreach (ListItem listItem in items)
{
// Get the current content type for this list item.
var currentContentTypeId = listItem["ContentTypeId"] + "";
var isOldContentTypeAssigned = currentContentTypeId.StartsWith(oldContentTypeId);
// This item does not use the old content type - skip to next list item.
if (!isOldContentTypeAssigned) continue;
// Update the list item content type to the new content type.
listItem["ContentTypeId"] = newContentType.StringId; // new content type Id;
listItem.Update();
}
// Save all changes.
cc.ExecuteQuery();
}
}