Tuesday, July 17, 2012

SharePoint: Showing Last Published Version to Authors

Quick 5 minute post! Hope it helps!

Recently, our content authors wanted to see the most recent published version without going to Version History. Unfortunately, they hate to use SharePoint’s Version History and let me mention – they hate the ribbon too Sad smile.

Anyways, they were okay with a button put in the side bar of the page which can only be displayed to Authors. And they wanted to view the page in a new window so that they can compare with draft version (thank god, they were okay with comparing the content manually Smile)

Rather than accessing the versions on server side, we decided to access the version information only when a button is clicked. Once again the wonderful Client Side Object model saved a lot of work for us. The script on click of button would look this (and that’s it for today)



this.ctx = SP.ClientContext.get_current();
this.page = ctx.get_web().getFileByServerRelativeUrl(window.location.pathname);
ctx.load(page);

ctx.executeQueryAsync(Function.createDelegate(
this, this.ShowVersion), Function.createDelegate(this, this.ShowError));
function ShowVersion() {
var versionID = page.get_uiVersion();
if (versionID < 512)
SP.UI.Notify.addNotification(
'This page was never published.', false);
else if (versionID % 512 == 0)
SP.UI.Notify.addNotification(
'You are currently viewing Published Version.', false)
else{
window.open(window.location
+ '?PageVersion=' + 512*(versionID % 512), '_blank')
}

}
function ShowError() {
SP.UI.Notify.addNotification(
'Unable to perform the action. Please report the issue.', false)
}

Saturday, January 21, 2012

Where is my Rating Feature?

Many of you know new new Rating FEAURE of SharePoint 2010. There are many resources out there to learn about using Rating Feature but here, I would talk about what it takes to make the Rating Feature available to you.

I will not waste time, ALL of following must be TRUE for rating feature to be available for your lists:

1. You must be using SharePoint Server product. According to Compare SharePoint Editions, Rating is NOT available to SharePoint Foundation that comes free with Windows Server 2008.

2. You must have configured User Profile Service in Central Administration.

3. The User Profile Service must be associated with your Web Application

Note: Step 2 and 3 are described here (and many other places, I am sure)

http://dxjo.net/dxit/2011/09/activate-and-enable-rating-in-sharepoint-2010/

4. This is perhaps not documented at many places, but you must NOT have created your site from a Blank site template. If yes, you are out of luck. But wait… there is one last chance, if you started with blank site template and you are okay with enabling Publishing Features at site collection level, you can still make it available! 

DISCLAIMER: I do not recommend and I have not tested the side effects of enabling publishing feature on sites created from blank site template. Personally, I would try to avoid it!

Alternatively, you can just try enabling the hidden rating FEATURE by using following PowerShell command. When I tested following, I was able to enable rating on announcement rating and save my rating, the average rating was also calculated depending upon the scheduled jobs. I did not test further:

Enable-SPFeature 915c240e-a6cc-49b8-8b2c-0bff8b553ed3 –URL http://yoururl.com

Also note that SharePoint staples the Rating FEATURE to following Site Templates:




<FeatureSiteTemplateAssociation Id="915c240e-a6cc-49b8-8b2c-0bff8b553ed3" TemplateName="STS#0" />

<FeatureSiteTemplateAssociation Id="915c240e-a6cc-49b8-8b2c-0bff8b553ed3" TemplateName="STS#2" />

<FeatureSiteTemplateAssociation Id="915c240e-a6cc-49b8-8b2c-0bff8b553ed3" TemplateName="MPS#0" />
<FeatureSiteTemplateAssociation Id="915c240e-a6cc-49b8-8b2c-0bff8b553ed3" TemplateName="MPS#1" />
<FeatureSiteTemplateAssociation Id="915c240e-a6cc-49b8-8b2c-0bff8b553ed3" TemplateName="MPS#2" />
<FeatureSiteTemplateAssociation Id="915c240e-a6cc-49b8-8b2c-0bff8b553ed3" TemplateName="MPS#3" />
<FeatureSiteTemplateAssociation Id="915c240e-a6cc-49b8-8b2c-0bff8b553ed3" TemplateName="MPS#4" />

