Wednesday, December 15, 2010

Missing Term Store Management link under Site Settings

I came across an interesting question today, the user was not able to find Term Store Management link under Site Settings.

I investigated it further and verified that it was not available to one of my site collection even if an appropriate Service Application was running fine and associated with my Web Application.

As usual, I went to the “SharePoint Root” to go to the “root of the problem” and found that the link is being made available by a FEATURE named “TaxonomyFieldAdded” and the stapling was made by FEATURE named “TaxonomyFeatureStapler”. I found that the Stapling FEATURE did not include Blank site template… Remember! it includes GLOBAL site template which includes everything but the blank site template!

So there it is! If you create your site collection using Blank site template, “Term Store Management” link will not be available in Site Settings.. Hope this was helpful!

Thursday, November 4, 2010

Hiding “New Site” in Site Actions Menu

Today, I came across an interesting question in a forum and the question was.. “How to hide “New Site” option available in the Site Actions menu when the publishing feature is enabled.

Initially, I thought it would be easy with HideCustomAction element in a custom feature. However, it did not turn out to be that easy. After some investigation I figured out that that menu item is created by Publishing feature in code. HideCustomAction would have helped me if it was created declaratively. So, I took the same approach as Publishing feature to hide the menu. Here is the solution:

This was tough when I started doing it today. It is possible via feature using a CustomAction element in the elements.xml and some code. I tried a no-code solution but it was not possible.

 <CustomAction
        Id="HideCreateSiteInSiteActions"
        Location="Microsoft.SharePoint.StandardMenu"
        GroupId="SiteActions"
        Sequence="901"
        Title="Publishing SiteActions Menu Customization"
        ControlAssembly="Your Assembly full name"        ControlClass="your class full name">
  </CustomAction>

Following code would go in class:

public class YourClassName : WebControl
    {
        protected override void OnLoad(EventArgs e)
        {
            var siteActions = ToolBarMenuButton.GetMenuControl(this);
            siteActions.MenuControl.PreRender += (o, args) =>
            {
                var targetMenu = siteActions.GetMenuItem("MenuItem_CreateSite");
                if (targetMenu == null) return;
                siteActions.MenuControl.HiddenMenuItems.Add(targetMenu);
            };
        }       
    }

The scope of your feature would be "site". Also, don't forget to put SafeControl entry for your class in the web.config or it may not work.

Monday, November 1, 2010

I am active at StackOverflow.com and SharePointOverflow.com

Recently I came across a presentation from Scott Hanselman and he insisted that “Every Developer must have a blog.. period..”. After inspired by that presentation, I thought of giving it a try and I decided to spend a few hours every week for these two activities:

1. Help the community by answering the questions they have!

2. Blog interesting things that I come across

For the first activity, I decided to actively participate in SharePoint 2007/2010 related questions posted by people at StackOverflow.com and SharePointOverflow.com. I like these sites because they are simple and fast.. very simple reason indeed! And here I am, after one month of this activity, I gave about 50 answers and collected about 700 points. Wow, looking back, I did not anticipate that I would give that many answers and get many points! I must state that I enjoyed a lot while helping the community, I learnt a lot. Many of those answers that I have required me to research and even work with VS.NET to get the correct answer. So, I want to continue with this… and who knows after a year I may be recognized by Microsoft as an MVP… that would a quite an achievement.. pinch me, I am dreaming!

This blog and the posts that created last month is the proof of my second activity. Let’s see how many interesting things I come across and I am able to blog it or not!

Wrong values for Location and GroupID of Custom Actions specified in SharePoint SDK

While I was researching a problem reported by a user @ SharePointoverflow.com, I realized that if I wanted to add a link to Central Admin site’s “Site Collection” section of “Application Management” and use the Location and GroupID specified in SharePoint SDK, it would NOT work!

It wasn’t a pleasant surprise to me. The problem which lead me to investigate the issue is: http://www.sharepointoverflow.com/questions/6689/central-admin-custom-action-menu-not-appearing

If you are interested in correct values, please visit: http://bloggingabout.net/blogs/arjen/archive/2010/02/04/custom-action-definitions-in-sharepoint-2010.aspx

I finally found the problem and answered to the user. It turned out that I have to mark the feature element with AutoActivateInCentralAdmin="TRUE" so that when the feature which is scoped at “Web” would activate automatically in the central administration and display my custom action.

Thursday, October 21, 2010

