Skip Ribbon Commands
Skip to main content
SPMCM.ME > Blog
May 09
Setting SharePoint content databases offline via Script

If you followed the TechNet documentation for Set-SPContentDatabase and try to take SharePoint content databases offline by running Set-SPContentDatabase –Status Offline you will be really disappointed to know that it just does not work. If you look at the TechNet documentation, the type associated with Status is Microsoft.SharePoint.Administration.SPObjectStatus, valid values are “Online”, “Disabled”, “Offline”, “Unprovisioning”, “Provisioning”, “Upgrading” See this link for more information

Unfortunately passing none of the above values work. So I decided to look into the source of manage content database settings page by doing a view source in browser

cdbsettings

What I found in view source is valid values for Database Status is 0 and 1 as shown in screenshot below.

cdbsettings1

So to Take Content Database Offline you have to run the following script

Get-SPContentDatabase “{replace with name of content database}” | Set-SPContentDatabase –Status 1

Bring Content Database Back Online

Get-SPContentDatabase “{replace with name of content database}” | Set-SPContentDatabase –Status 0

Cheers,

</Ram>

May 08
Setting Description to null when creating custom SP Groups via code can cause search crawler to fail

Recently was pulled into troubleshooting a search issue at a customer which prompted me to write this post. Basically the issue was there were excessive number of errors in crawl log. All error items in crawl log pointed to pretty much the same error.

Crawl fails with an error The SharePoint item being crawled returned an error when requesting data from the web service. ( Error from SharePoint site: Data is Null. This method or property cannot be called on Null values. )

See the screen shot below that shows errors in crawl log.

crawlerror

It turns out the cause of this Issue is because there were custom SharePoint groups created via code at the time Site was provisioned via a Provisioning engine with description property set to null.

Here is a simple PowerShell script to check if you have Custom SharePoint Groups with Description set to null.

Add-PSSnapin Microsoft.SharePoint.PowerShell –ea SilentlyContinue

Function ReportSPGroupDescriptionIsNull($url)
{
    $site = Get-SPSite($url)
    ForEach($web in $site.AllWebs)
    {
        Write-Host -ForeGroundColor white -BackGroundColor Blue "Checking site $($web.Title)"
        ForEach($group in $web.Groups)
        {
            if($group.Description -eq $null)
            {
                Write-Host "Description is null for $($group.Name) SharePoint Group"
            }
        }
    }
}

ReportSPGroupDescriptionIsNull({replace with SC url})

So if you run into this issue check your code and see if you are setting the description to a string value when creating custom SharePoint groups.

I also came across this support article that describes this issue http://support.microsoft.com/kb/2323206

Cheers,

</Ram>

February 08
ADFS Auto Certificate Rollover and Impact on SharePoint 2010 Claims Web Application

ADFS has a feature called Auto Certificate Roll Over which generate a new certificate when the current one nears expiration, when this happens with the Token Signing Certificate all your SharePoint 2010 Claims web applications will start failing with a “root of certificate chain not a trusted root authority” error

If you look through the event logs on ADFS server you will see following entry

MSIS10004: Certificate rollover service has set certificate with thumbprint '52FBF8F2B01E0CED0473858CA526BB48446EB9E3' as primary 'Encryption' certificate.

You can disable auto certificate roll over by running following PS

Add-PSSnapin Microsoft.ADFS.PowerShell

Set-ADFSProperties –AutoCertificateRollOver $false

Fix for this is you need to export the new primary token signing certificate from ADFS and add to security trusts

Sample PowerShell

$cert = Get-PfxCertificate($CertFile)

New-SPTrustedRootAuthority -Certificate $cert –Name “ADFS Token Signing”

<update> forgot to add this step, you also need to re-create your TrustedIdentityTokenIssuer</update>

 

Technorati Tags: ,

Cheers,

</Ram>

January 20
SharePoint 2010 language packs

Wow my first blog post of the year, been a crazy month, I wanted to write this blog post for quite some time, I have been in few large global projects where the program owner goes we need to install every language pack in our farm, it’s a global deployment blah blah blah. My first response is why? response I’ve gotten often is we are going to need it in future, might as well install it all, etc.