<FeatureSiteTemplateAssociation Id="915c240e-a6cc-49b8-8b2c-0bff8b553ed3" TemplateName="WIKI#0" />
<FeatureSiteTemplateAssociation Id="915c240e-a6cc-49b8-8b2c-0bff8b553ed3" TemplateName="BLOG#0" />
<FeatureSiteTemplateAssociation Id="915c240e-a6cc-49b8-8b2c-0bff8b553ed3" TemplateName="SGS#0" />

<FeatureSiteTemplateAssociation Id="915c240e-a6cc-49b8-8b2c-0bff8b553ed3" TemplateName="BDR#0" />

<FeatureSiteTemplateAssociation Id="915c240e-a6cc-49b8-8b2c-0bff8b553ed3" TemplateName="OFFILE#0" />
<FeatureSiteTemplateAssociation Id="915c240e-a6cc-49b8-8b2c-0bff8b553ed3" TemplateName="OFFILE#1" />

<FeatureSiteTemplateAssociation Id="915c240e-a6cc-49b8-8b2c-0bff8b553ed3" TemplateName="PWA#0" />
<FeatureSiteTemplateAssociation Id="915c240e-a6cc-49b8-8b2c-0bff8b553ed3" TemplateName="PWS#0" />

<FeatureSiteTemplateAssociation Id="915c240e-a6cc-49b8-8b2c-0bff8b553ed3" TemplateName="SPS#0" />

<FeatureSiteTemplateAssociation Id="915c240e-a6cc-49b8-8b2c-0bff8b553ed3" TemplateName="SPSMSITE#0" />

<FeatureSiteTemplateAssociation Id="915c240e-a6cc-49b8-8b2c-0bff8b553ed3" TemplateName="SPSTOC#0" />
<FeatureSiteTemplateAssociation Id="915c240e-a6cc-49b8-8b2c-0bff8b553ed3" TemplateName="SPSTOPIC#0" />

<FeatureSiteTemplateAssociation Id="915c240e-a6cc-49b8-8b2c-0bff8b553ed3" TemplateName="SPSNEWS#0" />
<FeatureSiteTemplateAssociation Id="915c240e-a6cc-49b8-8b2c-0bff8b553ed3" TemplateName="SPSNHOME#0" />
<FeatureSiteTemplateAssociation Id="915c240e-a6cc-49b8-8b2c-0bff8b553ed3" TemplateName="SPSSITES#0" />

<FeatureSiteTemplateAssociation Id="915c240e-a6cc-49b8-8b2c-0bff8b553ed3" TemplateName="SPSBWEB#0" />
<FeatureSiteTemplateAssociation Id="915c240e-a6cc-49b8-8b2c-0bff8b553ed3" TemplateName="SPSCOMMU#0" />

<FeatureSiteTemplateAssociation Id="915c240e-a6cc-49b8-8b2c-0bff8b553ed3" TemplateName="SPSREPORTCENTER#0" />
<FeatureSiteTemplateAssociation Id="915c240e-a6cc-49b8-8b2c-0bff8b553ed3" TemplateName="SPSPORTAL#0" />
<FeatureSiteTemplateAssociation Id="915c240e-a6cc-49b8-8b2c-0bff8b553ed3" TemplateName="SRCHCEN#0" />
<FeatureSiteTemplateAssociation Id="915c240e-a6cc-49b8-8b2c-0bff8b553ed3" TemplateName="PROFILES#0" />

<FeatureSiteTemplateAssociation Id="915c240e-a6cc-49b8-8b2c-0bff8b553ed3" TemplateName="CMSPUBLISHING#0" />

