protected WebDefinition GetLocalizedWebDefinition(WebDefinition definition) { var localeIds = Rnd.LocaleIds(); foreach (var localeId in localeIds) { definition.TitleResource.Add(new ValueForUICulture { CultureId = localeId, Value = string.Format("LocalizedTitle_{0}", localeId) }); definition.DescriptionResource.Add(new ValueForUICulture { CultureId = localeId, Value = string.Format("LocalizedDescription_{0}", localeId) }); } return(definition); }
protected virtual SPWebTemplate LookupCustomWebTemplateFromWeb(SPWeb web, WebDefinition definition) { // smain lookup by the internal name var result = web.GetAvailableWebTemplates(definition.LCID) .OfType <SPWebTemplate>() .FirstOrDefault(tmpl => tmpl.IsCustomTemplate && !string.IsNullOrEmpty(tmpl.Name) && tmpl.Name.ToUpper() == definition.CustomWebTemplate.ToUpper()); if (result != null) { return(result); } // one more try by title return(web.GetAvailableWebTemplates(definition.LCID) .OfType <SPWebTemplate>() .FirstOrDefault(tmpl => tmpl.IsCustomTemplate && !string.IsNullOrEmpty(tmpl.Title) && tmpl.Title.ToUpper() == definition.CustomWebTemplate.ToUpper())); }
private void CreateWeb(object modelHost, SPWeb parentWeb, WebDefinition webModel) { using (var web = GetOrCreateWeb(parentWeb, webModel, true)) { web.Title = webModel.Title; web.Description = webModel.Description; web.Locale = new CultureInfo((int)webModel.LCID); InvokeOnModelEvent(this, new ModelEventArgs { CurrentModelNode = null, Model = null, EventType = ModelEventType.OnProvisioned, Object = web, ObjectType = typeof(SPWeb), ObjectDefinition = webModel, ModelHost = modelHost }); web.Update(); } }
public override ModelNode ReverseSingleHost(object reverseHost, ReverseOptions options) { TraceService.Information((int)ReverseLogEventId.ReverseSingleHostStart, "Processing single web host start"); var item = (reverseHost as WebReverseHost).HostWeb; var def = new WebDefinition(); if (!item.IsPropertyAvailable("Title")) { item.Context.Load(item); item.Context.ExecuteQueryWithTrace(); } def.Title = item.Title; def.Description = item.Description; def.WebTemplate = item.WebTemplate; if (item.Configuration > -1) { def.WebTemplate = string.Format("{0}#{1}", item.WebTemplate, item.Configuration); } // always web relative def.Url = item.Url.Split('/').Last(); TraceService.Information((int)ReverseLogEventId.ReverseSingleHostStart, "Processing single web host end"); return(new WebModelNode { Options = { RequireSelfProcessing = true }, Value = def }); }
public void CanDeploySimpleBreakRoleInheritance_OnWeb() { var privateProjectWebDef = new WebDefinition { Title = "Private project", Url = "private-project", WebTemplate = BuiltInWebTemplates.Collaboration.TeamSite }; var privateProjectWebBreakRoleInheritance = new BreakRoleInheritanceDefinition { CopyRoleAssignments = false }; var privateSecurityGroupMembers = new SecurityGroupDefinition { Name = "Private Project Group Members" }; var privateSecurityGroupViewers = new SecurityGroupDefinition { Name = "Private Project Group Viewers" }; // site model with the groups var siteModel = SPMeta2Model.NewSiteModel(site => { site.AddSecurityGroup(privateSecurityGroupMembers); site.AddSecurityGroup(privateSecurityGroupViewers); }); // web model var webModel = SPMeta2Model.NewWebModel(web => { web.AddWeb(privateProjectWebDef, publicProjectWeb => { publicProjectWeb.AddBreakRoleInheritance(privateProjectWebBreakRoleInheritance, privateProjectResetWeb => { // privateProjectResetWeb is your web but after breaking role inheritance // link group with roles by SecurityRoleType / SecurityRoleName // use BuiltInSecurityRoleTypes or BuiltInSecurityRoleNames // add group with contributor permission privateProjectResetWeb.AddSecurityGroupLink(privateSecurityGroupMembers, group => { group.AddSecurityRoleLink(new SecurityRoleLinkDefinition { SecurityRoleType = BuiltInSecurityRoleTypes.Contributor }); }); // add group with reader permission privateProjectResetWeb.AddSecurityGroupLink(privateSecurityGroupViewers, group => { group.AddSecurityRoleLink(new SecurityRoleLinkDefinition { SecurityRoleType = BuiltInSecurityRoleTypes.Reader }); }); }); }); }); // deploy site model with groups, and then web model with the rest DeployModel(siteModel); DeployModel(webModel); }
protected LookupFieldEnvironment GetLookupFieldEnvironment(Action <LookupFieldEnvironment> action, WebDefinition destinationWebDefinition) { var result = new LookupFieldEnvironment(); var dataList = ModelGeneratorService.GetRandomDefinition <ListDefinition>(def => { def.TemplateType = BuiltInListTemplateTypeId.GenericList; }); var masterList = ModelGeneratorService.GetRandomDefinition <ListDefinition>(def => { def.TemplateType = BuiltInListTemplateTypeId.GenericList; }); var lookupField = GetSingleSelectLookupDefinition(def => { def.Indexed = false; //def.LookupListTitle = dataList.Title; }); ModelNode childListNode = null; var siteModel = SPMeta2Model.NewSiteModel(site => { site.AddField(lookupField); }); var webModel = SPMeta2Model.NewWebModel(web => { web.AddField(lookupField); }); var childWebModel = SPMeta2Model.NewWebModel(web => { if (destinationWebDefinition != null) { web.AddWeb(destinationWebDefinition, subWeb => { subWeb.AddList(dataList, list => { childListNode = list; list .AddRandomListItem() .AddRandomListItem() .AddRandomListItem(); }); }); } else { web.AddList(dataList, list => { childListNode = list; list .AddRandomListItem() .AddRandomListItem() .AddRandomListItem(); }); } }); var masterWebModel = SPMeta2Model.NewWebModel(web => { web.AddList(masterList, list => { list.AddListFieldLink(lookupField); }); }); result.LookupField = lookupField; result.ChildList = dataList; result.ChildListNode = childListNode; result.ChildListModel = childWebModel; result.MasterList = masterList; result.MasterListModel = masterWebModel; result.SiteModel = siteModel; result.WebModel = webModel; if (action != null) { action(result); } return(result); }
/// <summary> /// Creates a new instance of the ModelNode adding web model provided. /// If RequireSelfProcessing set as 'true', then web model is going to be processed and pushed by SPMeta2 API. /// Use action to get access to the "web model node" and construct model tree. /// </summary> /// <param name="webDefinition"></param> /// <param name="action"></param> /// <returns></returns> public static WebModelNode NewWebModel(WebDefinition webDefinition, Action <WebModelNode> action) { return(NewModelNode <WebDefinition, WebModelNode>(webDefinition, action)); }
private static void CreateOrUpdateSubSite(SPSite spSite, string siteName, int itemId, SPFieldUserValue director, SPFieldUserValueCollection members) { const string securityGroupNameFormat = "{0} - {1}"; string siteUrl = "user-web-" + itemId; var newWebDef = new WebDefinition { Title = siteName, Description = "", Url = siteUrl, WebTemplate = BuiltInWebTemplates.Collaboration.TeamSite }; var newWebBreakRoleInheritance = new BreakRoleInheritanceDefinition { CopyRoleAssignments = false }; var ownersGroup = new SecurityGroupDefinition { Name = string.Format(securityGroupNameFormat, siteName, Constants.SecurityGroups.OfficeOwners), Owner = director.LoginName }; var membersGroup = new SecurityGroupDefinition { Name = string.Format(securityGroupNameFormat, siteName, Constants.SecurityGroups.OfficeMembers), Owner = director.LoginName }; var visitorsGroup = new SecurityGroupDefinition { Name = string.Format(securityGroupNameFormat, siteName, Constants.SecurityGroups.OfficeVisitors), Owner = director.LoginName }; // site model with the groups var siteModel = SPMeta2Model.NewSiteModel(site => { site.AddSecurityGroup(ownersGroup); site.AddSecurityGroup(membersGroup); site.AddSecurityGroup(visitorsGroup); }); // web model var webModel = SPMeta2Model.NewWebModel(web => { web.AddWeb(newWebDef, publicProjectWeb => { publicProjectWeb.AddBreakRoleInheritance(newWebBreakRoleInheritance, newResetWeb => { // add group with owner permission newResetWeb.AddSecurityGroupLink(ownersGroup, group => { group.AddSecurityRoleLink(new SecurityRoleLinkDefinition { SecurityRoleType = BuiltInSecurityRoleTypes.Administrator }); }); // add group with contributor permission newResetWeb.AddSecurityGroupLink(membersGroup, group => { group.AddSecurityRoleLink(new SecurityRoleLinkDefinition { SecurityRoleType = BuiltInSecurityRoleTypes.Contributor }); }); // add group with reader permission newResetWeb.AddSecurityGroupLink(visitorsGroup, group => { group.AddSecurityRoleLink(new SecurityRoleLinkDefinition { SecurityRoleType = BuiltInSecurityRoleTypes.Reader }); }); }); }); }); var csomProvisionService = new SSOMProvisionService(); csomProvisionService.DeploySiteModel(spSite, siteModel); csomProvisionService.DeployWebModel(spSite.RootWeb, webModel); SPWeb existWeb = spSite.AllWebs.SingleOrDefault(w => w.Url.Contains(siteUrl)); if (existWeb == null) { return; } // add users to members group SPGroup spOwnerGroup = existWeb.SiteGroups.Cast <SPGroup>().FirstOrDefault(siteGroup => siteGroup.Name == string.Format(securityGroupNameFormat, siteName, Constants.SecurityGroups.OfficeOwners)); if (spOwnerGroup != null) { spOwnerGroup.AddUser(director.User); } SPGroup spMembersGroup = existWeb.SiteGroups.Cast <SPGroup>().FirstOrDefault(siteGroup => siteGroup.Name == string.Format(securityGroupNameFormat, siteName, Constants.SecurityGroups.OfficeMembers)); if (spMembersGroup != null) { foreach (SPFieldUserValue member in members) { spMembersGroup.AddUser(member.User); } } }
public static ModelNode AddHostWeb(this ModelNode model, WebDefinition definition) { return(AddHostWeb(model, definition, null)); }
private static void MapProperties(SPWeb web, WebDefinition webModel) { // temporarily switch culture to allow setting of the properties Title and Description for multi-language scenarios CultureUtils.WithCulture(web.UICulture, () => { if (!string.IsNullOrEmpty(webModel.Title)) { web.Title = webModel.Title; } if (!string.IsNullOrEmpty(webModel.Description)) { web.Description = webModel.Description; } }); if (webModel.LCID > 0) { web.Locale = new CultureInfo((int)webModel.LCID); } if (!string.IsNullOrEmpty(webModel.AlternateCssUrl)) { web.AlternateCssUrl = webModel.AlternateCssUrl; } if (!string.IsNullOrEmpty(webModel.SiteLogoUrl)) { web.SiteLogoUrl = webModel.SiteLogoUrl; } #if !NET35 if (webModel.IndexedPropertyKeys.Any()) { foreach (var indexedProperty in webModel.IndexedPropertyKeys) { // indexed prop should exist in the prop bag // otherwise it won't be saved by SharePoint (ILSpy / Refletor to see the logic) // http://rwcchen.blogspot.com.au/2014/06/sharepoint-2013-indexed-property-keys.html var propName = indexedProperty.Name; var propValue = string.IsNullOrEmpty(indexedProperty.Value) ? string.Empty : indexedProperty.Value; if (web.AllProperties.ContainsKey(propName)) { web.AllProperties[propName] = propValue; } else { web.AllProperties.Add(propName, propValue); } if (!web.IndexedPropertyKeys.Contains(propName)) { web.IndexedPropertyKeys.Add(propName); } } } #endif }
public static TModelNode AddWeb <TModelNode>(this TModelNode model, WebDefinition definition, Action <WebModelNode> action) where TModelNode : ModelNode, IWebHostModelNode, new() { return(model.AddTypedDefinitionNode(definition, action)); }
protected string GetCurrentWebUrl(ClientRuntimeContext context, Web parentWeb, WebDefinition webModel) { var fullUrl = context.Url.ToLower(); var serverUrl = fullUrl.EndsWith(parentWeb.ServerRelativeUrl.ToLower()) ? fullUrl.Substring(0, fullUrl.LastIndexOf(parentWeb.ServerRelativeUrl.ToLower())) : fullUrl; var isParentWebRootUrl = parentWeb.ServerRelativeUrl.Trim('/').Length == 0; var currentWebUrl = serverUrl + (isParentWebRootUrl ? String.Empty : parentWeb.ServerRelativeUrl + (webModel.Url.StartsWith("/") ? webModel.Url : "/" + webModel.Url)); return(currentWebUrl.ToLower()); }
protected string GetCurrentWebUrl(ClientRuntimeContext context, Web parentWeb, WebDefinition webModel) { var result = UrlUtility.CombineUrl(parentWeb.ServerRelativeUrl, webModel.Url); return(result.ToLower()); }
/// <summary> /// This method is used to capture requirements of WebDefinition complex type For Sub Web Collection. /// </summary> /// <param name="web">The WebDefinition complex type.</param> private void ValidateWebDefinitionForSubWebCollection(WebDefinition web) { // Proxy handles operation's SoapIn and SoapOut, if the server didn't respond the SoapOut message for the operation, Proxy will fail. // Proxy didn't fail now, that indicates server responds corresponding SoapOut message for the operation.So the requirement be captured. // Verify MS-WEBSS requirement: MS-WEBSS_R691 Site.CaptureRequirementIfAreEqual<ValidationResult>( ValidationResult.Success, SchemaValidation.ValidationResult, 691, @"[In WebDefinition] This type[WebDefinition] is defined as follows: <s:complexType name=""WebDefinition""> <s:attribute name=""Title"" type=""s:string"" use=""required"" /> <s:attribute name=""Url"" type=""s:string"" use=""required"" /> <s:attribute name=""Description"" type=""s:string"" /> <s:attribute name=""Language"" type=""s:string"" /> <s:attribute name=""Theme"" type=""s:string"" /> <s:attribute name=""FarmId"" type=""core:UniqueIdentifierWithBraces"" /> <s:attribute name=""Id"" type=""core:UniqueIdentifierWithBraces"" /> <s:attribute name=""ExcludeFromOfflineClient"" type=""core:TRUEFALSE"" /> <s:attribute name=""CellStorageWebServiceEnabled"" type=""core:TRUEFALSE"" /> <s:attribute name=""AlternateUrls"" type=""s:string"" /> </s:complexType>"); }
/// <summary> /// This method is used to capture requirements of WebDefinition complex type. /// </summary> /// <param name="web">The WebDefinition complex type.</param> private void ValidateWebDefinition(WebDefinition web) { // Proxy handles operation's SoapIn and SoapOut, if the server didn't respond the SoapOut message for the operation, Proxy will fail. // Proxy didn't fail now, that indicates server responds corresponding SoapOut message for the operation.So the requirement be captured. // Verify MS-WEBSS requirement: MS-WEBSS_R691 Site.CaptureRequirementIfAreEqual<ValidationResult>( ValidationResult.Success, SchemaValidation.ValidationResult, 691, @"[In WebDefinition] This type[WebDefinition] is defined as follows: <s:complexType name=""WebDefinition""> <s:attribute name=""Title"" type=""s:string"" use=""required"" /> <s:attribute name=""Url"" type=""s:string"" use=""required"" /> <s:attribute name=""Description"" type=""s:string"" /> <s:attribute name=""Language"" type=""s:string"" /> <s:attribute name=""Theme"" type=""s:string"" /> <s:attribute name=""FarmId"" type=""core:UniqueIdentifierWithBraces"" /> <s:attribute name=""Id"" type=""core:UniqueIdentifierWithBraces"" /> <s:attribute name=""ExcludeFromOfflineClient"" type=""core:TRUEFALSE"" /> <s:attribute name=""CellStorageWebServiceEnabled"" type=""core:TRUEFALSE"" /> <s:attribute name=""AlternateUrls"" type=""s:string"" /> </s:complexType>"); // Verify MS-WEBSS requirement: MS-WEBSS_R1092 // COMMENT: When the SUT product is Windows SharePoint Services 3.0, if the // Id attribute of the returned WebDefinition is null or empty, which means the Id // attribute is not returned in Windows SharePoint Services 3.0, then the following // requirement can be captured. if (Common.IsRequirementEnabled(1092, this.Site)) { Site.CaptureRequirementIfIsTrue( !string.IsNullOrEmpty(web.FarmId), 1092, @"[In Appendix B: Product Behavior]Implementation does support this method [GetWeb]. (<2> Section 2.2.4.2: This attribute is returned in Microsoft SharePoint Foundation 2010 and above follow this behavior.)"); } // Verify MS-WEBSS requirement: MS-WEBSS_R1093 // COMMENT: When the SUT product is Windows SharePoint Services 3.0, if the // ExcludeFromOfflineClient attribute of the returned WebDefinition is null or empty, // which means the ExcludeFromOfflineClient attribute is not returned in Windows // SharePoint Services 3.0, then the following requirement can be captured. if (Common.IsRequirementEnabled(1093, this.Site)) { Site.CaptureRequirementIfIsTrue( !string.IsNullOrEmpty(web.Id), 1093, @"[In Appendix B: Product Behavior]Implementation does support this method [GetWeb]. (<3> Section 2.2.4.2: This attribute is returned in Microsoft SharePoint Foundation 2010 and above follow this behavior.)"); } // Verify MS-WEBSS requirement: MS-WEBSS_R1094 // COMMENT: When the SUT product is Windows SharePoint Services 3.0, if the // CellStorageWebServiceEnabled attribute of the returned WebDefinition is null or // empty, which means the CellStorageWebServiceEnabled attribute is not returned // in Windows SharePoint Services 3.0, then the following requirement can be // captured. if (Common.IsRequirementEnabled(1094, this.Site)) { Site.CaptureRequirementIfIsTrue( !string.IsNullOrEmpty(web.ExcludeFromOfflineClient), 1094, @"[In Appendix B: Product Behavior]Implementation does support this method [GetWeb]. (<4> Section 2.2.4.2: This attribute is returned in Microsoft SharePoint Foundation 2010 and above follow this behavior.)"); } // Verify MS-WEBSS requirement: MS-WEBSS_R1095 // COMMENT: When the SUT product is Windows SharePoint Services 3.0, if the // AlternateUrls attribute of the returned WebDefinition is null or empty, which means // the AlternateUrls attribute is not returned in Windows SharePoint Services 3.0, // then the following requirement can be captured. if (Common.IsRequirementEnabled(1095, this.Site)) { Site.CaptureRequirementIfIsTrue( !string.IsNullOrEmpty(web.CellStorageWebServiceEnabled), 1095, @"[In Appendix B: Product Behavior]Implementation does support this method [GetWeb]. (<5> Section 2.2.4.2: This attribute is returned in Microsoft SharePoint Foundation 2010 and above follow this behavior.)"); } // Verify MS-WEBSS requirement: MS-WEBSS_R1096 // COMMENT: When the SUT product is Windows SharePoint Services 3.0, if the // AlternateUrls attribute of the returned WebDefinition is null or empty, which means // the AlternateUrls attribute is not returned in Windows SharePoint Services 3.0, // then the following requirement can be captured. if (Common.IsRequirementEnabled(1096, this.Site)) { Site.CaptureRequirementIfIsTrue( !string.IsNullOrEmpty(web.AlternateUrls), 1096, @"[In Appendix B: Product Behavior]Implementation does support this method [GetWeb]. (<6> Section 2.2.4.2: This attribute is returned in Microsoft SharePoint Foundation 2010 and above follow this behavior.)"); } }
public static TModelNode AddHostWeb <TModelNode>(this TModelNode model, WebDefinition definition) where TModelNode : ModelNode, IWebHostModelNode, new() { return(AddHostWeb(model, definition, null)); }
protected SPWeb GetOrCreateWeb(SPWeb parentWeb, WebDefinition webModel, bool updateProperties) { var webUrl = webModel.Url; var webDescription = string.IsNullOrEmpty(webModel.Description) ? String.Empty : webModel.Description; // Enhance web provision - handle '/' slash #620 // https://github.com/SubPointSolutions/spmeta2/issues/620 webUrl = UrlUtility.RemoveStartingSlash(webUrl); var currentWeb = GetWeb(parentWeb, webModel); if (!currentWeb.Exists) { TraceService.Information((int)LogEventId.ModelProvisionProcessingNewObject, "Processing new web"); InvokeOnModelEvent(this, new ModelEventArgs { CurrentModelNode = null, Model = null, EventType = ModelEventType.OnProvisioning, Object = null, ObjectType = typeof(SPWeb), ObjectDefinition = webModel, ModelHost = webModel }); // custom web template handling // based on pull request Implematation for CustomWebTemplate included #612 by @andreasblueher if (string.IsNullOrEmpty(webModel.CustomWebTemplate)) { currentWeb = parentWeb.Webs.Add(webUrl, webModel.Title, webDescription, webModel.LCID, webModel.WebTemplate, webModel.UseUniquePermission, webModel.ConvertIfThere); } else { var customWebTemplate = LookupCustomWebTemplate(parentWeb, webModel); if (customWebTemplate == null) { throw new SPMeta2ModelDeploymentException("Couldn't find custom web template: " + webModel.CustomWebTemplate); } currentWeb = parentWeb.Webs.Add(webUrl, webModel.Title, webModel.Description, webModel.LCID, customWebTemplate, webModel.UseUniquePermission, webModel.ConvertIfThere); } MapProperties(currentWeb, webModel); ProcessLocalization(currentWeb, webModel); } else { if (updateProperties) { TraceService.Information((int)LogEventId.ModelProvisionProcessingExistingObject, "Current web is not null. Updating Title/Description."); MapProperties(currentWeb, webModel); ProcessLocalization(currentWeb, webModel); InvokeOnModelEvent(this, new ModelEventArgs { CurrentModelNode = null, Model = null, EventType = ModelEventType.OnProvisioning, Object = currentWeb, ObjectType = typeof(SPWeb), ObjectDefinition = webModel, ModelHost = webModel }); TraceService.Verbose((int)LogEventId.ModelProvisionCoreCall, "currentWeb.Update()"); currentWeb.Update(); } } return(currentWeb); }
public static TModelNode AddHostWeb <TModelNode>(this TModelNode model, WebDefinition definition, Action <WebModelNode> action) where TModelNode : ModelNode, IWebHostModelNode, new() { return(model.AddTypedDefinitionNodeWithOptions(definition, action, ModelNodeOptions.New().NoSelfProcessing())); }
public static ModelNode AddWeb(this ModelNode model, WebDefinition definition, Action <ModelNode> action) { return(model.AddDefinitionNode(definition, action)); }
/// <summary> /// Creates a new instance of the ModelNode adding web model provided. /// If RequireSelfProcessing set as 'true', then web model is going to be processed and pushed by SPMeta2 API. /// </summary> /// <param name="webDefinition"></param> /// <returns></returns> public static WebModelNode NewWebModel(WebDefinition webDefinition) { return(NewWebModel(webDefinition, null)); }
public static ModelNode AddHostWeb(this ModelNode model, WebDefinition definition, Action <ModelNode> action) { return(model.AddDefinitionNodeWithOptions(definition, action, ModelNodeOptions.New().NoSelfProcessing())); }
private static void MapProperties(Web web, WebDefinition webModel) { if (!string.IsNullOrEmpty(webModel.Title)) { web.Title = webModel.Title; } if (!string.IsNullOrEmpty(webModel.Description)) { web.Description = webModel.Description; } var supportedRuntime = ReflectionUtils.HasProperty(web, "AlternateCssUrl") && ReflectionUtils.HasProperty(web, "SiteLogoUrl"); if (supportedRuntime) { var context = web.Context; if (!string.IsNullOrEmpty(webModel.AlternateCssUrl)) { context.AddQuery(new ClientActionInvokeMethod(web, "AlternateCssUrl", new object[] { webModel.AlternateCssUrl })); } if (!string.IsNullOrEmpty(webModel.SiteLogoUrl)) { context.AddQuery(new ClientActionInvokeMethod(web, "SiteLogoUrl", new object[] { webModel.SiteLogoUrl })); } } else { TraceService.Critical((int)LogEventId.ModelProvisionCoreCall, "CSOM runtime doesn't have Web.AlternateCssUrl and Web.SiteLogoUrl methods support. Update CSOM runtime to a new version. Provision is skipped"); } #if !NET35 if (webModel.IndexedPropertyKeys.Any()) { var props = web.AllProperties; // may not be there at all var indexedPropertyValue = props.FieldValues.Keys.Contains("vti_indexedpropertykeys") ? ConvertUtils.ToStringAndTrim(props["vti_indexedpropertykeys"]) : string.Empty; var currentIndexedProperties = IndexedPropertyUtils.GetDecodeValueForSearchIndexProperty(indexedPropertyValue); // setup property bag foreach (var indexedProperty in webModel.IndexedPropertyKeys) { // indexed prop should exist in the prop bag // otherwise it won't be saved by SharePoint (ILSpy / Refletor to see the logic) // http://rwcchen.blogspot.com.au/2014/06/sharepoint-2013-indexed-property-keys.html var propName = indexedProperty.Name; var propValue = string.IsNullOrEmpty(indexedProperty.Value) ? string.Empty : indexedProperty.Value; props[propName] = propValue; } // merge and setup indexed prop keys, preserve existing props foreach (var indexedProperty in webModel.IndexedPropertyKeys) { if (!currentIndexedProperties.Contains(indexedProperty.Name)) { currentIndexedProperties.Add(indexedProperty.Name); } } props["vti_indexedpropertykeys"] = IndexedPropertyUtils.GetEncodedValueForSearchIndexProperty(currentIndexedProperties); } #endif }