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.

<webParts>
  <webPart xmlns="http://schemas.microsoft.com/WebPart/v3">
    <metaData>
      <type name="Microsoft.SharePoint.WebPartPages.XsltListViewWebPart, Microsoft.SharePoint, Version=14.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" />
      <importErrorMessage>Cannot import this Web Part.</importErrorMessage>
    </metaData>
    <data>
      <properties>
        <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>
        <property name="Xsl" type="string" null="true" />
        <property name="CacheXslTimeOut" type="int">86400</property>
        <property name="WebId" type="System.Guid, mscorlib, Version=2.0.0.0, 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=14.0.0.0, 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=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">b7b83edb-714e-47a8-af42-92a194b09169</property>
        <property name="DataSourceMode" type="Microsoft.SharePoint.WebControls.SPDataSourceMode, Microsoft.SharePoint, Version=14.0.0.0, 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=14.0.0.0, 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" />
      </properties>
    </data>
  </webPart>
</webParts>

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]
$web.Id

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.

10 comments:

  1. Hi,

    We have something like that in our solution, but the action from ribbon gives error like «List does not exist» in sub site. Do you encounter this problem?

    Thanks!

    ReplyDelete
  2. I have encountered that problem. I'm working on a workaround, or possibly a fully functional web part to handle cross-site XSLT. I've seen a few pay solutions out there, but they aren't great. I have also seen this done in jQuery, but you lose the pagination.

    ReplyDelete
  3. Hi, we can simply open the page in designer and save the web part to the gallery. This will allow us the web part to be used in all sites under site collection. The web part will be by default saved in Miscellaneous group.

    ReplyDelete
  4. I liked your article, I will share your article to everyone!!



    ________________________________________________________________________
    WoW gold|Diablo 3 Gold|RS Gold|GW2 Gold

    ReplyDelete
  5. I really love the way information is presented in your post. I feel strongly about it and love learning more on this topic. If possible, as you gain expertise, would you mind updating your blog with more information? It is extremely helpful for me.
    health insurance broker florida

    ReplyDelete
  6. Most of the time I don’t make comments on blogs, but I want to mention that this post really forced me to do so. Really nice post! It is extremely helpful for me.
    health insurance in florida

    ReplyDelete
  7. Great solution. Works for me on SP2013. Unfortently the title of each blog post is wrong when showing on different site. It points to SitePages under the new site where the WebPart is imported - instead of the actual post.

    ReplyDelete
  8. Are you getting the "List does not exist..." error when you try to save a SharePoint List as a web part in SharePoint Designer?

    There is an easy but completely undocumented way to fix this. You must create a new custom view that uses a "Style" of "Basic Table". Then when you go into SharePoint Designer, click on that new custom view (I name all of mine SPDesigner just for simplicity / consistency), and then click inside the page and then click "LIST VIEW TOOLS >> WEB PART >> To Site Gallery". After you do this a pop-up window will come up asking if you want to maintain the original list data. If this pop-up does not appear, your web part will not work right.

    Thanks!

    ReplyDelete