<FeatureSiteTemplateAssociation Id="915c240e-a6cc-49b8-8b2c-0bff8b553ed3" TemplateName="SPSPORTAL#0" />
<FeatureSiteTemplateAssociation Id="915c240e-a6cc-49b8-8b2c-0bff8b553ed3" TemplateName="SPS#0" />
<FeatureSiteTemplateAssociation Id="915c240e-a6cc-49b8-8b2c-0bff8b553ed3" TemplateName="SPSREPORTCENTER#0" />
<FeatureSiteTemplateAssociation Id="915c240e-a6cc-49b8-8b2c-0bff8b553ed3" TemplateName="SPSTOC#0" />
<FeatureSiteTemplateAssociation Id="915c240e-a6cc-49b8-8b2c-0bff8b553ed3" TemplateName="SPSTOPIC#0" />
<FeatureSiteTemplateAssociation Id="915c240e-a6cc-49b8-8b2c-0bff8b553ed3" TemplateName="SPSNEWS#0" />
<FeatureSiteTemplateAssociation Id="915c240e-a6cc-49b8-8b2c-0bff8b553ed3" TemplateName="SPSNHOME#0" />
<FeatureSiteTemplateAssociation Id="915c240e-a6cc-49b8-8b2c-0bff8b553ed3" TemplateName="SPSSITES#0" />
<FeatureSiteTemplateAssociation Id="915c240e-a6cc-49b8-8b2c-0bff8b553ed3" TemplateName="SRCHCEN#0" />

<FeatureSiteTemplateAssociation Id="915c240e-a6cc-49b8-8b2c-0bff8b553ed3" TemplateName="CMSPUBLISHING#0" />
<FeatureSiteTemplateAssociation Id="915c240e-a6cc-49b8-8b2c-0bff8b553ed3" TemplateName="BLANKINTERNET#0" />
<FeatureSiteTemplateAssociation Id="915c240e-a6cc-49b8-8b2c-0bff8b553ed3" TemplateName="BLANKINTERNET#1" />
<FeatureSiteTemplateAssociation Id="915c240e-a6cc-49b8-8b2c-0bff8b553ed3" TemplateName="BLANKINTERNET#2" />


The Rating FEATURE is hidden and Publishing Feature depends on it and that’s the reason it becomes available to you when you activate Publishing Feature.

Thursday, January 12, 2012

Sending Emails to SharePoint Group

Recently, I came across a situation where I had to include SharePoint group in To field of “Send Email” activity in a reusable workflow designed in SharePoint Designer. I just included it thinking that it would work (just like hundreds of other developers I guess) but I was wrong. Well, that was my last activity in the workflow. After it was deployed, it would NOT send emails to members of the SharePoint Group and worse than that, it would not show any error, the workflow appears completed but it does NOT terminate itself but the page gets published. As a result, content authors cannot start a new workflow because previous workflow was not terminated even though item was published. SharePoint not sending emails is understood but I would be happier it it logged something in the workflow history or terminated the workflow. It took me many change/deploy cycles before I could figure it out.

I posted a question on here: Definitive answer to sending emails to SP Group from Workflow and on MSDN forum too, but did not get an answer for couple of days and then thought about figuring out solution that works for me (yes, there could be other solutions out there).

Solution and Assumptions: It was safe to assume in my situation that SharePoint users will directly be added to the group to which I need to send emails.

So the simplest solution was to get develop a custom activity which can be consumed by SharePoint designer. The activity outputs list of emails given the SharePoint group or individual’s name. The designer can take the output and store it in Workflow variable. And finally, the variable is used in “To” field of the Send Email Activity.

So following solution needs to be revisited (or tested) if the SharePoint group includes other groups or active directory groups.

Code

Here is my activity looks like:

