TL;DR Version
Cant create a webpart with searchbox (InplaceSearchEnabled
) from XML and even cant modify it afterwards via SSOM to make it work.
Setting the value over the UI works fine.
Problem only present on TeamSites.
Long Version
Possible still unanswered duplicate: View property “InplaceSearchEnabled” in onet.xml ignored
Scenario
I'm working with a CSOM XML-based provisioning solution my team created with some Microsoft developers. Sadly we have been and are running against a lot of problems. The problem bringing me here is the following:
Problem
When adding WebParts to pages like this:
XML
<!--ignore the $placeholders - they are properly replaced by the solution-->
<Web Title="$Title" Lcid="1031" Template="sts#0" Description="Teamsite" Url="$SubsitePath">
<TeamPages>
<TeamPage FileName="Homepage.aspx" HomePage="true" PageLayout="RowWithSidebar">
<WebParts>
<webParts Zone="wpz" Index="2" LayoutArea="1">
<webPart xmlns="http://schemas.microsoft.com/WebPart/v3">
<metaData>
<type name="Microsoft.SharePoint.WebPartPages.XsltListViewWebPart, Microsoft.SharePoint, Version=15.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" />
<importErrorMessage>Dieses Webpart kann nicht importiert werden.</importErrorMessage>
</metaData>
<data>
<properties>
<property name="InplaceSearchEnabled" type="bool">True</property>
<property name="ListUrl" type="string">$RelativeSiteCollectionUrl/Lists/Aufgabenliste</property>
<property name="ListName">{$listId{Aufgabenliste}}</property>
<property name="ChromeType" type="chrometype">TitleOnly</property>
<property name="Title" type="string">meine Aufgaben</property>
<property name="XmlDefinition" type="string"><View Name="{$listViewIdForView{Aufgabenliste, meine Aufgaben}}" Type="HTML" Hidden="TRUE" DisplayName="" Url="$RelativeSiteCollectionUrl/SitePages/Homepage.aspx" Level="1" BaseViewID="1" ContentTypeID="0x" ImageUrl="/_layouts/15/images/generic.png?rev=23" ><Query><OrderBy xmlns="http://hamburg.de/ProvisioningDefinition.xsd"><FieldRef Name="ID" Ascending="FALSE"/></OrderBy><Where xmlns="http://hamburg.de/ProvisioningDefinition.xsd"><Eq><FieldRef Name="DPVerantwortlichkeit"/><Value Type="Integer"><UserID Type="Integer"/></Value></Eq></Where></Query><ViewFields><FieldRef Name="DocIcon"/><FieldRef Name="LinkTitle"/><FieldRef Name="Modified"/><FieldRef Name="DPVerantwortlichkeit"/><FieldRef Name="DPStatus"/><FieldRef Name="DPF_x00e4_lligkeitsdatum"/><FieldRef Name="DPKategorie"/></ViewFields><RowLimit Paged="TRUE">500</RowLimit><JSLink>clienttemplates.js</JSLink><XslLink Default="TRUE">main.xsl</XslLink><Toolbar Type="Standard"/></View></property>
</properties>
</data>
</webPart>
</webParts>
</WebParts>
</TeamPage>
C#
WebPartDefinition wpdefSharePoint = wpm.ImportWebPart(webPartXml);
var webPart = wpm.AddWebPart(wpdefSharePoint.WebPart, wpe.Zone, wpe.Index);
The InplaceSearchEnabled
property is ignored.
When setting the property over the UI everything is fine.
Since CSOM does not support modifying this property, I made use of an SSOM extension to set the property serverside.
Sadly the code is only able to remove the searchbox, no matter what I set InplaceSearchEnabled
to, a modification of the property removes the searchbox (it can be re-enabled via the UI).
SSOM attempt
internal static bool SetWebPartInplaceSearchEnabled(string serverAbsolutePageUrl, string webPartId, bool inplaceSearchEnabled)
{
try
{
using (SPSite site = new SPSite(serverAbsolutePageUrl))
{
using (SPWeb web = site.OpenWeb())
{
var allowUnsafeUpdates = web.AllowUnsafeUpdates;
try
{
web.AllowUnsafeUpdates = true;
var webPartManager = web.GetLimitedWebPartManager(serverAbsolutePageUrl, System.Web.UI.WebControls.WebParts.PersonalizationScope.Shared);
foreach (Microsoft.SharePoint.WebPartPages.WebPart webPart in webPartManager.WebParts)
{
if (webPart.ID.Equals(webPartId))
{
XsltListViewWebPart xsltWebPart = webPart as XsltListViewWebPart;
xsltWebPart.InplaceSearchEnabled = inplaceSearchEnabled;
xsltWebPart.ClientRender = true;
webPartManager.SaveChanges(xsltWebPart);
}
}
}
catch (Exception ex)
{
throw ex;
}
finally
{
web.AllowUnsafeUpdates = allowUnsafeUpdates;
}
}
}
return true;
}
catch (Exception ex)
{
//Logger.LogError(string.Format("SetWebPartInplaceSearchEnabled - Url:'{0}', WebPartId:'{1}' \nError:\n{2}", serverAbsolutePageUrl, webPartId, ex.ToString()));
return false;
}
}
When decompiling the SP .dll's there is only one reference for InplaceSearchEnabled
, and it's not looking like it's causing the problem.
[Personalizable(PersonalizationScope.Shared, false)]
[PersistenceMode(PersistenceMode.Attribute)]
public bool InplaceSearchEnabled
{
get
{
if (this.SPList != null && this.SPList.Hidden || this.SPList != null && this.SPList.HasExternalDataSource)
return false;
if (this.inplaceSearchEnabled.HasValue)
return this.inplaceSearchEnabled.Value;
return this.ShowControlDiv;
}
set
{
this.inplaceSearchEnabled = new bool?(value);
}
}
Currently I'm out of ideas to solve this. Solutions/Workarounds are appreciated.
Update
Through the awesome dnSpy tool I could debug the SharePoint assemblies. Seems like the getter is the problem.. too bad the SPList
property isn't accessible.
Update 2
I created a test console app to make it easier for everyone to reproduce the error. Here's the code:
using Microsoft.SharePoint.Client;
using Microsoft.SharePoint.Client.WebParts;
/*
* I used Microsoft.SharePoint.Client version 15.0.0.0 (I've also tried the 16 version) for the usings
* Location C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\15\ISAPI\Microsoft.SharePoint.Client.dll
* SharePoint Version (via /_vti_pvt/service.cnf) 15.0.0.4693
* and SharePoint Version (other environment) 15.0.0.4763
*/
namespace Console
{
internal class Program
{
private static void Main(string[] args)
{
/*
* Steps to reproduce
* 1. Create a new SiteCollection of type TeamSite
* 2. Run the code below
*/
//edit for your url
var ctx = new ClientContext("https://sp2013base/sites/inplacesearch");
//here are some XML presets (you need to edit the properties for some of them to match your environment)
//as simple as it gets
string shortXml = @"
<webParts>
<webPart xmlns=""http://schemas.microsoft.com/WebPart/v3"">
<metaData>
<type name=""Microsoft.SharePoint.WebPartPages.XsltListViewWebPart, Microsoft.SharePoint, Version=15.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c"" />
<importErrorMessage>Dieses Webpart kann nicht importiert werden.</importErrorMessage>
</metaData>
<data>
<properties>
<property name=""InplaceSearchEnabled"" type=""bool"">True</property>
<property name=""ListUrl"" type=""string"">SitePages</property>
</properties>
</data>
</webPart>
</webParts>
";
//what sharepoint exports
string exportedWebPartXml = @"
<webParts>
<webPart xmlns=""http://schemas.microsoft.com/WebPart/v3"">
<metaData>
<type name=""Microsoft.SharePoint.WebPartPages.XsltListViewWebPart, Microsoft.SharePoint, Version=15.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c"" />
<importErrorMessage>Cannot import this Web Part.</importErrorMessage>
</metaData>
<data>
<properties>
<property name=""ShowWithSampleData"" type=""bool"">False</property>
<property name=""Default"" type=""string"" />
<property name=""NoDefaultStyle"" type=""string"" />
<property name=""CacheXslStorage"" type=""bool"">True</property>
<property name=""ViewContentTypeId"" type=""string"" />
<property name=""XmlDefinitionLink"" type=""string"" />
<property name=""ManualRefresh"" type=""bool"">False</property>
<property name=""ListUrl"" type=""string"" null=""true"" />
<property name=""ListId"" type=""System.Guid, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"">31e3873d-9bc5-4ba0-961f-1d6db280fabc</property>
<property name=""TitleUrl"" type=""string"">/sites/InplaceSearch/SitePages</property>
<property name=""EnableOriginalValue"" type=""bool"">False</property>
<property name=""Direction"" type=""direction"">NotSet</property>
<property name=""ServerRender"" type=""bool"">False</property>
<property name=""ViewFlags"" type=""Microsoft.SharePoint.SPViewFlags, Microsoft.SharePoint, Version=15.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c"">Html, TabularView, Hidden, Mobile</property>
<property name=""AllowConnect"" type=""bool"">True</property>
<property name=""ListName"" type=""string"">{31E3873D-9BC5-4BA0-961F-1D6DB280FABC}</property>
<property name=""ListDisplayName"" type=""string"" null=""true"" />
<property name=""AllowZoneChange"" type=""bool"">True</property>
<property name=""ChromeState"" type=""chromestate"">Normal</property>
<property name=""DisableSaveAsNewViewButton"" type=""bool"">False</property>
<property name=""ViewFlag"" type=""string"" />
<property name=""DataSourceID"" type=""string"" />
<property name=""ExportMode"" type=""exportmode"">All</property>
<property name=""AutoRefresh"" type=""bool"">False</property>
<property name=""FireInitialRow"" type=""bool"">True</property>
<property name=""AllowEdit"" type=""bool"">True</property>
<property name=""Description"" type=""string"" />
<property name=""HelpMode"" type=""helpmode"">Modeless</property>
<property name=""InplaceSearchEnabled"" type=""bool"">True</property>
<property name=""BaseXsltHashKey"" type=""string"" null=""true"" />
<property name=""AllowMinimize"" type=""bool"">True</property>
<property name=""CacheXslTimeOut"" type=""int"">86400</property>
<property name=""ChromeType"" type=""chrometype"">Default</property>
<property name=""Xsl"" type=""string"" null=""true"" />
<property name=""JSLink"" type=""string"" null=""true"" />
<property name=""CatalogIconImageUrl"" type=""string"">/_layouts/15/images/itwp.png?rev=23</property>
<property name=""SampleData"" type=""string"" null=""true"" />
<property name=""UseSQLDataSourcePaging"" type=""bool"">True</property>
<property name=""TitleIconImageUrl"" type=""string"" />
<property name=""PageSize"" type=""int"">-1</property>
<property name=""ShowTimelineIfAvailable"" type=""bool"">True</property>
<property name=""Width"" type=""string"" />
<property name=""DataFields"" type=""string"" />
<property name=""Hidden"" type=""bool"">False</property>
<property name=""Title"" type=""string"" />
<property name=""PageType"" type=""Microsoft.SharePoint.PAGETYPE, Microsoft.SharePoint, Version=15.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c"">PAGE_NORMALVIEW</property>
<property name=""DataSourcesString"" type=""string"" />
<property name=""AllowClose"" type=""bool"">True</property>
<property name=""InplaceSearchEnabled"" type=""bool"">True</property>
<property name=""WebId"" type=""System.Guid, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"">00000000-0000-0000-0000-000000000000</property>
<property name=""Height"" type=""string"" />
<property name=""GhostedXslLink"" type=""string"">main.xsl</property>
<property name=""DisableViewSelectorMenu"" type=""bool"">False</property>
<property name=""DisplayName"" type=""string"" />
<property name=""IsClientRender"" type=""bool"">False</property>
<property name=""XmlDefinition"" type=""string""><View Name=""{BEDB36C4-63B9-43A8-8E1B-DD0CBF298C53}"" MobileView=""TRUE"" Type=""HTML"" Hidden=""TRUE"" DisplayName="""" Url=""/sites/InplaceSearch/SitePages/Home.aspx"" Level=""1"" BaseViewID=""1"" ContentTypeID=""0x"" ToolbarTemplate=""WikiLibraryViewToolBar"" ImageUrl=""/_layouts/15/images/dlicon.png?rev=23"" ><Query><OrderBy><FieldRef Name=""Modified"" Ascending=""FALSE""/></OrderBy></Query><ViewFields><FieldRef Name=""DocIcon""/><FieldRef Name=""LinkFilename""/><FieldRef Name=""Editor""/><FieldRef Name=""Modified""/><FieldRef Name=""Author""/><FieldRef Name=""Created""/></ViewFields><RowLimit Paged=""TRUE"">30</RowLimit><JSLink>clienttemplates.js</JSLink><XslLink Default=""TRUE"">main.xsl</XslLink><Toolbar Type=""Standard""/></View></property>
<property name=""InitialAsyncDataFetch"" type=""bool"">False</property>
<property name=""AllowHide"" type=""bool"">True</property>
<property name=""ParameterBindings"" type=""string""> <ParameterBinding Name=""dvt_sortdir"" Location=""Postback;Connection""/>
<ParameterBinding Name=""dvt_sortfield"" Location=""Postback;Connection""/>
<ParameterBinding Name=""dvt_startposition"" Location=""Postback"" DefaultValue=""""/>
<ParameterBinding Name=""dvt_firstrow"" Location=""Postback;Connection""/>
<ParameterBinding Name=""OpenMenuKeyAccessible"" Location=""Resource(wss,OpenMenuKeyAccessible)"" />
<ParameterBinding Name=""open_menu"" Location=""Resource(wss,open_menu)"" />
<ParameterBinding Name=""select_deselect_all"" Location=""Resource(wss,select_deselect_all)"" />
<ParameterBinding Name=""idPresEnabled"" Location=""Resource(wss,idPresEnabled)"" /> <ParameterBinding Name=""NoAnnouncements"" Location=""Resource(wss,noXinviewofY_LIST)"" />
<ParameterBinding Name=""NoAnnouncementsHowTo"" Location=""Resource(core,noXinviewofY_DEFAULT)"" />
<ParameterBinding Name=""AddNewAnnouncement"" Location=""Resource(wss,addnewitem)"" />
<ParameterBinding Name=""MoreAnnouncements"" Location=""Resource(wss,moreItemsParen)"" /></property>
<property name=""DataSourceMode"" type=""Microsoft.SharePoint.WebControls.SPDataSourceMode, Microsoft.SharePoint, Version=15.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c"">List</property>
<property name=""AutoRefreshInterval"" type=""int"">60</property>
<property name=""AsyncRefresh"" type=""bool"">False</property>
<property name=""HelpUrl"" type=""string"" />
<property name=""MissingAssembly"" type=""string"">Cannot import this Web Part.</property>
<property name=""XslLink"" type=""string"" null=""true"" />
<property name=""SelectParameters"" type=""string"" />
</properties>
</data>
</webPart>
</webParts>
";
//from Christoffel de Gruyter's answer
string webPartXml = @"
<webParts>
<webPart xmlns=""http://schemas.microsoft.com/WebPart/v3"">
<metaData>
<type name=""Microsoft.SharePoint.WebPartPages.XsltListViewWebPart, Microsoft.SharePoint, Version=15.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c"" />
<importErrorMessage>Dieses Webpart kann nicht importiert werden.</importErrorMessage>
</metaData>
<data>
<properties>
<property name=""InplaceSearchEnabled"" type=""bool"">True</property>
<property name=""ListUrl"" type=""string"" null=""true"" />
<property name=""ListName"" type=""string"">{31E3873D-9BC5-4BA0-961F-1D6DB280FABC}</property>
<property name=""ListId"" type=""System.Guid, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"">31e3873d-9bc5-4ba0-961f-1d6db280fabc</property>
<property name=""ChromeType"" type=""chrometype"">TitleOnly</property>
<property name=""Title"" type=""string"">SitePages</property>
<property name=""XmlDefinition"" type=""string""><View Name=""{F52E1EA6-0264-4496-BF96-348EDB8C2353}"" MobileView=""TRUE"" Type=""HTML"" Hidden=""TRUE"" DisplayName="""" Url=""/sites/InplaceSearch/SitePages/Home.aspx"" Level=""1"" BaseViewID=""1"" ContentTypeID=""0x"" ImageUrl=""/_layouts/15/images/dlicon.png?rev=43"" ><Query><OrderBy><FieldRef Name=""FileLeafRef""/></OrderBy></Query><ViewFields><FieldRef Name=""DocIcon""/><FieldRef Name=""LinkFilename""/><FieldRef Name=""Modified""/><FieldRef Name=""Editor""/></ViewFields><RowLimit Paged=""TRUE"">30</RowLimit><JSLink>clienttemplates.js</JSLink><XslLink Default=""TRUE"">main.xsl</XslLink><Toolbar Type=""Standard""/></View></property>
</properties>
</data>
</webPart>
</webParts>
";
//add the webpart to the page
//change for your environment
var aspxPage = ctx.Web.GetFileByServerRelativeUrl("/sites/inplacesearch/SitePages/Home.aspx");
ctx.ExecuteQuery();
LimitedWebPartManager wpm = aspxPage.GetLimitedWebPartManager(PersonalizationScope.Shared);
WebPartDefinition wpdef = wpm.ImportWebPart(shortXml);
WebPartDefinition webPart = wpm.AddWebPart(wpdef.WebPart, "Right", 0);
ctx.ExecuteQuery();
}
}
}