MOSS MVP

I've moved my blog to http://blog.falchionconsulting.com!. Please update your links. This blog is no longer in use--you can find all posts and comments at my new blog; I will no longer be posting to this site and comments have been disabled.

Thursday, August 7, 2008

Adding a List View Web Part to a Page

I had a requirement recently to show a view of a list from a child site on the page of a parent site.  You can of course do this easily with a content query web part and then just manipulate the XSL to get the output to look the way you want but what if you want to be able to use the out of the box List View Web Part so that you get the toolbar and all the other stuff that the web part provides?  Many people aren't even aware that this is possible but it is - unfortunately it's kind of a pain to do via the browser - you have to add the web part to a page, export it using a custom tool or code (not sure if SPD allows you to export but you can't do it via the browser), edit the resultant XML to set the WebId  attribute, and then import the web part to the desired location.

To get around all these steps I built a simple command called gl-addlistviewwebpart.  I already had a command, gl-setwebpartstate, that could accomplish the same thing but using that command would require that you know the WebId and ListId which would most likely not be available during a scripted install.

The majority of the code is a derivative of the code from the gl-setwebpartstate command.  I simply instantiate a ListViewWebPart object, set a few properties and then add the web part using an instance of the SPLimitedWebPartManager class:

   1: /// <summary>
   2: /// Adds a List View Web Part to the specified page.
   3: /// </summary>
   4: /// <param name="pageUrl">The page URL.</param>
   5: /// <param name="listUrl">The list URL.</param>
   6: /// <param name="title">The title.</param>
   7: /// <param name="zoneID">The zone ID.</param>
   8: /// <param name="zoneIndex">Index within the zone.</param>
   9: /// <param name="publish">if set to <c>true</c> [publish].</param>
  10: public static void Add(string pageUrl, string listUrl, string title, string zoneID, int zoneIndex, bool publish)
  11: {
  12:     using (SPSite site = new SPSite(pageUrl))
  13:     using (SPWeb web = site.OpenWeb())
  14:         // The url contains a filename so AllWebs[] will not work unless we want to try and parse which we don't
  15:     {
  16:         SPFile file = web.GetFile(pageUrl);
  17:  
  18:         // file.Item will throw "The object specified does not belong to a list." if the url passed
  19:         // does not correspond to a file in a list.
  20:  
  21:         if (file.InDocumentLibrary)
  22:         {
  23:             if (!Utilities.IsCheckedOut(file.Item) || !Utilities.IsCheckedOutByCurrentUser(file.Item))
  24:                 file.CheckOut();
  25:             // If it's checked out by another user then this will throw an informative exception so let it do so.
  26:         }
  27:  
  28:         string displayTitle = string.Empty;
  29:         ListViewWebPart lvw = null;
  30:         SPLimitedWebPartManager manager = null;
  31:         try
  32:         {
  33:             manager = web.GetLimitedWebPartManager(pageUrl, PersonalizationScope.Shared);
  34:             lvw = new ListViewWebPart();
  35:             SPList list = Utilities.GetListFromViewUrl(listUrl);
  36:             if (list == null)
  37:                 throw new ArgumentException("List not found.");
  38:  
  39:             lvw.ListName = list.ID.ToString("B").ToUpperInvariant();
  40:             lvw.TitleUrl = list.DefaultViewUrl;
  41:             lvw.WebId = list.ParentWeb.ID;
  42:  
  43:             if (!string.IsNullOrEmpty(title))
  44:                 lvw.Title = title;
  45:  
  46:  
  47:             displayTitle = lvw.DisplayTitle;
  48:  
  49:             manager.AddWebPart(lvw, zoneID, zoneIndex);
  50:         }
  51:         finally
  52:         {
  53:             if (manager != null)
  54:             {
  55:                 manager.Web.Dispose();
  56:                 manager.Dispose();
  57:             }
  58:             if (lvw != null)
  59:                 lvw.Dispose();
  60:  
  61:             
  62:             if (file.InDocumentLibrary && Utilities.IsCheckedOut(file.Item))
  63:                 file.CheckIn("Checking in changes to page due to new web part being added: " + displayTitle);
  64:  
  65:             if (publish && file.InDocumentLibrary)
  66:             {
  67:                 file.Publish("Publishing changes to page due to new web part being added: " + displayTitle);
  68:                 if (file.Item.ModerationInformation != null)
  69:                 {
  70:                     file.Approve("Approving changes to page due to new web part being added: " + displayTitle);
  71:                 }
  72:             }
  73:         }
  74:     }
  75: }

The help for the command is shown below:

C:\>stsadm -help gl-addlistviewwebpart

stsadm -o gl-addlistviewwebpart


Adds a list view web part to a page.

Parameters:
        -url <web part page URL>
        -listurl <list url>
        -zone <zone ID>
        -zoneindex <zone index>
        [-title <web part title>]
        [-publish]

The following table summarizes the command and its various parameters:

Command Name Availability Build Date
gl-addlistviewwebpart WSS v3, MOSS 2007 8/6/2008

Parameter Name Short Form Required Description Example Usage
url   Yes The URL to the page to add the web part to. -url http://portal/pages/default.aspx
listurl lu Yes The URL of the list to point to. -listurl http://portal/subsite/Lists/Events

-lu http://portal/subsite/Lists/Events
zone z Yes The web part zone to add the web part to. -zone RightColumnZone

-z RightColumnZone
zoneindex zi Yes The index within the zone to add the web part. -zoneindex 1

-zi 1
title t No The title to give the web part.  If not specified then the list title is used. -title Events

-t Events
publish p No Publishes the page, if supported.  The page will be automatically checked-in to share draft - passing in this parameter will also publish the page.  

The following is an example of how to add a list view web part to a page where the list is contained within a sub site:

stsadm -o addlistviewwebpart -url http://portal/pages/default.aspx -listurl http://portal/subsite/lists/events -zone RighColumnZone -zoneindex 1 -title "Company Events" -publish

24 comments:

solutionizing.net said...

Doesn't list.ParentWeb need to be disposed as well?

Gary Lapointe said...

That's questionable - In this case it wouldn't hurt anything to do so and I probably should have but there's currently a debate going on as to whether or not objects that you did not create should be dispoosed.

solutionizing.net said...

I did a bit of reflection and it looks like list.ParentWeb will still refer to the SPWeb from which it was created, which would already have been disposed by the helper method.

I've expanded on my thoughts here.

Cheers ~
Keith

Gary Lapointe said...

Keith - thanks for the post - makes your head spin doesn't it :)

Michael said...

When I try to execute this command I receive the error: This page has encountered a critical error. Contact your admin etc...

Is there anyway I can get a more verbose message so I can determine what the problem is. The web app is running on a non standard port (81), if that should make any difference? thanks

Gary Lapointe said...

That error is being thrown by the SharePoint API so there's not much I can do. Are you trying to add a list view from the current web or a web within the same site collection or outside the site collection?

Michael said...

I was trying on a different site within the same collection, but I've just tested doing it on the same site as the lists is on, but same error. Are the zones on the pages created by SP within the browser (such as default.aspx on a blank site), just called LeftZone RightZone etc?

Here is an example of the command I executed:
stsadm -o gl-addlistviewwebpart -url http://spserver:81/test/default.aspx -listurl http://spserver:81/test/lists/contacts -zone LeftZone -zoneindex 1

Thanks

Willy said...

Hello Gary,

This utility is grateful!.

I checked to save the site as template in which i deployed this webpart and when i create a site using this template the WebPart doesn't appears, do you know if is possible to save it into the template?

Gary Lapointe said...

The list view web part requires the GUID of the list so if the source list doesn't exist (or has had the GUID changed) then the web part will not show. Nothing I can do about that. You probably want to avoid using site templates anyways - better to use a minimal site definition with Features.

Willy said...

Hello again Gary,

Thanks for your reply.

The source list is present in the parent site when i create the second site based on the site template which includes the list view web part but it doesnt't shows the WebPart.

The source list GUID should be the same always because the list isn't modified from its creation.

I don't know if i am making something wrong.

Regards and thanks for your attention Gary.

Gary Lapointe said...

One thing you might try is to download the stp file and open it up (it's just a CAB file). You can then take a look at the XML that's genereated - it might shed some light (not sure if it will help though).

Willy said...

Hello Gary,

I dont get success saving the template and restore it, the list view web part doesnt appears...i dont know what could be the reason. The source list GUID is the right one in stp file.

Must i do something more?

Sameer Dhoot said...

Can we use this to display list from another site collection?

Gary Lapointe said...

No - it only works within a site collection.

edudebolivar said...

Hi Gary,
I need share a SPList between a Site and a SubSite. I need get the Items from SPList of the main site and show the items in a webpart, i do it by code into the subsite.
Programmatically, into my custom web part I do:

CreateChildControls()
{
ListView lv = new ListView();
lv.ListId = SPContext.Current.Web.Lists["Documentation"].ID.ToString();
lv.DataBind();
Controls.Add(lv);
}

This code does not work. The SPExcption show the message "List does not exist. The page you selected contains a list that does not exist. It may have been deleted by another user.".
The list exist and is accesible into main site.

I hope you can help me. Thanks.
Regards,

Javier

Gary Lapointe said...

SPContext.Current.Web will return the current web (so the sub-site based on your description) - you'll need to either use SPContext.Current.Site.RootWeb or open the web directly using SPContext.Current.Site.OpenWeb("/subsite").

edudebolivar said...

Gary:
Thank you very much.
I could fix the error with your help.
Regards!

Frank said...

I try to add a webpart in a feature activated event:

SPFile file = web.GetFile(web.Url + "/Pages/default.aspx");
using (SPLimitedWebPartManager webpartsMng = file.GetLimitedWebPartManager(PersonalizationScope.Shared))
{
file.CheckOut();
ContentEditorWebPart webPart = new ContentEditorWebPart();
webPart.Title = "Test Web Part";
webpartsMng.AddWebPart(webPart, "Right", 0);
file.CheckIn("Added ContentEditorWebPart");
webpartsMng.Web.Dispose();
}
}

But I always get an exception telling me that the file is not checked out:
{"The file is not checked out. You must first check out this document before making changes."} System.Exception {Microsoft.SharePoint.SPException}
Anyone an idea?

Gary Lapointe said...

Check the file out before getting the SPLimitedWebPartManager.

Anonymous said...

Gary, i cannot thank you enough for all of the great work. Would it be possible to add the Select View and Toolbar Type settings to this command? Thank you again for everything, you do great work! -Patrick

mac said...

About the "This page has encountered a critical error" error - check the event log. I encountered the same error message after installing the telerik RAD editor. It turned out to be caused by the safe mode parser being unable to locate the old 1.0.6* version of System.Web.Extensions when running out of stsadm.exe

This was clearly stated in the event log, and could be fixed by setting up a Binding Policy for System.Web.Extension (1.0.* -> 3.5.0.0) in .NET Framework Configuration.

Kaléu said...

Hi Lapointe.

I tried to use the command gl-addlistviewwebpart and it worked very well, except with a post list of a blog. I got the following error:

“C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\12\BIN>stsadm -o gl-addlistviewwebpart -url http://jupiter_dev/Paginas/teste.aspx -listurl http://jupiter_dev/blog/Lists/Postagens -zone Header -zi 0

There was an error generating the XML document.”

Can you help me?

Thanks.

Peter said...

Hi Gary - this is a great command, however it seems these pages aren't supported in SharePoint 2010.

Can you think of any easy way of getting them to work in SharePoint 2010 with an XsltListView?

Gary Lapointe said...

I have another command (the name is escaping me right now) that allows you to add an arbitrary web part to a page. I don't remember if I've migrated it to 2010 or not but it should work though I know I've not tested this.