Tuesday, August 16, 2011

Cross-Site (Web) XsltListViewWebPart

It's been awhile since I've updated the blog, but just stumbled on something that may help anyone looking to display list information across multiple sites within a single site collection. Previously we handled this through jQuery, but I've found a much better way to display this information without the use of a CQWP, and the solution was lying directly under my nose the whole time.

I was looking at creating a list view web part that would allow us to present data from one Web on another Web while maintaining the same look and functionality of the ListViewWebPart. I created a web part project in Visual Studio, and began hacking apart the XsltListViewWebPart class in Reflector (shh... don't tell), when I noticed a property in the XsltListViewToolPart class called "WebId". Why would WebId be a property in the XsltListViewWebPart you might ask? Very curious I thought...

To begin, I created a new view on the list that I wanted to share, and exported the .webpart file from the XsltListView. To export the .webpart file, you simple click on Site Actions > Edit Page, and on the List View Web Part context menu click "Export" to save the file to your local machine. Web Part files are simply an XML representation of the properties of the web part, and can be imported back into the Web Parts library at the parent site for reuse throughout your Site Collection.

  <webPart xmlns="http://schemas.microsoft.com/WebPart/v3">
      <type name="Microsoft.SharePoint.WebPartPages.XsltListViewWebPart, Microsoft.SharePoint, Version=, Culture=neutral, PublicKeyToken=71e9bce111e9429c" />
      <importErrorMessage>Cannot import this Web Part.</importErrorMessage>
        <property name="InitialAsyncDataFetch" type="bool">False</property>
        <property name="ChromeType" type="chrometype">Default</property>
        <property name="Title" type="string" />
        <property name="Height" type="string" />
        <property name="CacheXslStorage" type="bool">True</property>
        <property name="ListDisplayName" type="string" null="true" />
        <property name="AllowZoneChange" type="bool">True</property>
        <property name="AllowEdit" type="bool">True</property>
        <property name="XmlDefinitionLink" type="string" />
        <property name="DataFields" type="string" />
        <property name="Hidden" type="bool">False</property>
        <property name="ListName" type="string">{B7B83EDB-714E-47A8-AF42-92A194B09169}</property>
        <property name="NoDefaultStyle" type="string" />
        <property name="AutoRefresh" type="bool">False</property>
        <property name="ViewFlag" type="string">8388613</property>
        <property name="Direction" type="direction">NotSet</property>
        <property name="AutoRefreshInterval" type="int">60</property>
        <property name="AllowConnect" type="bool">True</property>
        <property name="Description" type="string" />
        <property name="AllowClose" type="bool">True</property>
        <property name="ShowWithSampleData" type="bool">False</property>
        <property name="ParameterBindings" type="string">
			&lt;ParameterBinding Name="dvt_sortdir" Location="Postback;Connection"/&gt;
			&lt;ParameterBinding Name="dvt_sortfield" Location="Postback;Connection"/&gt;
			&lt;ParameterBinding Name="dvt_startposition" Location="Postback" DefaultValue=""/&gt;
			&lt;ParameterBinding Name="dvt_firstrow" Location="Postback;Connection"/&gt;
			&lt;ParameterBinding Name="OpenMenuKeyAccessible" Location="Resource(wss,OpenMenuKeyAccessible)" /&gt;
			&lt;ParameterBinding Name="open_menu" Location="Resource(wss,open_menu)" /&gt;
			&lt;ParameterBinding Name="select_deselect_all" Location="Resource(wss,select_deselect_all)" /&gt;
			&lt;ParameterBinding Name="idPresEnabled" Location="Resource(wss,idPresEnabled)" /&gt;
			&lt;ParameterBinding Name="NoAnnouncements" Location="Resource(wss,noXinviewofY_LIST)" /&gt;
			&lt;ParameterBinding Name="NoAnnouncementsHowTo" Location="Resource(wss,noXinviewofY_DEFAULT)" /&gt;
        <property name="Xsl" type="string" null="true" />
        <property name="CacheXslTimeOut" type="int">86400</property>
        <property name="WebId" type="System.Guid, mscorlib, Version=, Culture=neutral, PublicKeyToken=b77a5c561934e089">820a89d6-8509-4bc4-9d39-4fd91e420f7a</property>
        <property name="ListUrl" type="string" null="true" />
        <property name="DataSourceID" type="string" />
        <property name="FireInitialRow" type="bool">True</property>
        <property name="ManualRefresh" type="bool">False</property>
        <property name="ViewFlags" type="Microsoft.SharePoint.SPViewFlags, Microsoft.SharePoint, Version=, Culture=neutral, PublicKeyToken=71e9bce111e9429c">Html, TabularView, Mobile</property>
        <property name="ChromeState" type="chromestate">Normal</property>
        <property name="AllowHide" type="bool">True</property>
        <property name="PageSize" type="int">-1</property>
        <property name="SampleData" type="string" null="true" />
        <property name="BaseXsltHashKey" type="string" null="true" />
        <property name="AsyncRefresh" type="bool">False</property>
        <property name="HelpMode" type="helpmode">Modeless</property>
        <property name="ListId" type="System.Guid, mscorlib, Version=, Culture=neutral, PublicKeyToken=b77a5c561934e089">b7b83edb-714e-47a8-af42-92a194b09169</property>
        <property name="DataSourceMode" type="Microsoft.SharePoint.WebControls.SPDataSourceMode, Microsoft.SharePoint, Version=, Culture=neutral, PublicKeyToken=71e9bce111e9429c">List</property>
        <property name="AllowMinimize" type="bool">True</property>
        <property name="TitleUrl" type="string">/kb/Lists/Emerging Issues</property>
        <property name="CatalogIconImageUrl" type="string" />
        <property name="DataSourcesString" type="string" />
        <property name="GhostedXslLink" type="string">main.xsl</property>
        <property name="PageType" type="Microsoft.SharePoint.PAGETYPE, Microsoft.SharePoint, Version=, Culture=neutral, PublicKeyToken=71e9bce111e9429c">PAGE_NORMALVIEW</property>
        <property name="DisplayName" type="string">OnlineWPItems</property>
        <property name="UseSQLDataSourcePaging" type="bool">True</property>
        <property name="Width" type="string" />
        <property name="ExportMode" type="exportmode">All</property>
        <property name="XslLink" type="string" null="true" />
        <property name="ViewContentTypeId" type="string">0x</property>
        <property name="HelpUrl" type="string" />
        <property name="XmlDefinition" type="string">&lt;View Name="{863AE444-CE71-4B03-A037-976A884DFA9B}" MobileView="TRUE" Type="HTML" DisplayName="OnlineWPItems" Url="/kb/Lists/Emerging Issues/OnlineWPItems.aspx" Level="1" BaseViewID="1" ContentTypeID="0x" ImageUrl="/_layouts/images/generic.png"&gt;&lt;Query&gt;&lt;OrderBy&gt;&lt;FieldRef Name="Modified" Ascending="FALSE"/&gt;&lt;/OrderBy&gt;&lt;Where&gt;&lt;And&gt;&lt;And&gt;&lt;Contains&gt;&lt;FieldRef Name="Intuit_x0020_Services"/&gt;&lt;Value Type="Text"&gt;Software (SaaS):Online Payroll&lt;/Value&gt;&lt;/Contains&gt;&lt;IsNotNull&gt;&lt;FieldRef Name="Issue_x0020_Status"/&gt;&lt;/IsNotNull&gt;&lt;/And&gt;&lt;Neq&gt;&lt;FieldRef Name="Issue_x0020_Status"/&gt;&lt;Value Type="Text"&gt;Updated&lt;/Value&gt;&lt;/Neq&gt;&lt;/And&gt;&lt;/Where&gt;&lt;GroupBy/&gt;&lt;/Query&gt;&lt;ViewFields&gt;&lt;FieldRef Name="Issue_x0020_Status"/&gt;&lt;FieldRef Name="LinkTitle"/&gt;&lt;/ViewFields&gt;&lt;RowLimit Paged="TRUE"&gt;5&lt;/RowLimit&gt;&lt;Aggregations Value="Off"/&gt;&lt;Toolbar Type="Standard"/&gt;&lt;/View&gt;</property>
        <property name="Default" type="string" />
        <property name="TitleIconImageUrl" type="string" />
        <property name="MissingAssembly" type="string">Cannot import this Web Part.</property>
        <property name="SelectParameters" type="string" />

The highlighted line shows the WebId property in the exported web part file. If you open the file in a text editor or Visual Studio, you can modify the WebId before uploading the new file to your Web Parts Gallery. By default, the WebId is Guid.Empty() or 00000000-0000-0000-0000-000000000000.

To get the WebId, fire up powershell on one of your sharepoint servers and use this snippet:

$web = Get-SPWeb http://[url]

Be sure to include the full path of the web, e.g. if the list is hosted under a subsite it would be http://sharepoint/listlocation.

Now that you have your WebId, copy it from the powershell window and paste it into the WebPart file property "WebId" overwriting the default value. Save the file.

Uploading the Web Part File
  1. Navigate to the top-level site in your site collection
  2. Click on Site Actions > Site Settings
  3. Click on "Web Parts" under the "Galleries" section
  4. Upload your .webpart file to the Web Part Gallery (Name the file something that will easily be recognizable when adding the web part to your pages. I also tend to organize my web parts into groups, and in this case I've created a new Group called "Cross-site List View Web Parts")
  5. Save your file properties.

At this point you should be at the "Web Part Gallery" items view. From here you can click on the title of your newly added web part to see how it will render on your pages.

To add the web part to a page in SharePoint, simply edit your page and click the "Add Web Part" option, find the group you created in the "Add Web Part" menu, and click on you web part to add it to the page. Don't forget to save or Checkin your page. If you have publishing enabled, be sure to publish the page so that the changes are available to all users.