Mar
21
2008

How to query cross-site lists in DataFormWebPart - Part 1. Build your own data source for DataFormWebPart

Problem - We have a site which contains many sub-sites. On this site we want to use DataFormWebPart to display all the pages in Pages library of all sub-sites.

James Tsai Blog - C# ASP.Net SharePoint VST. How to query cross-site lists DataFormWebPart Pages Library

Possible solutions:

1. We could use OOTB DataFormWebPart with SharePoint Designer to configure SPDataSource of the web part to do cross-site query. On SharePoint Designer Team Blog they have detailed article about how to do this. But I couldn't get this working after followed the instructions described in the article. And it isn't easy to find out which part of my configuration was causing the error.

2. Create a custom DataFormWebPart (inherit from DataFormWebPart class) with SPSiteDataQuery to query the data we want. And use XmlDataSource as data source for our custom web part.

The steps are:

a. Build your query

We created a SPSiteDataQuery with following configurations

SPSiteDataQuery qry = new SPSiteDataQuery();
qry.Lists = "<Lists ServerTemplate='850' Hidden='TRUE' />"; //Pages library has template Id 850
qry.Webs = "<Webs Scope='Recursive' />"; //Set scope to Recursive. To query current site and all sub-sites
qry.ViewFields = "<FieldRef Name='Title' /><FieldRef Name='Comments' /><FieldRef Name=Type/>"; //The fields we want to display
qry.RowLimit = 1000; //number limit of results
qry.Query = "<Where><Eq><FieldRef Name='ContentType' /><Value Type='Text'>My Content Type</Value></Eq></Where><OrderBy><FieldRef Name='Title' Ascending='FALSE' /></OrderBy>"; //query logic
DataTable tbl = web.GetSiteData(qry); // query SPWeb and store result as DataTable

Above code returns all pages created with "My Content Type" content type in Pages Library of parent site and all sub-sites.

b. Save result data collection to XML format

Next step is to transform result in DataTable into XML. We respect default XML format expected by DataFormWebPart to make sure minimal changes needed for XSL in later stage.

XmlDocument doc = new XmlDocument();
XmlNode queryResponse = doc.AppendChild(doc.CreateElement("dsQueryResponse"));
XmlNode root = queryResponse.AppendChild(doc.CreateElement("Rows"));
foreach (DataRow row in tbl.Rows)
{
         XmlElement rowNode = doc.CreateElement("Row");
         foreach (DataColumn col in row.Table.Columns)
         {
               string val = row[col].ToString();
               XmlAttribute att = doc.CreateAttribute(col.ColumnName);
               att.Value = val;
               rowNode.Attributes.Append(att);
          }
          root.AppendChild(rowNode);
}

Sample result of above code looks like this


<dsQueryResponse>

        <Rows>

                <Row ListId="7DC60945-8C38-47D9-BD82-422D2B6D873C" WebId="A696D3FB-998F-4C7E-BDF9-3EECA4BE8A34" ID="2" Title="General Information" Comments="subsite 2 page 1" Type="Info" />

                <Row ListId="389949C9-D040-4DD4-A18F-75F4401F580A" WebId="E00F6CCB-9893-4155-A811-5D4D6DED5054" ID="4" Title="Important Information" Comments="subsite 1 page 2" Type="" />

                <Row ListId="389949C9-D040-4DD4-A18F-75F4401F580A" WebId="E00F6CCB-9893-4155-A811-5D4D6DED5054" ID="2" Title="Important Policy" Comments="subsite 1 page 1" Type="" />

       </Rows>

</dsQueryResponse>

c. Create XmlDataSource (The data source for custom DataFormWebPart)

The last step at this stage is to create a XmlDataSource and bind XML data we created in previous step with this XmlDataSource.

XmlDataSource source = new XmlDataSource();
source.Data = doc.InnerXml;

All above code are placed inside the overrided DataBind() method of custom DataFormWebPart. DataBind() method will be called when SharePoint try to render custom DataFormWebPart.

public class ExtendedDataFormWebPart : DataFormWebPart
{

    public override void DataBind()
    {

          /* all code described in above steps */

          this.DataSource = source;

          base.DataBind();

    }

}

That's all for Part 1 of How to query cross-site lists in DataFormWebPart. In Part II, I will describe how to display our query result on page using XSL.

blog comments powered by Disqus