Context-Aware SharePoint Designer Custom Workflow

I had this nice little idea that I could teach the guys in my department how to do workflow with the Sharepoint designer so I wouldn’t have to do all that myself with the big Visual Studio Guns. All was going well until they needed to send out an email containing the URL of the site from which we were sending it. Not a link to an item in the site, the actual URL of the site itself.

“Simple!,” said I. I’ll just get it from the sharepoint object model with a custom activity. I wrote it all up, tried to use SPContext.Current.Web… and got it to puke nicely on a Null reference to Current. Of course! Why would a workflow activity have any reference at all to sharepoint? Technically a workflow activity doesn’t care where it’s hosted. But mine were to be hosted in Sharepoint, and that’s what I wanted to access. So, I looked around on the web and found nothing. I knew it had to be possible to get the context somehow, because other Sharepoint Designer Activities that came in-the-box were using it… so I looked for a clue.

I cracked open Microsoft.SharePoint.WorkflowActions.dll in Lutz Roeder’s Reflector, and lo-and behold there is a very cheap trick at work here!

Microsoft has implemented a custom dependency property by the name of __Context that is picked up as a Microsoft.SharePoint.WorkflowActions.WorkflowContext object IF it exists in your code. If you don’t implement such a property then it’s just not there, and nobody’s the wiser. This WorkflowContext object has a reference to .Site and .Web as properties, so it’s really handy to have at from within your custom activities that need to know where they are.

I’d like to post the code I found directly, but I can’t since it’s not mine. I will show you, however, what my code looks like.

  public static System.Workflow.ComponentModel.DependencyProperty __ContextProperty =             System.Workflow.ComponentModel.DependencyProperty.Register("__Context", typeof(WorkflowContext), typeof(FooActivity));           [Description("Context")]         [ValidationOption(ValidationOption.Required)]         [Browsable(true)]         [DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]         public Microsoft.SharePoint.WorkflowActions.WorkflowContext __Context         {             get             {                 return ((Microsoft.SharePoint.WorkflowActions.WorkflowContext)base.GetValue(FooActivity.__ContextProperty));             }             set             {                 base.SetValue(FooActivity.__ContextProperty, value);             }         }  

That’s a lot of typing if you write a bunch of these activities, so I made a codesnippet just for all of you out there to have and keep forever so you don’t have to do this. (Warning, do not just make this into a base class and derive your activities from it. It will throw an exception when you try to use it. I’m not sure why, but it does. You have to add this to every single activity you create for SPD that needs to know the sharepoint context.)

Here’s the code snippet I made:

<?xml version="1.0" encoding="utf-8" ?> <CodeSnippets  xmlns="http://schemas.microsoft.com/VisualStudio/2005/CodeSnippet">   <CodeSnippet Format="1.0.0">     <Header>       <Title>spwfactivity</Title>       <Shortcut>spwfactivity</Shortcut>       <Description>Code snippet for creating a Sharepoint-Aware Workflow Activity</Description>       <Author>Dolan</Author>       <SnippetTypes>         <SnippetType>Expansion</SnippetType>       </SnippetTypes>     </Header>     <Snippet>       <Declarations>         <Literal>           <ID>classname</ID>           <ToolTip>Class Name</ToolTip>           <Default>Activity1</Default>         </Literal>       </Declarations>       <Code Language="csharp"><![CDATA[public partial class $classname$: System.Workflow.ComponentModel.Activity   {         public static System.Workflow.ComponentModel.DependencyProperty __ContextProperty =             System.Workflow.ComponentModel.DependencyProperty.Register("__Context", typeof(WorkflowContext), typeof($classname$));           [Description("Context")]         [ValidationOption(ValidationOption.Required)]         [Browsable(true)]         [DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]         public Microsoft.SharePoint.WorkflowActions.WorkflowContext __Context         {             get             {                 return ((Microsoft.SharePoint.WorkflowActions.WorkflowContext)base.GetValue($classname$.__ContextProperty));             }             set             {                 base.SetValue($classname$.__ContextProperty, value);             }         }       public $classname$()     {       InitializeComponent();     }   }]]>       

You’ll also have to add a Parameter value to the .actions file with your activity that specifies the __Context property as an Input property.

  .   .   .   <Parameters>     <Parameter Name="__Context" Type="Microsoft.SharePoint.WorkflowActions.WorkflowContext, Microsoft.SharePoint.WorkflowActions" Direction="In"/>    .    .    .   </Parameters>

This one took me a while to figure out, but finally it worked!

If you want some more info on adding your own actions to designer (my article has thus far assumed you’re familiar with the process,) check out this link.

Update: I forgot to mention that just about the DAY after I figured this out on my own, I stumbled onto this codeproject article that dealt with this exact topic.

Just for fun I’ve also attached the snippet file so you don’t have to copy and paste it. Just save it into “%ProgramFiles%/Microsoft Visual Studio 9.0/VC#/Snippets/1033/Visual C#.”

Click here to download it.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值