using System;
using System.ComponentModel;
using System.Linq;
using System.Workflow.ComponentModel;
using Microsoft.SharePoint;
using Microsoft.SharePoint.Utilities;
using Microsoft.SharePoint.Workflow;
using Microsoft.SharePoint.WorkflowActions;
namespace MyProduct.Workflows.Activities
{
public class ExpandSharePointGroup : Activity
{
public static DependencyProperty __ContextProperty = System.Workflow.ComponentModel.DependencyProperty.Register("__Context",
typeof(WorkflowContext), typeof(ExpandSharePointGroup));

[Description(
"Context")]
[Browsable(
true)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
public WorkflowContext __Context
{
get
{
return ((WorkflowContext)(base.GetValue(__ContextProperty)));
}
set
{
base.SetValue(__ContextProperty, value);
}
}


public static DependencyProperty GroupNameProperty = DependencyProperty.Register("GroupName",
typeof(string), typeof(ExpandSharePointGroup));

[Description(
"SharePoint Group Name")]
[Category(
"MyProduct Workflow Activities")]
[Browsable(
true)]
[DesignerSerializationVisibility
(DesignerSerializationVisibility.Visible)]
public string GroupName
{
get
{
return ((string)
(
base.GetValue(GroupNameProperty)));
}
set
{
base.SetValue(GroupNameProperty, value);
}
}

public static DependencyProperty FieldValueProperty = DependencyProperty.Register("FieldValue",
typeof(string), typeof(ExpandSharePointGroup));

[Description(
"Field Value")]
[Category(
"MyProduct Workflow Activities")]
[Browsable(
true)]
[DesignerSerializationVisibility
(DesignerSerializationVisibility.Visible)]
public string FieldValue
{
get
{
return ((string)
(
base.GetValue(FieldValueProperty)));
}
set
{
base.SetValue(FieldValueProperty, value);
}
}



protected override ActivityExecutionStatus Execute(ActivityExecutionContext executionContext)
{

SPWeb web
= (SPWeb)__Context.Web;

try
{
if (string.IsNullOrEmpty(GroupName))
{

return ActivityExecutionStatus.Closed;
}

string strOutput = string.Empty;
strOutput
= Helper.ResolveToEmailName(__Context, GroupName);
FieldValue
= strOutput;
}
catch (Exception ex)
{
// TODO: Log error here
return ActivityExecutionStatus.Faulting;
}


return ActivityExecutionStatus.Closed;
}

}

}

In order to make sure that above activity is available to SharePoint designer, we need to deploy a .Actions file to {SharePointRoot}\Template\1033\Workflow which is shown below:


<?xml version="1.0" encoding="utf-8"?>
<WorkflowInfo Language="en-us">
<Actions>
<Action Name="Expand SharePoint Group Members"
ClassName
="FULL CLASS NAME"
Assembly
="FULL ASSEMBLY NAME"
AppliesTo
="all"
Category
="My Custom Workflow Activities">
<RuleDesigner Sentence="Expand Email for %1 it in: %2">
<FieldBind Field="GroupName" Text="SharePoint Group" DesignerType="TextBox" Id="1"/>
<FieldBind Field="FieldValue" Text="Field Value" DesignerType="ParameterNames" Id="2"/>
</RuleDesigner>
<Parameters>
<Parameter Name="__Context" Type="Microsoft.SharePoint.WorkflowActions.WorkflowContext" Direction="In" DesignerType="Hide" />
<Parameter Name="GroupName" Type="System.String, mscorlib" Direction="In" />
<Parameter Name="FieldValue" Type="System.String, mscorlib" Direction="Out" />
</Parameters>
</Action>
</Actions>
</WorkflowInfo>

Finally, you need to add a web.config entry under authorizedTypes section:



<authorizedType Assembly="Full Assembly Name" Namespace="Your Name space" TypeName="Class Name or *" Authorized="True" />


Note: After your assembly is deployed in GAC, Actions file is deployed on SharePoint root and web.config entry is added (as shown above), you need to close the SharePoint Designer and open it again before you can see your activity in list of available actions.


Hope this helps!