If you look at the list of Server language packs SharePoint 2010 has about 40 lets assume you have a 10 server farm 4 WFEs and 6 Application servers that’s 400 (40*10 servers) extra installs not counting other environments by the way. Each time service packs come out for Language packs that’s another 400 installs once again not counting other environments. Now of course as any good IT pro I know you will script this out but my point is you are shooting yourself on the foot. So before making decision on how many SharePoint language packs do you need, interview potential site owners and understand what their needs are as far as being able to create sites in different languages. Don’t assume that just because they are in a different region means the would want to create sites in different languages

Language packs are also needed if you want to leverage MUI which is a new feature in SharePoint 2010. If you are interested check out my posts on MUI

Automating Language pack Install using SPModule

Now lets look at scripting installation of SharePoint Server Language Packs using SPModule. If you don’t know what SPModule is, it’s a set of scripts provided by SharePoint product group for automating installation of SharePoint 2010, this can also be used to install the language packs. Download SPModule here http://www.microsoft.com/download/en/details.aspx?displaylang=en&id=6194

See Full list of language packs here http://technet.microsoft.com/en-us/library/ff463597.aspx download and take some time/planning to figure out exactly which language packs you need.

What about SP1 for Server Language Packs

Don’t just apply SP1 for your SharePoint Server, once you install language packs you now have to keep your language packs updated as well, so don’t ignore it. I recommend slipstreaming Server Language Pack 2010 RTM bits + SP1 for Server Language Pack 2010 if you are doing a fresh install, you can download SP1 for Server Language Packs here http://www.microsoft.com/download/en/details.aspx?displaylang=en&id=26621 be sure to select the appropriate language before downloading otherwise you will get the same file, I had one customer called me back saying you are full of it, it English always Smile see image below

languagepack

Steps for slipstreaming language packs are exactly identical as slipstreaming SP1s and patches for SharePoint 2010, there is several posts so I won’t try to bore you with same details. One other thing, you don’t need to install SharePoint foundation language packs if you have SharePoint Server 2010, both Foundation and Server language packs are packaged together.

Preparing for Install

Create a folder in your build directory and lets call it Server Language Packs, for each language pack you will be installing create sub folders and name them to match the language code as show in image below

languagepack1

I’ve extracted the “ServerLanguagePack.exe” file using “/extract” switch on to folder that corresponds to each server language pack downloaded, additionally I extracted the SP1 for Server Language Pack 2010 to updates folder within each server language pack folder

PowerShell Script to Install Server Language Pack

Script below takes language pack folder as parameter and loops through every child item to kick off a language pack install using SPModule

Function InstallLanguagePacks
{
    param([string] $lpDir)
   
    Try
    {
        $runPsConfig = $false
        $PSConfig = "$env:CommonProgramFiles\Microsoft Shared\Web Server Extensions\14\BIN\psconfig.exe"
   
        if(!(Test-Path $lpDir))
        {
            Write-Warning "LanguagePack folder does not exist"
            break;
        }

        $installedOfficeServerLanguages = [string] (Get-Item "HKLM:\Software\Microsoft\Office Server\14.0\InstalledLanguages").GetValueNames() | ? {$_ -ne ""}
        ForEach ($folder in Get-ChildItem $lpDir)
        {
            If(!($installedOfficeServerLanguages.Contains($folder.Name.ToLower())))
            {
                Write-Host -ForeGroundColor White " - Installing Language Pack" $folder.Name
                $lpSetupDir = Join-Path $lpDir $folder.Name
               
                Install-SharePoint -DisplayLevel $displaylevel -LoggingType $loggingType -LogPath $logpath -LogTemplate $loggingtemplate -PhysicalSKU "SharePointLanguagePack" -SetupExePath $lpSetupDir -LanguagePacks $folder.Name -SkipPreReqInstaller
                $runPsConfig = $true ;
            }
            Else
            {
                Write-Host -ForeGroundColor White " - $folder.Name language pack already installed on server, skipping..."
            }
        }

        # If there were language packs installed we need to run psconfig to configure them
        If ($runPsConfig)
        {
            Write-Host -ForegroundColor White " - Running PSConfig & Configuring Language Packs..."
            Start-Sleep 20
            # Run PSConfig.exe
            Start-Process -FilePath $PSConfig -ArgumentList "-cmd upgrade –inplace b2b -wait -force" -NoNewWindow -Wait
        }
    }
    Catch
    {
        Write-Host $_
        Break;
    }
}

