SharePoint SendEmail Activity “Go to My Tasks”
In Microsoft.SharePoint.WorkflowActions.SendEMail Acitivity, there is a property called IncludeStatus https://msdn.microsoft.com/en-us/library/microsoft.sharepoint.workflowactions.sendemail.includestatus.aspx. When this property is set to true, in the Email that we receive through SendEMail Acitivity will include two links.
1) View Workflow Summary
2) Go to My Tasks
Each of these links takes us to the appropriate page based on the generated URL. The link for View Workflow Summary is constructed correctly, but for Go to My Tasks is not correct.
For e.g
The Workflow Summary URL is correctly setup, pointing to https://myServer.com/Home/_layouts/WrkStat.aspx?List=62d46228-4188-49e5-90f2-31245864b03b&WorkflowInstanceID=234b7864-c37d-42d0-b2bb-964d15cb67a2
For Go to my tasks URL is incorrect setup, pointing to https://myServer.com/SiteA/SiteB/SiteA/SiteB/Lists/Tasks/AllItems.aspx. The problem being the "SiteA/SiteB” being twice in this case. The link may vary depending on Site Collection level, Site level or Managed property defined.
The Interface type for the send Email action was set to Microsoft.SharePoint.Workflow.ISharePointService. In the SharePoint dll's SPWinOEWSSService class implements this interface. The Send Email method of this class (SendEmail(Guid workflowId, bool includeStatus, StringDictionary headers, string body)) contains an error where it will incorrectly set the URL.
public void string str4 = parentWeb.Url + currentWorkflow.TaskList.DefaultViewUrl;
parentWeb.Url Equals https://myServer.com/SiteA/SiteB
currentWorkflow.TaskList.DefaultViewUrl Equals /SiteA/SiteB /Lists/AllItems.aspx
In order to fix this issue, we can write a custom activity similar to SendEmail activity and change the URL generated for “Go to My Tasks”
1. In the Main Workflow code file, have these properties declared.
public Guid workflowId = default(System.Guid);
public SPWorkflowActivationProperties workflowProperties = new SPWorkflowActivationProperties();
2. Code snippet in OnWorkflowActivated Event
Activity1.ItemId = workflowProperties.ItemId;
Activity1.LibId = workflowProperties.ListId;
Activity1.WebId = workflowProperties.WebId;
Activity1.SiteId = workflowProperties.SiteId;
Activity1.WorkflowId = workflowProperties.WorkflowId;
3. Custom Activity code file, variable declarations
public static int ItemId;
public static Guid LibId;
public static Guid WebId;
public static Guid SiteId;
public static Guid WorkflowId;
4. Dependency Property declarations
#region Dependency_Properties
//BCC
public static DependencyProperty BCCProperty = DependencyProperty.Register("BCC", typeof(System.String), typeof(SendEmailActivity.Activity1));
[DesignerSerializationVisibilityAttribute(DesignerSerializationVisibility.Visible)]
[BrowsableAttribute(true)]
[CategoryAttribute("Misc")]
public String BCC
{
get
{
return ((System.String)(base.GetValue(SendEmailActivity.Activity1.BCCProperty)));
}
set
{
base.SetValue(SendEmailActivity.Activity1.BCCProperty, value);
}
}
//Body
public static DependencyProperty BodyProperty = DependencyProperty.Register("Body", typeof(System.String), typeof(SendEmailActivity.Activity1));
[DesignerSerializationVisibilityAttribute(DesignerSerializationVisibility.Visible)]
[BrowsableAttribute(true)]
[CategoryAttribute("Misc")]
public String Body
{
get
{
return ((System.String)(base.GetValue(SendEmailActivity.Activity1.BodyProperty)));
}
set
{
base.SetValue(SendEmailActivity.Activity1.BodyProperty, value);
}
}
//CC
public static DependencyProperty CCProperty = DependencyProperty.Register("CC", typeof(System.String), typeof(SendEmailActivity.Activity1));
[DesignerSerializationVisibilityAttribute(DesignerSerializationVisibility.Visible)]
[BrowsableAttribute(true)]
[CategoryAttribute("Misc")]
public String CC
{
get
{
return ((System.String)(base.GetValue(SendEmailActivity.Activity1.CCProperty)));
}
set
{
base.SetValue(SendEmailActivity.Activity1.CCProperty, value);
}
}
//From
public static DependencyProperty FromProperty = DependencyProperty.Register("From", typeof(System.String), typeof(SendEmailActivity.Activity1));
[DesignerSerializationVisibilityAttribute(DesignerSerializationVisibility.Visible)]
[BrowsableAttribute(true)]
[CategoryAttribute("Misc")]
public String From
{
get
{
return ((System.String)(base.GetValue(SendEmailActivity.Activity1.FromProperty)));
}
set
{
base.SetValue(SendEmailActivity.Activity1.FromProperty, value);
}
}
//Header
public static DependencyProperty HeaderProperty = DependencyProperty.Register("Header", typeof(System.String), typeof(SendEmailActivity.Activity1));
[DesignerSerializationVisibilityAttribute(DesignerSerializationVisibility.Visible)]
[BrowsableAttribute(true)]
[CategoryAttribute("Misc")]
public String Header
{
get
{
return ((System.String)(base.GetValue(SendEmailActivity.Activity1.HeaderProperty)));
}
set
{
base.SetValue(SendEmailActivity.Activity1.HeaderProperty, value);
}
}
//IncludeStatus
public static DependencyProperty IncludeStatusProperty = DependencyProperty.Register("IncludeStatus", typeof(System.Boolean), typeof(SendEmailActivity.Activity1));
[DesignerSerializationVisibilityAttribute(DesignerSerializationVisibility.Visible)]
[BrowsableAttribute(true)]
[CategoryAttribute("Misc")]
public Boolean IncludeStatus
{
get
{
return ((System.Boolean)(base.GetValue(SendEmailActivity.Activity1.IncludeStatusProperty)));
}
set
{
base.SetValue(SendEmailActivity.Activity1.IncludeStatusProperty, value);
}
}
//Subject
public static DependencyProperty SubjectProperty = DependencyProperty.Register("Subject", typeof(System.String), typeof(SendEmailActivity.Activity1));
[DesignerSerializationVisibilityAttribute(DesignerSerializationVisibility.Visible)]
[BrowsableAttribute(true)]
[CategoryAttribute("Misc")]
public String Subject
{
get
{
return ((System.String)(base.GetValue(SendEmailActivity.Activity1.SubjectProperty)));
}
set
{
base.SetValue(SendEmailActivity.Activity1.SubjectProperty, value);
}
}
//To
public static DependencyProperty ToProperty = DependencyProperty.Register("To", typeof(System.String), typeof(SendEmailActivity.Activity1));
[DesignerSerializationVisibilityAttribute(DesignerSerializationVisibility.Visible)]
[BrowsableAttribute(true)]
[CategoryAttribute("Misc")]
public String To
{
get
{
return ((System.String)(base.GetValue(SendEmailActivity.Activity1.ToProperty)));
}
set
{
base.SetValue(SendEmailActivity.Activity1.ToProperty, value);
}
}
//MethodInvoking
public static DependencyProperty MethodInvokingEvent = DependencyProperty.Register("MethodInvoking", typeof(System.EventHandler), typeof(SendEmailActivity.Activity1));
[DesignerSerializationVisibilityAttribute(DesignerSerializationVisibility.Visible)]
[BrowsableAttribute(true)]
[CategoryAttribute("Handlers")]
public event EventHandler MethodInvoking
{
add
{
base.AddHandler(MethodInvokingEvent, value);
}
remove
{
base.RemoveHandler(MethodInvokingEvent, value);
}
}
//InterfaceType
public static DependencyProperty InterfaceTypeProperty = DependencyProperty.Register("InterfaceType", typeof(System.String), typeof(SendEmailActivity.Activity1));
[DesignerSerializationVisibilityAttribute(DesignerSerializationVisibility.Visible)]
[BrowsableAttribute(true)]
[CategoryAttribute("Activity")]
public String InterfaceType
{
get
{
return "Microsoft.SharePoint.Workflow.ISharePointService";
}
}
//MethodName
public static DependencyProperty MethodNameProperty = DependencyProperty.Register("MethodName", typeof(System.String), typeof(SendEmailActivity.Activity1));
[DesignerSerializationVisibilityAttribute(DesignerSerializationVisibility.Visible)]
[BrowsableAttribute(true)]
[CategoryAttribute("Activity")]
public String MethodName
{
get
{
return "SendEmail";
}
}
//CorrelationToken
public static DependencyProperty CorrelationTokenProperty = DependencyProperty.Register("CorrelationToken", typeof(System.String), typeof(SendEmailActivity.Activity1));
[DesignerSerializationVisibilityAttribute(DesignerSerializationVisibility.Visible)]
[BrowsableAttribute(true)]
[CategoryAttribute("Activity")]
public String CorrelationToken
{
get
{
return ((System.String)(base.GetValue(SendEmailActivity.Activity1.CorrelationTokenProperty)));
}
set
{
base.SetValue(SendEmailActivity.Activity1.CorrelationTokenProperty, value);
}
}
//OwnerActivityName
public static DependencyProperty OwnerActivityNameProperty = DependencyProperty.Register("OwnerActivityName", typeof(System.String), typeof(SendEmailActivity.Activity1));
[DesignerSerializationVisibilityAttribute(DesignerSerializationVisibility.Visible)]
[BrowsableAttribute(true)]
[CategoryAttribute("Activity")]
public String OwnerActivityName
{
get
{
return ((System.String)(base.GetValue(SendEmailActivity.Activity1.OwnerActivityNameProperty)));
}
set
{
base.SetValue(SendEmailActivity.Activity1.OwnerActivityNameProperty, value);
}
}
#endregion
5. ExecudeCode method of code activity in custom activity.
SendEmail sE = new SendEmail();
sE.From = From;
sE.To = To;
sE.Subject = Subject ;
sE.Body = Body;
CorrelationToken ct = new CorrelationToken(CorrelationToken);
ct.OwnerActivityName = OwnerActivityName;
sE.CorrelationToken = ct;
sE.IncludeStatus = IncludeStatus;
SPSite site = new SPSite(SiteId);
SPWeb web = site.OpenWeb(WebId);
SPList list = web.Lists[LibId];
SPListItem item = list.GetItemById(ItemId);
SPWorkflow currentWorkflow = item.Workflows[WorkflowId];
StringDictionary headers = new StringDictionary();
SPWeb parentWeb = currentWorkflow.ParentList.ParentWeb;
string str = SPResource.GetString("DirectionDirValue", new object[0]);
string str2 = headers["subject"];
string str3 = parentWeb.Url + "/" + currentWorkflow.ParentAssociation.StatusUrl + "?List=" + currentWorkflow.ParentList.ID.ToString() + "&WorkflowInstanceID=" + currentWorkflow.InstanceId.ToString();
//string str4 = parentWeb.Url + currentWorkflow.TaskList.DefaultViewUrl;
int sIndex = currentWorkflow.TaskList.DefaultViewUrl.IndexOf("/Lists"); // Depending on the URL, the logic can be changed
string str4 = parentWeb.Url + currentWorkflow.TaskList.DefaultViewUrl.Substring(sIndex);
string body = sE.Body;
body = string.Format(CultureInfo.InvariantCulture, SPResource.GetString("WorkflowChannelEmailHeader", new object[0]), new object[] { str, str2, str3, str4, body });
SPUtility.SendEmail(web, true, false, sE.To, sE.Subject, body);
That’s all we have to do! Use the custom activity in the workflow and set its properties. By setting IncludeStatus property to true, and then by running the workflow, we will get a wonderful email with correct URL generated for “Go to My Tasks” link!!
Comments
- Anonymous
March 21, 2010
I am missing SendEmailActivity.dll in my solution . I didn't find it. - Anonymous
November 07, 2013
hmm, it 2013 and this still hasn't been fixed yet :( - Anonymous
February 20, 2014
Wonder why the boys in Redmond have not fixed this bug yet....