I am iterating through my Site Collections in SharePoint for a custom navigation. But I am trying to only allow the iteration to output nodes from one level deep after /sites/. For example, sites/IT.
At the moment, my method is iterating through all nodes. For example, sites/IT/Support.
private void GetSiteChildNodes(string siteName)
{
SPSecurity.RunWithElevatedPrivileges(delegate()
{
foreach (SPSite site in SPContext.Current.Site.WebApplication.Sites)
{
try
{
if (SPSite.Exists(new Uri(site.Url)) && site.ServerRelativeUrl.StartsWith(String.Format("/sites/{0}/", siteName)))
{
SPWeb subSites = site.RootWeb;
foreach (SPWeb cn in subSites.Webs)
{
navBuilder.AppendFormat("<li>{1}</li>", cn.Url, cn.Title);
}
}
}
finally
{
site.Dispose();
}
}
});
}
As you can see from my code, I am using "RootWeb" so that I ignore any child nodes from within the site. But that is not working.
Any help would be appreciated.
Try this:
using (SPSite oSiteCollection = new SPSite("http://<>"))
{
SPWeb web = oSiteCollection.OpenWeb("sites");
foreach (SPWeb oWebsite in web.Webs)
{
Console.WriteLine("Web site: {0}", oWebsite.Url);
oWebsite.Dispose();
}
}
Upon reading your comment, #R100, if you have managed paths defined for your subsites, then each managed path (no matter the logical hierarchy you put into place) is at the same level in the SPWebApplication.Sites collection.
For example, if you have the following hierarchy:
Root (/) [Site Collection]
Sites (/sites) [Site Collection]
IT (/sites/IT) [Site Collection]
Support (/sites/IT/Support) [Site Collection]
then SPWebApplication.Sites will contain each of those above in a flattened collection.
Additionally, the ServerRelativeUrl for site collections is all relative to the root of the SharePoint installation. Thus, what you see in the parenthesis in the above hierarchy is the ServerRelativeUrl for each of the nodes.
Thus, your check when you're iterating over your values is true for each child site collection under /sites/it (if it is the siteName you are passing down):
site.ServerRelativeUrl.StartsWith(String.Format("/sites/{0}/", siteName))
Related
Recently i came across with the following scenario:
Create a list item in custom list
Delete it using the batch deletion procedure (before delete it keep the UniqueId somewhere)
The item goes to the recycle bin
I have tried the web.RecycleBin.Delete(ids) (i used the UniqueId from step 2) and the error System.ArgumentException: ids at Microsoft.SharePoint.SPRecycleBinItemCollection.GetSortedIds(Guid[] ids, SPRecycleBinItemType[]& itemTypes) occurred
I tried to iterate through the recycle bin items and none of the deleted items had the UniqueId from step 2. Also i tried the SPRecycleBinItemCollection.GetItemById without any luck
my question is what guid expects the web.RecycleBin.Delete? I used the item.UniqueId but i think i'm wrong
Based on my test, you can try the following code. You can store the guid in a temp Array.
using (SPSite site = new SPSite(strSiteUrl))//SPContext.Current.Site)
{
using (SPWeb web = site.OpenWeb())
{
// Allow Unsafe Updates to prevent the cross site scripting
web.AllowUnsafeUpdates = true;
//// Get The SPList
SPList list = web.Lists["123"];
// Get the list items
SPListItem item = list.Items[0];
Guid strGuid = item.UniqueId;
item.Delete();
Guid[] guids = { strGuid };
web.RecycleBin.Delete(guids);
}
}
But I suggest you to use the CSOM to do it.
We have a SharePoint Web Application that has a number of Site Collections underneath 2 different managed paths (depts & offices) e.g
http://sharepoint.abc/depts/finance
http://sharepoint.abc/depts/isg
http://sharepoint.abc/offices/boston
http://sharepoint.abc/offices/chicago
When a user logs in they are presented with a list of the site collections they have read access to using the following c# code which is in the WebPart
SPSecurity.RunWithElevatedPrivileges(delegate()
{
using (SPSite spSite = new SPSite(SPContext.Current.Site.Url))
{
foreach (SPSite site in spSite.WebApplication.Sites)
{
try
{
var rootWeb = site.RootWeb;
if (rootWeb.DoesUserHavePermissions(SPContext.Current.Web.CurrentUser.LoginName, SPBasePermissions.ViewPages))
{
if (this.ValidSite(rootWeb.Url))
{
string url = GetRelativePath(rootWeb.Url);
allowedSites.Add(new SiteInfo(rootWeb.Title, url));
}
}
}
catch (Exception ex)
{
this.Controls.Add(new LiteralControl("<br/>GetAllowedSites Error: " + ex.Message));
}
}
}
});
It works fine but in production it takes 20-seconds to load the webpart (we have 700 site collections across the 2 paths).
I've used caching to hold the list of their sites but once the cache expires it takes 20-seconds to regenerate itself.
Ideally what I want is to see what Site Collections a user can access using the User rather than iterating through all the Site Collections to see if the user has access to them. Can this be achieved???
Thanks
eaigs
Try to use SPWeb.GetSubwebsForCurrentUser method to get the subsites beneath the current website of which the current user is a member.
I am running my code under administrative rights that iterates over different site->spweb to check the existance of a list. Strangely and for some site the code returns me that list does not exists(exception : List does not exists) Yet i can totally browse the list from browser on the same web
what am i missing here ?
EDIT:Adding Code
foreach (SPSite s in webApp.Sites)
{
foreach (SPWeb w in s.AllWebs)
{
try{
SPList sourceList = w.Lists["Ticks and Cross"];
}catch(exception ex){ ..... }
}
s.Dispose();
}
All sites has same templates, so there is no chance that list is not ther. For some site i get the sourceList, for other its exception, its really wired
I guess you pass incorrect parameter to Lists[]. You should specify valid guid, title or index of the list. Can you post your code?
From code I've automatically created a lot of similar sites (SPWeb) in my site collection from a site template (in Sharepoint Foundation). Every site has a home page on which I've added the "what's new" web part (found under "Social collaboration").
Even though the web part has several "target lists" (I'd have called it "source lists") added to it on the template site, this connection is lost on the sites created from the template. So I need to programmatically find all these web parts and add the target lists to them. Looping the web parts is not an issue - I've done that before - but I can't seem to find a word on the net on how to go about modifying this particular web part. All I have is a brief intellisense.
I've found out that it recides in the
Microsoft.SharePoint.Applications.GroupBoard.WebPartPages
namespace, but on the lists provided on MSDN this is one of very few namespaces that doesn't have a link to a reference documentation.
Does anyone have any experience of modifying this web part from code? If not, how would you go about to find out? I can't seem to figure out a method for this..
Here is how I did it. It worked really well. I had a feature that created several list instances and provisioned the What's New web part. In the Feature Receiver, I looped through all of the list instances, indexed the Modified field, and then added the list to the web part:
private void ConfigureLists(SPWeb web, SPFeatureReceiverProperties properties)
{
List<Guid> ids = new List<Guid>();
SPElementDefinitionCollection elements =
properties.Feature.Definition.GetElementDefinitions(new CultureInfo((int)web.Language, false));
foreach (SPElementDefinition element in elements)
{
if ("ListInstance" == element.ElementType)
{
XmlNode node = element.XmlDefinition;
SPList list = web.Lists[node.Attributes["Title"].Value];
SPField field = list.Fields[SPBuiltInFieldId.Modified];
if (!field.Indexed)
{
field.Indexed = true;
field.Update();
}
ids.Add(list.ID);
}
}
string targetConfig = string.Empty;
foreach (Guid id in ids)
{
targetConfig += string.Format("'{0}',''\n", id);
}
SPFile file = web.GetFile("Pages/default.aspx");
file.CheckOut();
using (SPLimitedWebPartManager manager = file.GetLimitedWebPartManager(PersonalizationScope.Shared))
{
WhatsNewWebPart webpart = null;
foreach (System.Web.UI.WebControls.WebParts.WebPart eachWebPart in manager.WebParts)
{
webpart = eachWebPart as WhatsNewWebPart;
if (null != webpart)
{
break;
}
}
if (null != webpart)
{
webpart.TargetConfig = targetConfig;
manager.SaveChanges(webpart);
}
}
file.CheckIn("ConfigureWebParts");
file.Publish("ConfigureWebParts");
file.Approve("ConfigureWebParts");
}
If you are unsure about the property, export the web part from the browser, then open the .webpart/.dwp file with a text editor. Somewhere in the xml will be a reference to the source list.
*.webparts are usually easier to modify, just set the property.
*.dwps are harder because you sometimes have to get the property (eg ViewXML), then load it into an XmlDocument, then replace the property, and write the xml document string value back to ViewXML.
Is there a way to get a site's (site collection) site directory, the one which is defined within the web site collection setting of a collaboration or publishing portal?
Of course I could iterate through all the SPWebs of the site collection but I hope there's a easier way to get the directory as the information seems to be already stored somewhere.
Bye,
Flo
UPDATE
Of course I want to get the information programmatically.
The site directory path is stored in the root web property bag
The code below taken from an internal utility class SiteDirectoryUtil shows the logic of how to determine the path
internal static string GetLocalSiteDirectoryLocation(SPWeb rootWeb)
{
if (rootWeb != null)
{
if (rootWeb.AllProperties.ContainsKey("DefaultSiteDirectorySiteId"))
{
string str = rootWeb.AllProperties["DefaultSiteDirectorySiteId"] as string;
if (string.IsNullOrEmpty(str))
{
return string.Empty;
}
if (!rootWeb.AllProperties.ContainsKey("DefaultSiteDirectoryWebId"))
{
return string.Empty;
}
string str2 = rootWeb.AllProperties["DefaultSiteDirectoryWebId"] as string;
if (string.IsNullOrEmpty(str2))
{
return string.Empty;
}
try
{
using (SPSite site = new SPSite(new Guid(str), rootWeb.Site.Zone))
{
using (SPWeb web = site.OpenWeb(new Guid(str2)))
{
return web.ServerRelativeUrl;
}
}
}
catch (FileNotFoundException)
{
return string.Empty;
}
}
else
{
return string.Empty;
}
}
return string.Empty;
}
Are you referring to the site directory that is under the Site Content and Structure?
If so, you can browse to http://sitename/_layouts/sitemanager.aspx to see site directory (assuming you have sufficient privileges to the site).
For what it's worth, if you have access to the WSS database(s) you can either leverage off existing SPs or create your own. I wanted to return things like 'RequestAccessEmail' and incorporate that into our own site maps (handy to know who the site owner is sometimes). Our SP at it's most basic...
CREATE PROCEDURE [dbo].[my_sitemap](
#PartialUrl nvarchar(260)
)
AS
SELECT ID, FullUrl, Title, RequestAccessEmail
FROM Webs
WHERE FullUrl LIKE #PartialUrl + '%'
ORDER BY FullUrl
GO
Worked very well for me. Hope this helps.