InstallLanguagePacks -lpDir "C:\{customer farm}\Software\SharePoint Server Language Packs"

Hope this helps

Cheers,

</Ram>

Technorati Tags:
January 05
Speaking at Project Conference 2012 in Phoenix, AZ

This March, Phoenix Arizona will host the Project Conference 2012 and I will be presenting a session on leveraging Microsoft Project Server 2010 in SharePoint 2010 Extranet Environments. If you currently have deployed SharePoint 2010 Extranet you should come check this session out as I will be trying to convince you why you all should seriously look at deploying Project Server 2010 together with SharePoint in your Extranet. I will be covering everything from licensing to business scenarios, claims identity federation scenarios. So what are you waiting for head over here http://www.msprojectconference.com/pages/register.aspx and register

I look forward to seeing you there

Cheers,

</Ram>

PC2012_Sig_160x98_Speaker

December 12
Issue regarding Installing SharePoint 2010 prerequisites from network share

I came across an issue while installing SharePoint 2010 for a customer which prompted this blog post. Like any good SharePoint Pro I only do scripted installs. If you haven’t checked out PowerShell scripts published by SharePoint Product team check out this TechNet article http://technet.microsoft.com/en-us/library/cc262839.aspx for more info

Any ways now regarding the issue, Customer environment servers have no internet access, by default when you run the prerequisite installer, it will attempt to download all prerequisites from the internet which was not going to work for this scenario as servers don’t have internet access, which means I had to download all prerequisite software on to network share and use an arguments file, TechNet provides a nice article that covers this scenario http://technet.microsoft.com/en-us/library/ff686793.aspx#install. Now to the problem, I created my answer file by copying from this article and found out that the prerequisite installer tool still tried to download WIF from internet which failed as server did not have internet connection. It turns out the command line switch for WIF when installing on Windows 2008 R2 is IDFXR2 instead of just IDFX. You can see this by running the prerequisite installer tool with /? option. I would hope the above TechNet article would be updated at some point to include this information, in the mean time if you ran into this you know what to do

Cheers,

</Ram>

Technorati Tags:
October 09
Using LINQ to retrieve list of external lists in current web

This one is a short little post, I was looking for a way to use LINQ to query list of external lists created in current web, I didn’t want to enumerate through list collection and check the base template. See the code sample below.

Cheers,

</Ram>

var lists = (from el in web.Lists.OfType<SPList>()
            where el.BaseTemplate == SPListTemplateType.ExternalList
           select el);

 

Technorati Tags: ,
September 01
Updating “safecontrol” entries after a namespace rename for web part

I have had couple of developers tell me the steps they take to update the safecontrol entry in web.config to avoid the dreaded “Type not registered as safe” error after renaming the namespace, which really prompted me to write this post

By default when you add a web part to your SharePoint project in Visual Studio, VS creates a folder under your project in file system to store all web part files, if you look at web part’s code behind file the namespace will contain the folder name by default. So for example if the core namespace for your web part library “contoso.sharepoint.webparts” and let’s say you added a “StockWebPart” to show stock quotes, namespace for your web part code behind will say “contoso.sharepoint.webparts.stockwebpart” also the full type name for stock web part will look like “contoso.sharepoint.webparts.stockwebpart.stockwebpart”

So to keep things clean and you are a good SharePoint developer when you rename the namespace. There is an easier way to update the Safe Control entries from Visual Studio.

If you click on the web part item in VS in properties window you will notice an option called Safe Control Entries

safecontrol1

If you click on the “..” button this will bring up a dialog where you can update the safe control entries that will be written on to the web.config. See image below

