PANVEGA’s Blog

DotNet Development, SharePoint Customizing, Silverlight, MS Infrastructure and other tips and tricks

How to access a custom User Subweb List with SP Object Model

Posted by PANVEGA on July 18, 2008

Introduction:

SharePoint provides a solid framework for the .Net developers to write code against and extend sharepoint functionality. As sharepoint is done on ASP.NET 2.0 and have a power code base of .Net Class libraries, a lot of developers can now make use of them and create excellent applications utilizing sharepoint features and libraries.

As I have been working to develop a custom webservice that our organization will use to present all data from multiple sub-sites to a top-level site in a DropDownList when consuming the service with the SP Designer. I want to be able to generate a query on a Sharepoint environment to give me back the list of all the sites that a user is member of. The method returns a XMLDocument for the webservice.

First, you will need to create a reference to “SharePoint.dll” assembly in your Visual Studio 2005 project. This is located at:

C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\12\ISAPI\Microsoft.SharePoint.dll

Here are the most important SP model classes for this szenario:

SPSite:
Represents a collection of sites on a virtual server, including a top-level site and all its subsites. Each SPSite object, or site collection, is represented within an SPSiteCollection object that consists of the collection of all site collections on the virtual server.
Note: SPSite is NOT a Collection, in another words, you can not use foreach to loop SPSite. To do this, you have to use SPWebCollection.

SPWebCollection:
Represents a collection of SPWeb objects.

SPWeb:
Represents a SharePoint Web site.

Note:

When running as an administrator, this code doesn’t cause a single problem. However, if you swap to a non-administrative user that doesn’t have full control of the site, you’ll get the lovely access denied page. The problem is that you must have full control of the site to be able to use the AllWebs property.

Unhandled Exception: System.UnauthorizedAccessException: Access is denied.

The fix for this is to use a property of the SPWeb object. See the corrected code below:

replace siteCollection.AllWebs with siteCollection.OpenWeb().GetSubwebsForCurrentUser();

By using the GetSubwebsForCurrentUser() method, I’m able to get a list of subsites that the user does have access to view. If the user doesn’t have access to any subsites, there will not be the access denied error message and you can display a warning to the user.

Be very careful with the use of both GetSubwebsForCurrentUser() and SPSite.AllWebs(). These two OM methods are both performance killers on large sites (200+ subsites).

private XmlDocument getCollection()
{
XmlDocument doc = new XmlDocument();
XmlElement webs = doc.CreateElement(“Webs”);

try
{

//You can also use the
using (SPSite siteCollection = new SPSite(“http://localhost”))
{
SPWebCollection sites = siteCollection.OpenWeb().GetSubwebsForCurrentUser();

foreach (SPWeb web in sites)
{
XmlElement webElement = doc.CreateElement(“Web”);
webElement.SetAttribute(“Title”, web.Title.Trim());
webElement.SetAttribute(“Url”, web.Url.Trim());
webs.AppendChild(webElement);
}
doc.PrependChild(webs);
}
return doc;
}
catch (Exception ex)
{
throw (new Exception(“An Error occured: “, ex));
}

}

Important: Do not forget to dispose the objects. Better using “using” instead of “dispose”.

Lots of situations where we will use APIs for retrieving information about Webs, Lists and List Items. In SharePoint, lists are the objects storing large amount of data. So we need to be little cautious while working with those APIs, because internally those APIs are calling some SQL queries to pull the data which has been stored the SharePoint Content DBs.

The performance issues may happen in some cases if numbers of lists are very high or in some cases total number of lists will be less but the items will be very large.

Read more: http://msdn.microsoft.com/en-us/library/aa973248.aspx

————————————————————–

2. Approach accessing the Subwebs the SP Webs.asmx webservice.

Microsoft has provided SharePoint Web services to work with sites and sub sites. The URL for this site is: http://Server_Name/[sites/][Site_Name/]_vti_bin/Webs.asmx.

It provides five methods. The GetAllSubWebCollection method returns the titles and URLs of all sites within the current site collection. Here we use GetWebCollection() to get the titles and URLs of all sites directly beneath the current site. This example shows the code to return all the sub sites one level down.

ws_webs.Webs ws = new ws_webs.Webs();
ws.Url = sSPSServer + @”/” +sSecondLevelSite + “/_vti_bin/Webs.asmx”;
ws.Credentials =System.Net.CredentialCache.DefaultCredentials;
System.Xml.XmlNode nd = ws.GetWebCollection();
XmlNodeList ndlist = nd.ChildNodes;
foreach (XmlNode xGet in ndlist)
{
string sWebTitle = xGet.Attributes[“Title”].Value;
string sOneSubSite =xGet.Attributes[“Url”].Value;
}

Read more:

http://blogs.msdn.com/sowmyancs/archive/2008/10/26/best-practices-sharepoint-object-model-for-performance-tuning.aspx

http://msdn.microsoft.com/en-us/library/ms473633.aspx

http://weblog.vb-tech.com/nick/archive/2006/04/10/1528.aspx

http://msdn.microsoft.com/en-us/library/webs.aspx

http://www.sharepointblogs.com/tanujashares/archive/2007/08/07/impersonation-in-sharepoint-2007.aspx

http://blogs.msdn.com/rogerla/archive/2008/10/04/updated-spsite-rootweb-dispose-guidance.aspx

Ah, I just noticed – GetSubwebsForCurrentUser only returns the subwebs directly under the given root (MSDN could be more clear on this, I think… but I guess we’ve all seen that before ;o). So I will need to make recursive calls to this method, in order to traverse the entire tree of subwebs for any given user. That sounds expensive to me, when you have a large (and deep) site collection.

If anyone knows how SharePoint does this on its own – e.g. on the MySite “Memberships” tab – I would be very interested in hearing about that.

In my next post I found a great solution how to solve this issue.

Thanks

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

 
%d bloggers like this: