I am writing custom activity for sharepoint workflow and I don\'t know how I can use current workflow item, SPWeb or SPSite.
I see http://blogs.microsoft.co.il/blogs/dav
Kit Menke's answer is very comprehensive and covers just about all you need: I would only add the following...
If you do this:
SPWeb tmpweb = __Context.Web;
SPSite site = new SPSite(tmpweb.Url);
SPWeb web = site.OpenWeb();
instead of this:
SPWeb web = __Context.Web;
...
then you are free of the security context passed through to the workflow by the person who triggered it.
I don't know if this is too easy, but I used:
objCurrentItem = workflowProperties.Item
to get the item within the workflow (a list) and then to alter the items in the list
The answer to this is a couple steps:
STEP 1: Here is the code for the properties (my class is named GetEmails which you will need to rename to be your class):
public static DependencyProperty __ContextProperty = System.Workflow.ComponentModel.DependencyProperty.Register("__Context", typeof(WorkflowContext), typeof(GetEmails));
[Description("The site context")]
[Category("User")]
[Browsable(true)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
public WorkflowContext __Context
{
get
{
return ((WorkflowContext)(base.GetValue(GetEmails.__ContextProperty)));
}
set
{
base.SetValue(GetEmails.__ContextProperty, value);
}
}
public static DependencyProperty __ListIdProperty = System.Workflow.ComponentModel.DependencyProperty.Register("__ListId", typeof(string), typeof(GetEmails));
[ValidationOption(ValidationOption.Required)]
public string __ListId
{
get
{
return ((string)(base.GetValue(GetEmails.__ListIdProperty)));
}
set
{
base.SetValue(GetEmails.__ListIdProperty, value);
}
}
public static DependencyProperty __ListItemProperty = System.Workflow.ComponentModel.DependencyProperty.Register("__ListItem", typeof(int), typeof(GetEmails));
[ValidationOption(ValidationOption.Required)]
public int __ListItem
{
get
{
return ((int)(base.GetValue(GetEmails.__ListItemProperty)));
}
set
{
base.SetValue(GetEmails.__ListItemProperty, value);
}
}
public static DependencyProperty __ActivationPropertiesProperty = DependencyProperty.Register("__ActivationProperties", typeof(Microsoft.SharePoint.Workflow.SPWorkflowActivationProperties), typeof(GetEmails));
[ValidationOption(ValidationOption.Required)]
public Microsoft.SharePoint.Workflow.SPWorkflowActivationProperties __ActivationProperties
{
get
{
return (Microsoft.SharePoint.Workflow.SPWorkflowActivationProperties)base.GetValue(GetEmails.__ActivationPropertiesProperty);
}
set
{
base.SetValue(GetEmails.__ActivationPropertiesProperty, value);
}
}
STEP 2: Then in your .actions file add to your block the mappings for those properties (note the entries for __ListID, __ListItem, __Context, and __ActivationProperties):
<Action Name="[DESCRIPTION OF YOUR ACTION]"
ClassName="[Your.Namespace.Goes.Here].GetEmails"
Assembly="[yourDLLName], Version=1.0.0.0, Culture=neutral, PublicKeyToken=0bfc6fa4c4aa913b"
AppliesTo="all"
Category="[Your Category Goes Here]">
<RuleDesigner Sentence="[blah blah blah]">
<FieldBind Field="PeopleFieldName" Text="people field" Id="1"/>
<FieldBind Field="Output" Text="emailAddress" Id="2" DesignerType="parameterNames" />
</RuleDesigner>
<Parameters>
<Parameter Name="__Context" Type="Microsoft.SharePoint.WorkflowActions.WorkflowContext" Direction="In" />
<Parameter Name="__ListId" Type="System.String, mscorlib" Direction="In" />
<Parameter Name="__ListItem" Type="System.Int32, mscorlib" Direction="In" />
<Parameter Name="PeopleFieldName" Type="System.String, mscorlib" Direction="In" />
<Parameter Name="Output" Type="System.String, mscorlib" Direction="Out" />
<Parameter Name="__ActivationProperties" Type="Microsoft.SharePoint.Workflow.SPWorkflowActivationProperties, Microsoft.SharePoint" Direction="Out" />
</Parameters>
</Action>
STEP 3: Here is an example execute function:
protected override ActivityExecutionStatus Execute(ActivityExecutionContext provider)
{
Output = string.Empty;
try
{
SPWeb web = __Context.Web;
// get all of the information we currently have about the item
// that this workflow is running on
Guid listGuid = new Guid(__ListId);
SPList myList = web.Lists[listGuid];
SPListItem myItem = myList.GetItemById(__ListItem);
//...
}
catch (Exception e)
{
//...
}
return ActivityExecutionStatus.Closed;
}
I'm not sure if this is a change in the 2010 API but the __Context property provides all the necessary pieces, including the list and item. The example below includes @davek's suggestion for discarding the security context:
var contextWeb = __Context.Web;
var site = new SPSite(contextWeb.Url);
var web = site.OpenWeb();
var list = web.Lists[new Guid(__Context.ListId)];
var item = list.GetItemById( __Context.ItemId);
Take a look at the SPWorkflowActivationProperties.Item Property
Gets the list item on which the workflow instance is running.
I try this code and runs as well bat the contex objet always is null. some one know why?
protected override ActivityExecutionStatus Execute(ActivityExecutionContext executionContext)
{
//return base.Execute(executionContext);
int IdRetorno = -1;
try {
SPSecurity.RunWithElevatedPrivileges(delegate
{
LogExceptionToWorkflowHistory("Inicio:", executionContext, WorkflowInstanceId);
using (SPSite sitio = new SPSite(this.__Context.Site.ID))
{
using (SPWeb web = sitio.AllWebs[this.__Context.Site.ID])
{
SPList sourceList = web.Lists[new Guid(ListId)];
LogExceptionToWorkflowHistory(ListId, executionContext, WorkflowInstanceId);
SPList destinoList = web.Lists[new Guid(SourceListId)];
LogExceptionToWorkflowHistory(SourceListId, executionContext, WorkflowInstanceId);
SPListItem sourceItem = sourceList.Items.GetItemById(ListItem);
LogExceptionToWorkflowHistory(ListItem.ToString(), executionContext, WorkflowInstanceId);
SPListItem destinoItem = destinoList.Items.Add();
CopyFieldValues(sourceItem, destinoItem);
destinoItem.SystemUpdate();
sourceItem.Delete();
IdRetorno = destinoItem.ID;
}
}
});
}
catch (Exception ex) {
if (!System.Diagnostics.EventLog.SourceExists("MyApp1"))
System.Diagnostics.EventLog.CreateEventSource(
"MyApp1", "Application");
EventLog EventLog1 = new EventLog();
EventLog1.Source = "MyApp1";
EventLog1.WriteEntry(ex.Message,EventLogEntryType.FailureAudit);
LogExceptionToWorkflowHistory(ex.Message, executionContext, WorkflowInstanceId);
}
OutListItemID = IdRetorno;
return base.Execute(executionContext);
}
thanks