Reza on blogging [MVP]

THIS BLOG HAS MOVED TO: http://blogs.devhorizon.com/reza

Subscriptions

<November 2008>
SuMoTuWeThFrSa
2627282930311
2345678
9101112131415
16171819202122
23242526272829
30123456

News



toronto.sharepoint.camp


Navigation

Post Categories

Other Bloggers

Personal Links

Thursday, September 27, 2007 - Posts

Item Level Permission in workflow CreateTaskXXX activities

I wish there was an easier way of incorporating item-level security into "CreateTask" and "CreateTaskWithContetType" activities other than what SPWorkFlowTask offers.I think this is a serious requirement for many clients who asks for a process to be modeled by workflow and therefore there should be an easier way to accomplish it. sadly,workflows assume that users already have permission to access the task list and once the tasks are created by workflow, you are basically on your own to set up the required permissions. If you fail to properly set the required permissions on item level basis and aside from the issue described above, assignee might get an email regarding the new task , click on link and boom ...... ugly "Access Denied" will be thrown at his face. There is a sample activity here that you can check out , but for me it only worked in SharePoint designer and I was never able to get it to work as an activity in my custom workflows not written in SPD.

Here is the way I do it:

1) I create the Task using "CreateTaskWithContentType" activity from my workflow. Obviously, I already have a content type in place.

2) I have also attached an event handler to the content type I use above. Oops! I forgot to say that there is no way you can visually do that (except this one), so I use a programmatic approach to assign an event handler to my content type when the feature that contains my content type get activated.

3) So I have to create a Feature that contains the content type (MyTaskContentType.xml is content type definition which I will skip for the sake of code brevity)
<?xml version="1.0" encoding="utf-8" ?>
<Feature Id="5FED1202-C6B8-453e-9EC0-F328655ED4DC"
  Title="My Workflow Task Content Types"
  Description="...."
  Version="12.0.0.0"
  Scope="Site"
  xmlns="http://schemas.microsoft.com/sharepoint/"
  ReceiverAssembly="DevHorizon.SharePoint.Workflows, Version=1.0.0.0, Culture=neutral, PublicKeyToken=207a12b7817b805c"
  ReceiverClass=" "DevHorizon.SharePoint.Workflows.AddConentTypesEventHanlders">

<ElementManifests>
  <ElementManifest Location="DivRepTask.xml" />
  <ElementManifest Location="HRAdminTask.xml" />
</ElementManifests>

</Feature>

4) I create a feature receiver class for this feature, I get a reference to the content type and attach the event handler to it programmatically:

    public override void FeatureActivated(SPFeatureReceiverProperties properties)
        {
            using (SPSite siteCollection = (SPSite) properties.Feature.Parent)
            {
                using (SPWeb web = siteCollection.OpenWeb())
                {
            System.Reflection.Assembly a = System.Reflection.Assembly.GetExecutingAssembly();                   
                    SPContentType ctMyTask = web.ContentTypes["My Conent Type"];
                    ctMyTask.EventReceivers.Add(SPEventReceiverType.ItemAdded, a.FullName,"MyTaskItemEventReceiver");
                    ctMyTask.Update();
                    web.Update();
           
                 }
              }
          }

5)  Now,I need to create an event handler class named "MyTaskItemEventReceiver" that inherits from SPItemEventReceiver.Make sure you decorate this class with the right attributes to target to the featureId that contains your content type and the content type Id that you are writing this event handler for. You also need a unique GUID for your event handler

           [TargetContentType("feature id goes here", "content type id goes here")]
           [Guid("and here is the unique id for your enevnt handler")]


6) In ItemAdded method of your event handler add the following code:

            DisableEventFiring();
            SPListItem listItem = properties.ListItem;
            try
            {
                listItem.BreakRoleInheritance(false);
                listItem.Update();
                listItem =SetItemLevelPermissions(listItem.Web, listItem, SPRoleType.Contributor, listItem["Assigned To"].ToString());
                listItem.Update();
            }
            catch (Exception ex)
            {
                try
                {
                   //Add error handling code here
                }
                catch { }
            }

            EnableEventFiring();

7) And finally add this helper method somewhere accessible from within your event handler

         public static SPListItem SetItemLevelPermissions(SPWeb setSPWeb, SPListItem setListItem, SPRoleType setRoleType, string assignedTo)
        {
            int index = assignedTo.IndexOf(';');
            int id = Int32.Parse(assignedTo.Substring(0, index));
            SPUser user = setSPWeb.SiteUsers.GetByID(id);
            SPRoleDefinition roleDefinition = setSPWeb.RoleDefinitions.GetByType(setRoleType);
            SPRoleAssignment roleAssignment = new SPRoleAssignment(user.LoginName, string.Empty, string.Empty, string.Empty);
            roleAssignment.RoleDefinitionBindings.Add(roleDefinition);
            setListItem.RoleAssignments.Add(roleAssignment);
            return setListItem;
        }

Now when your workflow creates a task, its item level permission will be broken and set to "assigned to" field.Happy ending!


posted Thursday, September 27, 2007 2:00 AM by rezaa with 0 Comments

Powered by Community Server, by Telligent Systems