implementing a simple Cross SIte collection list view webpart

Out of the box list view web part does not support lists that are contained in a different site collection. In this post I will show you how you can write a simple web part that will allow cross site collection list support.

Within the custom web part I’m leveraging ListViewByQuery control that is contained within the “Microsoft.SharePoint.WebControls” namespace in assembly “Microsoft.SharePoint.dll”

Couple of things about “ListViewByQuery” control

  • you must set “List” and “Query” properties for this control
  • You will get a “missing list” exception or something like that if you don’t set “ViewFields” property for the Query
  • SPQuery should be instantiated with a View, otherwise you will get a blank page (If you instantiate SPQuery with a view you do not need to specify “ViewFields” property although MSDN documentation states different)

My custom web part has following properties defined

SiteUrl: if the list is in different site collection, set site collection URL

ViewName: List View Name to be used

SourceList: Source List to Query

In the overriden CreateChildControls method of web part new up an instance of “ListViewControl” and set List and Query properties and add to the controls collection. If a site url was not specified, we assume the list is contained within the current web context, also if a view name was specified through properties, we are using that when creating SPQuery object, other wise default view on the list is used.

 

    1: protected override void CreateChildControls()
    2: {
    3:     base.CreateChildControls();
    4:     SPSite site = null ;
    5:     SPWeb web = null ;
    6:     Boolean disposeSPSite = false ;
    7:     try
    8:     {
    9:         if (this.SourceList != string.Empty && this.SourceList != string.Empty)
   10:         {
   11:             viewByQuery = new ListViewByQuery();
   12:             if(this.SiteUrl != null && this.SiteUrl != string.Empty)
   13:             {
   14:                 site = new SPSite(this.SiteUrl);
   15:                 disposeSPSite = true ;
   16:             }
   17:             else
   18:             {
   19:                 site = SPContext.Current.Site ;
   20:             }
   21:             web = site.OpenWeb();
   22:             SPList sourceList = web.Lists[this.SourceList];
   23:             viewByQuery.List = sourceList;
   24:             SPQuery query = null;
   25:             if (CheckIfViewExists(viewByQuery.List))
   26:             {
   27:                 //use the view specified in webpart property
   28:                 query = new SPQuery(viewByQuery.List.Views[this.ViewName]);
   29:             }
   30:             else
   31:             {
   32:                 //use default view to initialized
   33:                 query = new SPQuery(viewByQuery.List.DefaultView);
   34:             }
   35:             viewByQuery.Query = query;
   36:             viewByQuery.DisableFilter = this.DisableFilter;
   37:             viewByQuery.DisableSort = this.DisableSort;
   38:             this.Controls.Add(viewByQuery);
   39:         }
   40:         else
   41:         {
   42:             encodedLiteral = new EncodedLiteral();
   43:             encodedLiteral.Text = "This webpart is not configured.";
   44:             this.Controls.Add(encodedLiteral);
   45:         }
   46:     }
   47:     finally
   48:     {
   49:         if(disposeSPSite)
   50:         {
   51:             ((IDisposable)site).Dispose();
   52:             ((IDisposable)web).Dispose();
   53:         }
   54:     }
   55: }

Custom Web Part Configuration View

crosssistelist3

Here is a view of the web part showing documents from document library named “Documents” contained within a different site collection

crosssitelist4

All Items view of document library named “Documents” in root site collection of the web app

crossitelist1

 

  <Update Date="10/10/2010">

I recently received comment about not being able to see folder, try setting the ViewAttributes property for the SPQuery object

Ex:

query.ViewAttributes = "Scope=\"Recursive\"";
 

</Update>

 

 

 

