Joel's SharePoint Architect Blog

SharePoint 2010, MOSS & WSS Tips and Consultancy Tales

Subscribe Subscribe  View Joel Jeffery's profile on LinkedIn
joelblogs.co.uk | joelj.co.uk | joeljeffery.co.uk | jfdiphoenix.co.uk

Posts Tagged ‘SharePoint Development’

SPSite and the Recycle Bin in SharePoint 2010 SP1

Service Pack 1 for SharePoint 2010 brought us a much-needed feature – the recycle bin for SPWeb and SPSite objects.

Recycling SharePoint Sites

If you want to move an SPWeb into the recycle bin programmatically, there’s the fairly-straightforward SPWeb.Recycle() method. Once you’ve invoked this, you can restore the SPWeb from the SPSite.RecycleBin object with the Restore() method.

But, how do I recycle and restore a site collection (SPSite)?

Recycling SharePoint Site Collections

Firstly, there’s no Recycle() method on the SPSite object. Invoking Delete() removes the SPSite immediately, unless you pass in an argument to get it to perform a gradual delete. The gradual delete process is carried out by the “Gradual Delete Timer Job”, whose purpose is to delete site collections efficiently 1000 database rows at a time.

However, it also has some nice side effects. The timer job only deletes site collections that were deleted more than 30 days ago (or whatever the recycle bin age is configured for the web application). In that intermediate time, the deleted site collections are available to be restored.

You can get at the deleted sites via the GetDeletedSites method of the SPWebApplication object. This returns a collection of SPDeletedSite objects, on which you can invoke the Restore method.

Sample Code

// get our web application
SPWebApplication webapp = SPWebApplication.Lookup(new Uri("http://sharepoint"));
// find our deleted site collection
foreach (SPDeletedSite site in webapp.GetDeletedSites("http://sharepoint/sites/myoldsite"))
{
    //restore it!
    site.Restore();
}

Enjoy!

Technorati Tags: SharePoint, SharePoint 2010, SharePoint Development

The purpose of STSADM’s “copyappbincontent” command is:

stsadm –o copyappbincontent

Copies Web application–specific files, such as page resource (*.resx) files from their respective locations in the 12\CONFIG folder to the correct location in each Web application on the computer.

According to TechNet, there is no equivalent PowerShell cmd-let http://technet.microsoft.com/en-us/library/ff621081.aspxt:

No PowerShell Equivalent to stsadm -o copyappbincontent

However, there is a PowerShell cmd-let called Install-SPApplicationContent:

Install-SPApplicationContent

Copies shared application data to existing Web application folders.

Now that sounds pretty similar.

I’ve tried this out – making a custom layouts.sitemap.xml file, and invoking Install-SPApplicationContent. It copies/merges the sitemap into the correct place under inetpub\wwwroot\wss\VirtualDirectories\*\_app_bin.

So, how dissimilar are they? I’ve heard it said that the PowerShell version won’t apply your changes to the whole farm, only the current server. But surely, that’s what stsadm does too?

Let’s use the rather fantastic open-source ILSpy replacement for Reflector to reflect over the code,

STSADM’s copyappbincontent decompiled

// Microsoft.SharePoint.StsAdmin.SPCopyAppBinContent
public override void Run(StringDictionary keyValues)
{
    SPServiceInstance sPServiceInstance = SPWebServiceInstance.LocalContent;
    if (sPServiceInstance != null && sPServiceInstance.Status == SPObjectStatus.Online)
    {
        SPWebService contentService = SPWebService.ContentService;
        contentService.ApplyApplicationContentToLocalServer();
    }
    sPServiceInstance = SPWebServiceInstance.LocalAdministration;
    if (sPServiceInstance != null && sPServiceInstance.Status == SPObjectStatus.Online)
    {
        SPWebService administrationService = SPWebService.AdministrationService;
        administrationService.ApplyApplicationContentToLocalServer();
    }
}

Microsoft.SharePoint.PowerShell’s Install-SPApplicationContent decompiled

if (sPWebServiceInstance.Status == SPObjectStatus.Online)
{
  SPWebService administrationService = SPWebService.AdministrationService;
  ServiceHelper.TryToControlService("W3SVC", false, out flag, out flag2);
  administrationService.ApplyApplicationContentToLocalServer();
}
if (null != SPWebServiceInstance.LocalContent)
{
  if (SPWebServiceInstance.LocalContent.Status == SPObjectStatus.Online)
  {
    ServiceHelper.TryToControlService("W3SVC", false, out flag3, out flag4);
    SPWebService contentService = SPWebService.ContentService;
    contentService.ApplyApplicationContentToLocalServer();
  }
}

Conclusion

So, there you have it. Like two completely dissimilar things… in a pod.

To be clear: you need to invoke either of these methods on each server in your farm to deploy content from the 14 hive to the IIS virtual directories.

Or have I missed something?

Technorati Tags: PowerShell, SharePoint, SharePoint 2010, SharePoint Administration, SharePoint Development

