SharePoint: How to determine a site's site directory programmatically - sharepoint

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.

Related

SharePoint Get Site Collections for Current User

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.

Need to change web.server.host property during runtime

Please help me in below problem
I have single liferay instance and it has single site on it. This single site is serving multiple clients and they access the site using their dedicated domain name
xxx.mysite.com -> domain name for the client xxx
yyy.mysite.com -> domain name for the client yyy
These domain names are configured in apache web server which is sitting infront of liferay instance. I used property in portal-ext.properties web.server.host to configure the webserver information in liferay. Liferay uses this property to generate all the links on the page(if this property is not mentioned it uses the servername to generate the urls). But using this I can only define one site at a time. I can not achieve above functionality. I went to the liferay code and in PortalImpl.java it has following code
public String getPortalURL(
String serverName, int serverPort, boolean secure) {
StringBundler sb = new StringBundler();
if (secure || Http.HTTPS.equals(PropsValues.WEB_SERVER_PROTOCOL)) {
sb.append(Http.HTTPS_WITH_SLASH);
}
else {
sb.append(Http.HTTP_WITH_SLASH);
}
if (Validator.isNull(PropsValues.WEB_SERVER_HOST)) {
sb.append(serverName);
}
else {
sb.append(PropsValues.WEB_SERVER_HOST);
}
if (!secure) {
if (PropsValues.WEB_SERVER_HTTP_PORT == -1) {
if ((serverPort != Http.HTTP_PORT) &&
(serverPort != Http.HTTPS_PORT)) {
sb.append(StringPool.COLON);
sb.append(serverPort);
}
}
else {
if (PropsValues.WEB_SERVER_HTTP_PORT != Http.HTTP_PORT) {
sb.append(StringPool.COLON);
sb.append(PropsValues.WEB_SERVER_HTTP_PORT);
}
}
}
if (secure) {
if (PropsValues.WEB_SERVER_HTTPS_PORT == -1) {
if ((serverPort != Http.HTTP_PORT) &&
(serverPort != Http.HTTPS_PORT)) {
sb.append(StringPool.COLON);
sb.append(serverPort);
}
}
else {
if (PropsValues.WEB_SERVER_HTTPS_PORT != Http.HTTPS_PORT) {
sb.append(StringPool.COLON);
sb.append(PropsValues.WEB_SERVER_HTTPS_PORT);
}
}
}
return sb.toString();
}
In above method it uses the web.server.host property defined in poratal-ext.properties and constructs the URLs. Now I need to overwrite this method to determine the web server host during runtime.
my question are.
How to overwrite this function in PoralImpl.java? Do I need use extension to achieve this?
Is anyother way(betterway) to achieve this functionality.
I am using liferay 6.1.0 GA-1/tomcat bundle
Yes, the only way to override Liferay's core functionality (= code that exists in "portal-impl.jar") is to use ext plugin, http://www.liferay.com/community/wiki/-/wiki/Main/Ext+Plugin

How to programmatically add target lists to the what's new web part in Sharepoint (or how to handle undocumented namespaces)

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.

MapPath or equivalent to use in an installation application

I need to check a .config file in an installation application (iis custom action in a WIX project). The user picks a website and enters a virtual directory name. I can't do a http read to retrieve the config file as ASP.NET does not serve config files.
How can I find the local disk path of the selected website and virtual directory?
After further searching, I ended up using DirectoryServices. I'm posting my solution here for others.
If there is a better way, please still post it.
static string FindVirtualDirectoryPath(string virtualDirectoryName)
{
return FindVirtualDirectoryPath(null, virtualDirectoryName);
}
static string FindVirtualDirectoryPath(string siteName, string virtualDirectoryName)
{
DirectoryEntry iis = new DirectoryEntry("IIS://localhost/W3SVC");
foreach (DirectoryEntry index in iis.Children)
{
if (index.SchemaClassName == "IIsWebServer")
{
int id = Convert.ToInt32(index.Name);
DirectoryEntry site = new DirectoryEntry(string.Concat("IIS://localhost/W3SVC/", id));
string iSiteName = site.Properties["ServerComment"].Value.ToString();
if (iSiteName == siteName || (string.IsNullOrEmpty(siteName) && id == 1))
{
DirectoryEntry rootVDir = new DirectoryEntry(string.Concat("IIS://localhost/W3SVC/", id, "/Root"));
foreach (DirectoryEntry vDir in rootVDir.Children)
{
if (vDir.SchemaClassName == "IIsWebVirtualDir" && vDir.Name.ToLower() == virtualDirectoryName.ToLower())
{
return vDir.Properties["Path"].Value.ToString();
}
}
}
}
}
return null;
}
Have you tried using the standard WiX IIsExtension for this? Just capture the user input in a property, and then use standard elements like iis:WebSite and iis:WebVirtualDir to create a virtual directory in appropriate web site.

Web Part connections in site definitions

I have requirement of specifying web part connections in onet.xml. So when site is created using this site definition the said web parts are already connected and ready to use. Which properties I need to specify for that particular web parts in onet.xml.
I have also hit the wall on this one sometime last year! It looks like connections can no longer be specified on Web Parts in the new .webpart format as they could in the old .dwp format. I ended up including a custom feature in the site definition like kpinhack also suggests. My code for connecting the Web Parts is listed below. The method is just designed for connecting two Web Parts of different types - it does not support multiple Web Parts of the same type on the same page. But I am sure you'll catch the general idea.
private void ConnectWebParts(SPWeb web, string pageName, Type providerType, Type consumerType)
{
SPFile file = web.GetFile(pageName);
SPList list = null;
if (file.InDocumentLibrary)
{
list = file.Item.ParentList;
if (list.ForceCheckout) file.CheckOut();
}
SPLimitedWebPartManager webPartManager =
web.GetLimitedWebPartManager(
pageName,
System.Web.UI.WebControls.WebParts.PersonalizationScope.Shared);
WebPart provider = null;
foreach (WebPart wp in webPartManager.WebParts)
{
if (wp.GetType() == providerType)
{
provider = wp;
break;
}
}
foreach (WebPart consumer in webPartManager.WebParts)
{
if (consumer.GetType() != consumerType) continue;
ProviderConnectionPointCollection providerConnections = webPartManager.GetProviderConnectionPoints(provider);
ProviderConnectionPoint providerConnection = providerConnections[0];
ConsumerConnectionPointCollection consumerConnections = webPartManager.GetConsumerConnectionPoints(consumer);
ConsumerConnectionPoint consumerConnection = consumerConnections[0];
SPWebPartConnection con = webPartManager.SPConnectWebParts(provider, providerConnection, consumer, consumerConnection);
webPartManager.SPWebPartConnections.Add(con);
}
if (list != null)
{
if (list.ForceCheckout)
{
file.CheckIn("Added Web Part Connections");
}
if (list.EnableVersioning && list.EnableMinorVersions)
{
file.Publish("Added Web Part Connections");
}
}
}
I would configure the WebParts in the SiteProvisioning-Feature, by implementing the 'OnActivated'-Eventhandler. That way the code will run when the website is created, and you can handle errors the way you like it (i.e. if the WebParts are not available when the website is created - for whatever reason)
I hope this helps!
you would need to use the < AllUsersWebPart > tag to declare your web parts, and then declare your connections within the enclosed < WebPart > elements.
example

Resources