Code from web part project, if you find it useful please leave a comment here…

    1: #region using statements
    2: using System;
    3: using System.Runtime.InteropServices;
    4: using System.Web;
    5: using System.Web.UI;
    6: using System.Web.UI.WebControls;
    7: using System.Web.UI.WebControls.WebParts;
    8: using System.Xml.Serialization;
    9: using System.Text;
   10:  
   11:  
   12: using Microsoft.SharePoint;
   13: using Microsoft.SharePoint.WebControls;
   14: using Microsoft.SharePoint.WebPartPages;
   15: #endregion
   16:  
   17: namespace Foo
   18: {
   19:     [Guid("9558189B-CD3B-481b-9B06-AE434CF47B18")]
   20:     public class CrossSiteCollectionListViewWebPart : System.Web.UI.WebControls.WebParts.WebPart
   21:     {
   22:         #region protected child control variable definitions
   23:         protected ListViewByQuery viewByQuery = null;
   24:         protected EncodedLiteral encodedLiteral = null;
   25:         #endregion
   26:         
   27:         #region webpart properties
   28:         /// <summary>
   29:         /// 
   30:         /// </summary>
   31:         private string viewNameField = string.Empty;
   32:         [Personalizable(), WebPartStorage(Storage.Shared), WebBrowsable(),
   33:          WebDisplayName("View Name"), WebDescription("View Name")]
   34:         public string ViewName
   35:         {
   36:             get
   37:             {
   38:                 return this.viewNameField;
   39:             }
   40:             set
   41:             {
   42:                 this.viewNameField = value;
   43:             }
   44:         }
   45:         private string siteUrlField = string.Empty;
   46:         [Personalizable(), WebPartStorage(Storage.Shared), WebBrowsable(),
   47:          WebDisplayName("Site Url"), WebDescription("Site Url")]
   48:         public string SiteUrl
   49:         {
   50:             get
   51:             {
   52:                 return this.siteUrlField;
   53:             }
   54:             set
   55:             {
   56:                 this.siteUrlField = value;
   57:             }
   58:         }
   59:         /// <summary>
   60:         /// 
   61:         /// </summary>
   62:         private string sourceListField = string.Empty;
   63:         [Personalizable(), WebPartStorage(Storage.Shared), WebBrowsable(),
   64:          WebDisplayName("Source List"), WebDescription("Source list to query")]
   65:         public string SourceList
   66:         {
   67:             get
   68:             {
   69:                 return this.sourceListField;
   70:             }
   71:             set
   72:             {
   73:                 this.sourceListField = value;
   74:             }
   75:         }
   76:         private Boolean disableFilterField = false;
   77:         [Personalizable(), WebPartStorage(Storage.Shared), WebBrowsable(),
   78:          WebDisplayName("Disable Filter"), WebDescription("Disable List Filtering")]
   79:         public Boolean DisableFilter
   80:         {
   81:             get
   82:             {
   83:                 return disableFilterField;
   84:             }
   85:             set
   86:             {
   87:                 disableFilterField = value;
   88:             }
   89:         }
   90:         private Boolean disableSortField = false;
   91:         [Personalizable(), WebPartStorage(Storage.Shared), WebBrowsable(),
   92:          WebDisplayName("Disable Sort"), WebDescription("Disable list sorting")]
   93:         public Boolean DisableSort
   94:         {
   95:             get
   96:             {
   97:                 return disableSortField;
   98:             }
   99:             set
  100:             {
  101:                 this.disableSortField = value;
  102:             }
  103:         }
  104:         #endregion
  105:  
  106:         #region overrides
  107:         protected override void CreateChildControls()
  108:         {
  109:             base.CreateChildControls();
  110:             SPSite site = null ;
  111:             SPWeb web = null ;
  112:             Boolean disposeSPSite = false ;
  113:             try
  114:             {
  115:                 if (this.SourceList != string.Empty && this.SourceList != string.Empty)
  116:                 {
  117:                     viewByQuery = new ListViewByQuery();
  118:                     if(this.SiteUrl != null && this.SiteUrl != string.Empty)
  119:                     {
  120:                         site = new SPSite(this.SiteUrl);
  121:                         disposeSPSite = true ;
  122:                     }
  123:                     else
  124:                     {
  125:                         site = SPContext.Current.Site ;
  126:                     }
  127:                     web = site.OpenWeb();
  128:                     SPList sourceList = web.Lists[this.SourceList];
  129:                     viewByQuery.List = sourceList;
  130:                     SPQuery query = null;
  131:                     if (CheckIfViewExists(viewByQuery.List))
  132:                     {
  133:                         //use the view specified in webpart property
  134:                         query = new SPQuery(viewByQuery.List.Views[this.ViewName]);
  135:                     }
  136:                     else
  137:                     {
  138:                         //use default view to initialized
  139:                         query = new SPQuery(viewByQuery.List.DefaultView);
  140:                     }
  141:                     viewByQuery.Query = query;
  142:                     viewByQuery.DisableFilter = this.DisableFilter;
  143:                     viewByQuery.DisableSort = this.DisableSort;
  144:                     this.Controls.Add(viewByQuery);
  145:                 }
  146:                 else
  147:                 {
  148:                     encodedLiteral = new EncodedLiteral();
  149:                     encodedLiteral.Text = "This webpart is not configured.";
  150:                     this.Controls.Add(encodedLiteral);
  151:                 }
  152:             }
  153:             finally
  154:             {
  155:                 if(disposeSPSite)
  156:                 {
  157:                     ((IDisposable)site).Dispose();
  158:                     ((IDisposable)web).Dispose();
  159:                 }
  160:             }
  161:         }
  162:         protected override void RenderContents(HtmlTextWriter writer)
  163:         {
  164:             
  165:             EnsureChildControls();
  166:             RenderChildren(writer);
  167:         }
  168:         #endregion
  169:  
  170:         #region helper methods
  171:         private Boolean CheckIfViewExists(SPList list)
  172:         {
  173:             Boolean ret = false;
  174:  
  175:             foreach (SPView view in list.Views)
  176:             {
  177:                 if (view.Title.ToLower() == this.ViewName.ToLower())
  178:                 {
  179:                     ret = true;
  180:                 }
  181:             }
  182:             return ret;
  183:         }
  184:         #endregion
  185:     }
  186: }

Technorati Tags: sharePoint,WebParts