safecontrol2

That’s about it

Hope that helps

Cheers,

</Ram>

Technorati Tags:
August 27
Aggregating recycle bin items using PowerShell

I’ve always wished since recycle bin was first introduced in SharePoint 2007 that It would be nice from an Administrator perspective to be able to see recycle bin items aggregated so that they can see how much space is being taken up by recycle bin within sites and subwebs. I wrote a simple PowerShell script to accomplish this. If you are interested in the script you can download it from TechNet script repository, here is the direct link for it http://gallery.technet.microsoft.com/scriptcenter/Script-to-aggregate-5dd4f358

Script is fairly straight forward, it loops through recycle bin items from site collections and subwebs and adds it to an array list which is then returned to output. You can simple pipe the output to do things like format-table, filter to see items that are greater than specific size and even sum up all the size values (which is in bytes BTW) to see how much total space recycle bin is taking.

Image below shows recycle bin items aggregated for all site collections and subwebs in a web application

recyclebinreport

If you want more info about the script head over to the link and check it out

Cheers,

</Ram>

August 18
Cross Site Collection List using OData and Business Connectivity Services

In the article I will walk through how to use OData, Business Connectivity Services to create a solution for cross site collection list scenarios

For the purpose of this article I created a Site Collection in my environment and named it “Shared”, full URL of this site collection is “http://team.contoso.local/sites/shared”, this site collection also contains a “Contacts” list named “Team Contacts”. Goal is to expose this list to other site collections so you have all the data in one central location and still accessible from other site collections as if the list was available locally within the site collection.

Create a empty SharePoint project within Visual Studio 2010, be sure to chose farm solution. Add a BDC Model item to your project in Visual Studio 2010

odata2

Add a web service reference to your BDC Model project in Visual Studio 2010, see image below

odata1

Add an entity into your model by choosing the entity option from the toolbox and dragging it on to the design surface. Rename the entity to “Contacts”, add an identifier to the entity, name it “ID” and changed the data type to System.Int32

Using the BDC Method Details window add a finder method to the “Contacts” entity, this will create a “ReadList” method, next we need to change the data type of “Contacts” typedescriptor to use the OData entities generated by Visual Studio 2010 when we added the OData service reference. See image below

odata3

Set up additional typedescriptors, see image below

odata4

Next create a SpecificFinder method, add “Creator”, “Updater” and “Deleter” If you want to provide full CRUD capabilities.