SharePoint Outlook Connector

Over the last few months I’ve had the privilege of being one of the contributors to the Sobiens SharePoint Outlook Connector project on CodePlex.

The project is a VSTO package that gives Outlook a new tree view panel showing connected SharePoint sites, providing a drag and drop interface to save emails and their attachments to the document libraries of your choice.

image

The Outlook Connector lets you drag emails from Outlook into document libraries in SharePoint.

The new release gives users a context menu when you right-drag email across, giving options to Copy or Move the email as an Outlook .msg file, or to Copy the email and attachments as Word documents.

The new version also shows all document library types, not only those made from the Document Library template.

Hopefully, we’ve also closed a few bugs without creating too many new ones!

Technorati Tags: Outlook, SharePoint, SharePoint 2010, SharePoint Development

SharePoint 2010 Locale Stapler / Master Locale

I’ve just put up another project on CodePlex. As usual, you can download the full project and source code for SharePoint 2010 Locale Stapler.

Why?

SharePoint doesn’t let you set a master locale per web application. SharePoint 2010 Publishing Features lets you specify that all sub sites inherit the locale settings from the parent… But this is sadly lacking.

How?

My project gives you a SharePoint farm solution with a couple of feature staplers (FeatureSiteTemplateAssociations) that fire for all templates (“GLOBAL”) at either the farm or web application level. On creation of a new site collection or site, the feature staple fires and looks up the regional settings of the root web at the root site collection for the web application, and then copies those settings to the current web (SharePoint site).

 

Manage Farm Features or Web Application Features

Code!

First off, here’s the code for the payload – the method to do the copying.

/// <summary>
/// Sets the locale for web.
/// </summary>
/// <param name="web">The web.</param>
public static void SetLocaleForWeb(SPWeb web)
{
    try
    {
        // find the Uri of the current web
        Uri currentWebUri = new Uri(web.Url);
        // work out the Uri for the root (e.g. 
        // http://webapp1/sites/site1/subsite1 becomes http://webapp1)
        UriBuilder rootWebUri = new UriBuilder(currentWebUri.Scheme,
            currentWebUri.Host, currentWebUri.Port);
        string rootSiteUrl = rootWebUri.ToString();
        // attempt to change the locale / regional settings by running as system...
        SPSecurity.RunWithElevatedPrivileges(delegate
        {
            // ...to access the root site/web of the web app
            using (SPSite rootSite = new SPSite(rootSiteUrl))
            {
                using (SPWeb rootWeb = rootSite.RootWeb)
                {
                    // ...and change the locale and regional settings of the current site
                    // to those of the root site collection root web's.
                    web.Locale = (System.Globalization.CultureInfo)rootWeb.Locale.Clone();
                    web.Update();
                    web.RegionalSettings = new SPRegionalSettings(rootWeb);
                    web.Update();
                }
            }
        });
    }
    catch (Exception ex)
    {
        LogError(System.Reflection.MethodBase.GetCurrentMethod().Name,
            ex.Message, ex.StackTrace);
    }
}

And here’s the code that’s run on FeatureActivated at the Web level (and a similar one at the Site level):

/// <summary>
/// Occurs after a Feature is activated.
/// </summary>
/// <param name="properties">An <see cref="T:Microsoft.SharePoint.SPFeatureReceiverProperties"/>
/// object that represents the properties of the event.</param>
public override void FeatureActivated(SPFeatureReceiverProperties properties)
{
    if (properties.Feature.Parent is SPWeb)
    {
        SPWeb web = (SPWeb) properties.Feature.Parent;
        Utilities.SetLocaleForWeb(web);
    }
}

Next, we need to create a a feature to do the stapling itself. This should include an element manifest (or elephant) with FeatureSIteTemplateAssociation nodes.

<?xml version="1.0" encoding="utf-8"?>
<Elements xmlns="http://schemas.microsoft.com/sharepoint/">
  <!--Web-level feature-->
  <FeatureSiteTemplateAssociation
    Id="dd5923f9-05a4-4d6a-a78f-0dd8b08ff079"
    TemplateName="GLOBAL" />
  <!--Site-level feature-->
  <FeatureSiteTemplateAssociation
    Id="54fa6d42-c145-49dc-b2eb-f5db548bc111"
    TemplateName="GLOBAL" />
</Elements>

Once again, don’t forget the full project and source code is available on CodePlex here: http://slash.codeplex.com.

Enjoy!

Technorati Tags: SharePoint, SharePoint 2010, SharePoint Administration, SharePoint Development

In a fit of community spiritness, I’ve decided to share my Google Maps Web Part, complete with source on CodePlex.

Example of joelblogs.co.uk Google Map Web Part

If you want a Sandbox Solution or a Farm Solution with a simple way of placing a Google Map onto a Web Part page, this is for you.

Check out the project here: http://sp2010googlemaps.codeplex.com.

Technorati Tags: Google Maps, SharePoint 2010, SharePoint Development, Solution Sandbox, WebParts