Comments

  • Anonymous
    April 21, 2009
    PingBack from http://microsoft-sharepoint.simplynetdev.com/implementing-a-simple-cross-site-collection-list-view-webpart/

  • Anonymous
    May 08, 2009
    Nice post. Really useful. There is an another web-part called "SiteDocuments" - which can do nearly the same thing for the document libraries.

  • Anonymous
    June 03, 2009
    have a list that has a column that is a "choice" field.  I have selections that they can chooose from in rop down format.....and i i have added some values and default value too.I am using the list senario in meeting events list,i have to check the condition when any one uses New Item->Save and close then  i have to check wheather anyone already selected some choice field for specific time,i donot want to allow others to book that choice again ,i have to show some custom message...is there any way I can read the values of choice column and check the meeting events values already booked ,then diplay som emessage that that choice is already booked message in New Form.aspx? I am using SPS2003,Designer 2007,wss 2.0. Can we do the above by using of webpart. Please help my out . Regards Ravi

  • Anonymous
    July 16, 2009
    It would be really useful if you could provide the baby steps on how to deploy this code. Did you use VSeWSS? Did you start with a Web part template? Can this be saved as a solution and deployed globally? Any advice appreciated.

  • Anonymous
    August 30, 2009
    Hi, Your code is really helpful, but when i show the list from other site i.e other web application not same site collection, then display and edit items thows error becuase it assumes that list is in same site collection. Is there and solution to this?

  • Anonymous
    September 01, 2009
    I will take a look at this and post response here Thanks, </Ram>

  • Anonymous
    September 27, 2009
    Is there a way to export the listviewbyquery results to Excel? daniel.r.walker1@navy.mil

  • Anonymous
    October 27, 2009
    Hello Ram, I have a requirement to retrieve all the open and closed service requests from a list called Service requests. I have a web application with 2 site collections. Service requests list is in one site collection and in the second site collection i am using your web part to retrieve all the data. This does retrieves the data but the problem comes when i added 2 webparts on the same page. One for Open and second for closed service requests. I have 2 questions for you : 1 ) My requirement is to make the closed Service requests web part to be collapsed by default. When i set this in the view, i always see "Loading..."om the web part page. It never loads

  1. If in both open and closed service requests web parts if i use group by caluse in the view , and i try to expand and collapse them in the web part. It never works. Like for example i have 2 webparts on same page. If i try to expand/collapse the second web part it always collapses/expands for the first webpart. which is weird. Do you have any thoughts or suggestions on this. I appreciate your help. Thanks.
  • Anonymous
    January 08, 2010
    Excellent Post! You saved me a lot of development time.

  • Anonymous
    February 03, 2010
    Thanks for the code, works brilliantly! I'm trying to create a web part which uses the same list and site but different views. When i try to hard code the list name i get an unhandled exception...any ideas?

  • Anonymous
    February 16, 2010
    hi Ram Thanq very much it was very help ful

  • Anonymous
    March 22, 2010
    Hello Ram, thank you for your great blog! Your solution is great, however, I am having the problem that if I use the Group By feature in the view, the cross-site collection list view webpart will not expand the selection. Is there a problem with adding the required javascript files? (Ajax issue). Could you help me out? Thanks again. Martin

  • Anonymous
    April 09, 2010
    Excellent. Work -- I've been looking a different solutions for this problem and yours is definitely the best. Now I need to figure out a way to security trim based on a query of the site directory. Any ideas?

  • Anonymous
    April 09, 2010
    Hello Ram, I am trying to find the ways to deploy this code, can you give the steps. I have visual studion 2008 professional edition with sharepoin extensions, i am seeing that when ever i deploy the webpart ( simple hello webpart) the process of creting wsp and adding to gac and activating the feature is all handling by Visual studio as I am working on the sharepoint server but when i try to add the webpart i am getting the message saying that i need to add the safecontrol.. is it not handled by visual studio.. do i need to add anything to xml files to achieve this. right now i just build and click on deploy.. please advice.. much appericiate your help. thanks.

  • Anonymous
    April 09, 2010
    Jay: Not sure if I understand your scenario well, why do you need to security trim based on site directory query? Naresh: WSP Deployment should have done this automatically, how ever you can manually edit the solution manifest and make sure there is a safecontrol entry for your webpart <SafeControl  Assembly = "{replace with webpart assembly"  Namespace = "{replace with your namespace}"  Safe = "TRUE" | "FALSE"  TypeName = "{replace}"> </SafeControl>

  • Anonymous
    April 26, 2010
    Hi! It works!!, BUT it doesn't seem to work when there are folders inside of the list. When I click on a folder, the page that contains the list appears and nothing else happens. Is there a workaround to fix this issue ? Thank you !

  • Anonymous
    May 06, 2010
    This works great until you put a Folder object in the Document Library.  This is proving to be quite a tricky issue, clicking a folder sends you the the Document Library View page.  This would need to be modified to post back to itself, which I've got working, but the query of a Folders contents appears to be a common problem that I'm haven't yet found an answer to.  Any ideas?