Assigning Secondary Site Collection Administrators in bulk

 

I recently came across a situation where I needed to make a particular user the site collection administrator for all site collections within my web applications.

Thanks to the PowerShell for helping me automate this repetitive task. FYI, I used following command:

image

Wednesday, October 20, 2010

How to know if a document (lying in SharePoint Document Library) review is due…

I came across an interesting scenario when I was reading stackoverflow.com. Here is the scenario:

“In sharepoint 2010 I need to be able to set a review date on a document and be emailed when this review date is reached. Is this possible?”

I thought of researching on this and found a no-code solution for this. Please review my answer to above post. I will continue to monitor above post if I find a better answer.. But for now here is what I think:

 

To make it the most robust solution, I would suggest to customize the Alerts framework of SharePoint. SharePoint allows following customizations (as documented here http://msdn.microsoft.com/en-us/library/bb802949.aspx)

  • Adding or removing buttons from the alert e-mails.
  • Changing the cascading style sheet used to format e-mail alerts. This is particularly useful for sites that want to create a consistent appearance.
  • Changing the latency of "immediate" alerts by adjusting the default timer interval.
  • Override the templates used to create e-mail or SMS alerts, either by creating a new template or by setting the SPList.AlertTemplate property.
  • Creating custom filters by using Collaborative Application Markup Language (CAML) queries in the element in the alert templates.
  • Programmatically setting or changing the mobile messaging service provider (MSP) that forwards SMS alerts to mobile telephones.
  • Adding custom event handlers that respond when a user creates or modifies an alert. Also, custom handlers that respond to the alert sending event can be created.
  • Programming the alerts framework by using the SharePoint Foundation object model. For more information about how to customize alerts programmatically, see SPAlert.

If your list supports sending alerts based on a View, you are lucky, A NO CODE SOLUTION is already there for you. You can create a View with filter condition like "DueDate is equal to [Today]" (and possibly "AssignedTo is equal to [Me]) and then subscribe to any changes to that view.

If you end up with custom alert filter, following links may get you started: http://egrimmett.wordpress.com/2008/01/17/custom-alerts-part-2-filters/

http://blogs.msdn.com/b/sharepointdeveloperdocs/archive/2007/12/07/customizing-alert-notifications-and-alert-templates-in-windows-sharepoint-services-3-0.aspx

Monday, October 18, 2010

Creating a Web Application with all out of the box templates

As a SharePoint Developer, I am sure you would think about creating one site collections for all available web templates for learning purpose. I used to to do this as first thing after I was done with configuring my server farm. After doing it several times manually, I thought of automating it and I am sharing my experience here…

Welcome to the world of SharePoint 2010 and PowerShell, it is not too difficult to do this.

Here are the steps to do so….

First, we need to create Web Application that will host several Site Collections (as many as the out of the box web templates). I took an approach of creating a .csv file as an input to my web application script. For now, I will have just one row in my WebApps.csv but you can have as many as you want!

Here is the script which access the WebApps.csv file and creates web application:

Add-PsSnapin Microsoft.SharePoint.PowerShell
Import-Csv -Path "WebApps.csv" -Delimiter "," | ForEach-Object {New-SPWebApplication -Name $_.Name -Port $_.Port -ApplicationPool  $_.ApplicationPool -ApplicationPoolAccount (Get-SPManagedAccount $_.PoolAccount)}
Write-host "Operation was executed successfully."
Read-Host

For the purpose of this exercise, my WebApps.csv looks like:

image

Next, I created a list of site collections and then provisioned each site collection with out of the box site template I used same .csv approach above and used following PowerShell script to create the site collections:

Add-PsSnapin Microsoft.SharePoint.PowerShell
Import-Csv -Path "Templates.csv" -Delimiter "," | ForEach-Object {New-SPSite -Url $_.Url -OwnerAlias "Sp10\Administrator" -Language 1033 -Template $_.Name -Name $_.Title }
Write-host "Operation was executed successfully."
Read-Host

As you can see we needed an official name of the site template if you want to create a site collection programmatically. And I used another SharePoint cmdlet to get list of appropriate site templates as shown below

Get-SPWebTemplate | where { ( $_.'IsHidden' -eq [System.Boolean]$False ) -and ( $_.'IsSubWebOnly' -eq [System.Boolean]$False ) }

The result of above command would look like:

image

I used above result to create a .csv file that I need, my final Templates.csv file looks like:

Lcid,Title,Name,url
1033,Team Site,STS#0,http://#YourWebAppUrl#
1033,Blank Site,STS#1,http://#YourWebAppUrl#/Sites/Blank
1033,Document Workspace,STS#2,http://#YourWebAppUrl#/Sites/DocWS
1033,Basic Meeting Workspace,MPS#0,http://#YourWebAppUrl#/Sites/BasicMeetWS
1033,Blank Meeting Workspace,MPS#1,http://#YourWebAppUrl#/Sites/BlankMeetWS
1033,Decision Meeting Workspace,MPS#2,http://#YourWebAppUrl#/Sites/DecisionMeetWS
1033,Social Meeting Workspace,MPS#3,http://#YourWebAppUrl#/Sites/SocialMeetWS
1033,Multipage Meeting Workspace,MPS#4,http://#YourWebAppUrl#/Sites/MeetWS
1033,Blog,BLOG#0,http://#YourWebAppUrl#/Sites/Blog
1033,Group Work Site,SGS#0,http://#YourWebAppUrl#/Sites/GroupSite
1033,Document Center,BDR#0,http://#YourWebAppUrl#/Sites/DocCenter
1033,Records Center,OFFILE#1,http://#YourWebAppUrl#/Sites/Records
1033,Business Intelligence Center,BICenterSite#0,http://#YourWebAppUrl#/Sites/BI
1033,Enterprise Search Center,SRCHCEN#0,http://#YourWebAppUrl#/Sites/EntSearch
1033,Publishing Portal,BLANKINTERNETCONTAINER#0,http://#YourWebAppUrl#/Sites/PubPortal
1033,My Site Host,SPSMSITEHOST#0,http://#YourWebAppUrl#/Sites/mysite
1033,Enterprise Wiki,ENTERWIKI#0,http://#YourWebAppUrl#/Sites/EntWiki
1033,Basic Search Center,SRCHCENTERLITE#0,http://#YourWebAppUrl#/Sites/BasicSearch
1033,FAST Search Center,SRCHCENTERFAST#0,http://#YourWebAppUrl#/Sites/FASTSearch
1033,Visio Process Repository,visprus#0,http://#YourWebAppUrl#/Sites/Visio

You may want to change the data in .csv file as needed!

Hope you enjoyed reading this and save some time by automating this process!

Sunday, October 17, 2010

Crucial Real SSD C300 and SharePoint 2010

Today, I upgraded my SONY VAIO VPCF115FM laptop with Crucial RealSSD C300 256GB SSD Drive. This is my 3rd laptop upgrade in last 1 month; in fact, one of them was an upgrade to 7200 RPM HDD to Seagate Momentus XT Hybrid drive (from a regular 7200 RPM hard drive). The Hybrid drive significantly improved my laptop’s performance and I did not need SSD so badly! But I must call myself a gadget-freak, I could not wait!

Anyways, I spend high bucks for SSD because I wanted to get started with SharePoint 2010 development on VS.NET 2010 in 60 seconds! Before I switched to SSD, I noticed the performance of my older (it was still fastest performing platter based drive though, so don’t get surprised if you have same or comparable laptop and my number looks impressive!) drive.

My Environment:

Windows Server 2008 R2 with Domain Controller Role, SQL Server 2008 R2, SharePoint 2010, VS.NET 2008/2010

Performance of Seagate Momentus XT Hybrid 7200 RPM Drive

To see desktop wallpaper from Power On: 135 Seconds

To Browse google.com from power On: 150 seconds

Open Central Admin First time - 30-35 Seconds

VS.NET 2010 First Time- 12-15 Seconds

Microsoft Word – 5 seconds

 

Performance of Crucial RealSSD C300 SATA III 256GB Drive

To see desktop wallpaper from Power On: 70 Seconds

To Browse google.com from power On: 75 seconds

Open Central Admin First time - 30-35 Seconds

VS.NET 2010 First Time- 4-5 Seconds

Microsoft Word – 2-3 seconds

 

As you can see, SSD is performing much better than my already rocking Seagate Momentus XT Hybrid drive, perhaps the improvement may not be worth 550 bucks! Again, if I was comparing it with regular (non-hybrid) drive, the numbers would look very impressive, I vaguely remember it used to take about 220 seconds with regular 7200 RPM drive.

Time for final thoughts!

If you care of each and every seconds of improvement and ready to spend as much as you can, SSD is definitely a way to go. But if you are looking for a high capacity drive with maximum performance, go for Seagate Momentus XT 500GB drive, this performs really really good on Windows 7.

Wednesday, October 13, 2010

Creating a simple workflow using SharePoint Designer 2010

Scenario:

Create a list in which I can enter information about an item which was found unoccupied in the campus. Employees can claim the lost item using a workflow. The workflow is considered closed when front-desk verifies the information about the claimant and the item itself and returns the item back to the employee.

At high level this is how it would work:

1. Front Desk (office administration department) enters information about the item found in SharePoint

2. Let’s assume that employees would have subscribed an email alert to this list so that they receive an email whenever a new item is added to this list. (Alternatively, we can have SharePoint send an email to a distribution list whenever a new item is added to the list)

3. Person who lost the item can click on the item and Select “Claim Item” button from the toolbar

Here are the steps to implement such functionality using Sharepoint 2010 List and a simple workflow created using Sharepoint Designer 2010:

1. Create a new content type called “Lost Item”. I will add following Site Columns to it:

a. Name

b. Date Found

c. Contact Person (Someone at front desk)

d. Description

2. Create a New list called Lost Items and enable content type on the list

3. Associate “Lost Item” content type to the “Lost Items” List

I have done all these using Sharepoint Designer as it is much quicker to do with SPD than the browser base interface!

Our Next task is to create a Reusable Workflow using SPD to facilitate the process. And we will attach this reusable workflow to our “Lost Item” content type.

clip_image001

The name of the workflow would be “Claim Lost Item”

clip_image002

When you click Ok, the wonderful Workflow Designer would open up and it would look like this:

clip_image004

Now, when someone claims the lost item, for verification purpose we may want to capture a few things like:

1. Contact Details

2. Item Identification

3. Lost at (Location)

So that front desk can verify the information and make sure that item is being returned to the right person.

Also note that we can assume that person initiating the workflow is claimant himself and we may already have the information about the user (Login ID, Email ID, Name etc) as part of the user profile imported from Active Directory. For the sake of simplicity, we will capture this information when the workflow is kicked off.

Note that above information shall be captured in a Workflow Initiation form and that form can be a custom .ASPX file or an InfoPath form.

Let’s move on!

Let’s add following initiation parameters using SPD.

clip_image005

Please note that APD will automatically create a basic Info Path form to capture this information and it will associate it with the workflow as shown below:

clip_image007

You can click open the form and make it fancier with InfoPath if you want!

Let’s get to the core business and specify what should actually happen as during the workflow. What we want to do is assign a task to the person who created the “Lost Item” record in the “Lost Items” list. The workflow is then hibernated (SharePoint actually persists it in database) until that task is either accepted or rejected.

The first thing I want to do is send an email to the person who created this item. For simplicity, I am sending email to myself! For that, I have added a Send Email activity while being on the workflow designer surface of SPD.

I want an intelligent email. At minimum, I want the claimant’s information in email and the information about the item as well. I love SPD because it makes it a bridge for me ( I feel that even my 2 year old daughter can do it)!

clip_image009

The next thing I want to do is leverage OOB action which allows me to assign a task and wait for someone to approve/reject the task. In this case, approve means the claimant is legitimate and the item must be returned to the claimant and reject means…. Blah blah.. (let me save some typing here)

I have also associated a column called “Claim Status” which I can modify based on the outcome (approved/rejected) of the task. I also want to include in detailed task description when a new task is assigned to someone. My final configuration looks like:

clip_image011

I have also taken following actions based on the outcome of the task:

clip_image012

And finally, I would verify that there is no error with the workflow configuration (again, SPD is so elegant!) and publish the workflow:

clip_image013

At this point you are ready to associate the workflow to my “Lost Item” content type and once that is done, we can see it in action!

Let’s create a new “Lost Item” and feel the claim process (well, be honest and claim it only if it is your wallet)

clip_image014

Just before starting the workflow, the claimant is presented with an initiation form in which claimant can provide more information about the claim as shown below:

clip_image016

When Start button is clicked, the workflow is put in “In Progress” status and email is sent (assuming that you have configured outgoing emails in your server farm)

Below is an email that I received:

clip_image018

Go ahead and check the tasks, you should see a task assigned to you. The Claim Status would change depending upon your actions on the task (approve/reject).

Last not the least, using SPD you can also add a custom action in the List’s Ribbon to kick off claim process!

Hope this was helpful…