At this point we are pretty much ready to wire up the entity service class, I have gone ahead and implemented all the CRUD methods. See the code from the entity service class below. Not a whole lot to explain, I’m using OData to perform CRUD operations against the “Team Contacts” list in the shared site collection

   1: public static IEnumerable<TeamContactsItem> ReadList()
   2: {
   3:     SharedSiteCollectionDataContext dc = new SharedSiteCollectionDataContext(new Uri("http://team.contoso.local/sites/shared/_vti_bin/listdata.svc"));
   4:     dc.Credentials = CredentialCache.DefaultNetworkCredentials;
   5:  
   6:     var contacts = from c in dc.TeamContacts
   7:                 orderby c.Id
   8:                 select c;
   9:     return contacts;
  10: }
  11:  
  12: public static TeamContactsItem ReadItem(int id)
  13: {
  14:     SharedSiteCollectionDataContext dc = new SharedSiteCollectionDataContext(new Uri("http://team.contoso.local/sites/shared/_vti_bin/listdata.svc"));
  15:     dc.Credentials = CredentialCache.DefaultNetworkCredentials;
  16:  
  17:     var contact = (from c in dc.TeamContacts
  18:                 where c.Id == id
  19:                 select c).FirstOrDefault();
  20:     return contact;
  21: }
  22:  
  23: public static TeamContactsItem Create(TeamContactsItem newContacts)
  24: {
  25:     SharedSiteCollectionDataContext dc = new SharedSiteCollectionDataContext(new Uri("http://team.contoso.local/sites/shared/_vti_bin/listdata.svc"));
  26:     dc.Credentials = CredentialCache.DefaultNetworkCredentials;
  27:  
  28:     dc.AddToTeamContacts(newContacts);
  29:     dc.SaveChanges();
  30:  
  31:     return newContacts;
  32: }
  33:  
  34: public static void Delete(int id)
  35: {
  36:     SharedSiteCollectionDataContext dc = new SharedSiteCollectionDataContext(new Uri("http://team.contoso.local/sites/shared/_vti_bin/listdata.svc"));
  37:     dc.Credentials = CredentialCache.DefaultNetworkCredentials;
  38:  
  39:     TeamContactsItem contactToDelete = (from c in dc.TeamContacts
  40:                               where c.Id == id
  41:                               select c).FirstOrDefault();
  42:  
  43:     if (contactToDelete != null)
  44:     {
  45:         dc.DeleteObject(contactToDelete);
  46:         dc.SaveChanges();
  47:     }
  48: }
  49:  
  50: public static void Update(TeamContactsItem contacts)
  51: {
  52:     SharedSiteCollectionDataContext dc = new SharedSiteCollectionDataContext(new Uri("http://team.contoso.local/sites/shared/_vti_bin/listdata.svc"));
  53:     dc.Credentials = CredentialCache.DefaultNetworkCredentials;
  54:  
  55:     //retrieve the contact to update
  56:     TeamContactsItem contactToUpdate = (from c in dc.TeamContacts
  57:                                         where c.Id == contacts.Id 
  58:                                         select c).FirstOrDefault();
  59:     if (contactToUpdate != null)
  60:     {
  61:         //set fields to update
  62:         contactToUpdate.FirstName = contacts.FirstName;
  63:         contactToUpdate.LastName = contacts.LastName;
  64:         contactToUpdate.HomePhone = contacts.HomePhone;
  65:         contactToUpdate.Address = contacts.Address;
  66:         contactToUpdate.BusinessPhone = contacts.BusinessPhone;
  67:         contactToUpdate.City = contacts.City;
  68:         contactToUpdate.Company = contacts.Company;
  69:         contactToUpdate.CountryRegion = contacts.CountryRegion;
  70:         contactToUpdate.EMailAddress = contacts.EMailAddress;
  71:         contactToUpdate.FaxNumber = contacts.FaxNumber;
  72:         contactToUpdate.FullName = contacts.FullName;
  73:         contactToUpdate.JobTitle = contacts.JobTitle;
  74:         contactToUpdate.MobileNumber = contacts.MobileNumber;
  75:         contactToUpdate.StateProvince = contacts.StateProvince;
  76:         contactToUpdate.WebPage = contacts.WebPage;
  77:         contactToUpdate.ZIPPostalCode = contacts.ZIPPostalCode;
  78:         
  79:         //update the entity
  80:         dc.UpdateObject(contactToUpdate);
  81:         dc.SaveChanges();
  82:     }
  83: }

 

Deploy the BCS solution to farm and create an external list called “Contacts” in root site collection “http://team.contoso.local”, I usually provide a site collection scoped feature  with a feature receiver that programmatically creates the external list when ever I use .NET connectivity to create my BCS entities.

End Result:

Image below shows “Team  Contacts” list in “Shared” Site Collection

odata5

Image below shows the external list “Contacts” created in root site collection, as you can see there is full CRUD support and users can work with the contacts data same way they would if the “Contacts” list was available locally within the site collection, thanks to external list feature within BCS that provides the familiar list like user interface Smile

Odata6

 

Couple of things to keep in mind regarding working complex data types in BCS, see this article from BCS team http://blogs.msdn.com/b/bcs/archive/2010/02/10/working-with-complex-data-types-in-business-connectivity-services.aspx also same approach can be used to work around the data access limitation in Sandbox solution, only change would be to leverage secure store in .NET connectivity project

Hope that helps

Cheers,

</Ram>

Technorati Tags: ,
1 - 10Next
About this blog
Welcome to my blog. My name is Ram Gopinathan and I'm an Independant SharePoint Consultant/Architect currently based out of Chicago, IL. Opinions expressed in this blog are my own and does not in any way or form represent the views of my company or its clients

Twitter