in

SharePoint Blogs

The Best Place for SharePoint-related Blogs

Team Eli's blog

June 2007 - Posts

  • Modifying the Workflow Association Data in SharePoint 2007 Pre-Initiation

    One of our customers wanted to use the out-of-the-box Approval workflow but wanted to pre-fill the Approvers field with users from the items metadata.  In another words, each document in a document library can potentially have a difference approver so rather than have the Approvers field pre-filled from the initial Association data, they want it populated from the Approvers field on the initiated item.

    Initially, I started out modifying the out-of-the-box Approval InfoPath form (Review-RoutingInit.xsn) and was able to successfully populate the Approvers field with hardcoded data but I then realized that I didn’t know what Item the workflow had been started on, which meant I couldn’t figure out who the Approver was for the specific item that the workflow had been started.  So, I scrapped that idea and decided to create a new InfoPath Workflow initiation page (this is the page that loads the InfoPath Forms on initiation).

    After using Lutz Roeder’s . NET Reflector to analyze the IniWrkflIPPage.aspx page, I was able to determine that if I wanted to change the AssociationData before it was populated into the InfoPath Form Control, I needed to modify the property m_formData before the page finished its databinding.

    protected override void OnLoad(EventArgs ea)
    {  
        base.OnLoad(ea);
      
       
    /* Some code commented out */  
       
    this.m_assocTemplate = SPWorkflowAssociationCollection.GetAssociationForListItemById(this.m_listItem, associationId);
      
       
    this.m_formData = this.m_assocTemplate.AssociationData;  
    --> this.m_formData = “My modified form data”;   
       
    /* More code commented out */
      
       
    this.DataBind(true);
    }


    I then went on to modify the form data using metadata from the item that initiated the workflow.  Because I wanted to inherit my custom InfoPath initiation form from IniWrkflIPPage.aspx, I realized that I couldn’t change the code in the OnLoad event, but instead needed to change it on the DataBind event. 

    protected override void DataBind(bool raiseOnDataBinding)
    {   
       if (m_listItem["Approver"] != null)
       
      
    {
            
          
    // Load form data into an XmlDocument
            
          
    XmlDocument xmlDoc = new XmlDocument();
             
           
    xmlDoc.LoadXml(this.m_formData);
             
           // Defines the namespace manager to handle using the 'my' namespace
            
          
    XmlNamespaceManager manager = new XmlNamespaceManager(xmlDoc.NameTable);
            
          
    manager.AddNamespace("my", "http://schemas.microsoft.com/office/infopath/2003/myXSD");
             
          
    // Gets a collection of all the Users specificed in the Approver field (Requires Approver field on document library)
            
          
    SPFieldUserValueCollection users = new SPFieldUserValueCollection(m_listItem.Web, m_listItem["Approver"].ToString());
            
          
    string personXml = string.Empty;
             
          
    // Loops through each user and builds out a new Person element
             
          
    foreach (SPFieldUserValue user in users)
            
          
    {
                 
             
    personXml += "<my:Person><my:DisplayName>" + user.User.Name + "</my:DisplayName><my:AccountId>" + user.User.LoginName + "</my:AccountId><my:AccountType>User</my:AccountType></my:Person>";
             
           
    }
          // Selects the Reviewers (aka Approver) in the form data and sets the innerXml = to the collection of users we built        
         
    xmlDoc.SelectSingleNode("/my:myFields/my:Reviewers", manager).InnerXml = personXml;
              // overwrites the default association data with our newly modified data
             this.m_formData = xmlDoc.InnerXml;  
    }
    }

    As it turned out, apparently some of the global variables in the IniWrkflIPPage.aspx don’t “port” very well over to my custom page, so I ended up faking it a bit.  There is probably a better way to do this but at this point I didn’t care J

    using System;
    using System.Collections.Generic;
    using System.Security.Permissions;
    using Microsoft.SharePoint;
    using Microsoft.Office.InfoPath.Server.Controls; 

    namespace TeamEli.Sharepoint.Workflow.ApprovalWorkflow
    {
      [PermissionSet(SecurityAction.InheritanceDemand, Name = "FullTrust"), PermissionSet(SecurityAction.Demand, Name = "FullTrust")]
      public class ApprovalIniWrkflIP : Microsoft.Office.Workflow.IniWrkflIPPage
      {
            //// Fields
            protected new string m_listItemName;
            protected new string m_listItemUrl;
            protected new string m_workflowName;
            protected new XmlFormView XmlFormControl;
             //// Methods
            protected override void OnInit(EventArgs e)
            {
                base.XmlFormControl = this.XmlFormControl;
                base.m_workflowName = this.m_workflowName;
                base.m_listItemName = this.m_listItemName;
                base.m_listItemUrl = this.m_listItemUrl;
                base.OnInit(e);
            }
             protected override void OnLoad(EventArgs ea)
            {
                base.OnLoad(ea);
                this.XmlFormControl = base.XmlFormControl;
                this.m_listItemName = base.m_listItemName;
                this.m_workflowName = base.m_workflowName;
            }

             protected override void DataBind(bool raiseOnDataBinding)        {            //// See above…        }
      }
    }

    With the code above precompiled into a DLL, all I needed to was modify two lines of my copied IniWrkflIPPage.aspx and that was to add my assembly and to change the page inherits to our new codebehind page.

    <%@ Assembly Name="TeamEli.Sharepoint.Workflow.ApprovalWorkflow, Version=1.0.0.0, Culture=neutral, PublicKeyToken=<<PUBLICKEYTOKEN>>"%>
    <%@ Page Language="C#" Inherits="TeamEli.Sharepoint.Workflow.ApprovalWorkflow.ApprovalIniWrkflIP" MasterPageFile="~/_layouts/application.master"   EnableSessionState="true" AutoEventWireup="false"  %>

    All that was left was to create a new Feature that calls our new initiation page.  And volia!

    Hopefully some of this made sense.  If not, let me know.

    Eli

  • Adding a Sites Listing (& Setting Owner) from WSS Object Model

    In one of my current projects, in which I am programmatically adding a new SPListItem to the Sites list (created from the Site Directory Template), I couldn't figure out how to get the Owners name to save.

    /* Doesn't save the Owner information to the Sites list */
    SPListItem
    item = siteDirectoryList.Items.Add();

    item[item.Fields.GetFieldByInternalName("Owner").Id] = string.Format("{0};#{1}", user.ID.ToString(), user.Name);

    After a number of fruitless effects to try and set the Owner field properties, I decided to take a look at all the available fields that are part of the Sites List. The list below is all the fields that were returned for my instance of Sites. Your may contain more or less depending on how much you customize your Sites List.

    ContentTypeId        Title            _ModerationStatus        _ModerationComments        File_x0020_Type
    SiteTitle        SiteURL        Description            Owner                    Division
    Region            DivisionMulti        RegionMulti            BestBet                URL
    TopSite            TasksAndTools        OwnerNew            URLStatus                Manager
    ID            ContentType        Modified            Created                Author
    Editor            _HasCopyDestinations    _CopySource            owshiddenversion            WorkflowVersion
    _UIVersion        _UIVersionString    Attachments            Edit                    LinkTitleNoMenu
    LinkTitle        SelectTitle        InstanceID            Order                    GUID
    WorkflowInstanceID    FileRef            FileDirRef            Last_x0020_Modified            Created_x0020_Date
    FSObjType        PermMask        FileLeafRef            UniqueId                ProgId
    ScopeId        HTML_x0020_File_x0020_Type                _EditMenuTableStart            _EditMenuTableEnd
    LinkFilenameNoMenu    LinkFilename        DocIcon            ServerUrl                EncodedAbsUrl
    BaseName        MetaInfo        _Level                _IsCurrentVersion            TitlewURL
    TitlewMenu

    As you can see, there are many hidden fields that are used to keep the Sites List working. Needless to say, there are two fields relating to the Owner field; Owner & OwnerNew. So, I tried setting the OwnerNew field of my Sites list and it worked!! See sample code below…

    public static void AddSiteItem(string siteDirectoryURL, string title, string url, string desc)
    {

    /* Open up a SPWeb to the Site Directory */
    SPSite portalSite = new SPSite(siteDirectoryURL);
    SPWeb siteDirectory = portalSite.OpenWeb();

    /* Get the Sites List */
    SPList siteDirectoryList = siteDirectory.Lists["Sites"];
    portalSite.AllowUnsafeUpdates = true;

    /* Create a new item in memory */
    SPListItem item = siteDirectoryList.Items.Add();

    /* Grab current user to be used as the owner */
    SPUser user = SPContext.Current.Web.CurrentUser;

    /* Set default properties */
    item[item.Fields.GetFieldByInternalName("Title").Id] = title;
    item[item.Fields.GetFieldByInternalName("URL").Id] = url;
    item[item.Fields.GetFieldByInternalName("Description").Id] = desc;

    /* Set owner field using field OwnerNew vs. Owner */
    item[item.Fields.GetFieldByInternalName("OwnerNew").Id] = string.Format("{0};#{1}", user.ID.ToString(), user.Name);

    /* Update / Save item */
    item.Update();

    portalSite.AllowUnsafeUpdates = false;

    }

    Who would have thought? Anyways, hopefully if anyone else has to do this, this will help.

    As a side note, I am using item.Fields.GetFieldByInternalName because I have multiple languages that use the same pages and strangely enough only the Title field seemed to have a common GUID across each of the languages and you can't use item["Title"] because they don't always match across languages (meaning Title is spelled differently in French or Spanish) only InternalName seemed to be constant across the languages. I could have used the index value but that is prone to change and is just bad practice.

    Eli

     

  • Welcome - Repost

    Well, now that SharepointBlogs is back (Way to go Dustin!), I thought I'd repost some of my post.  (Not there was many to begin with :)) 

    Well, I guess it is time to stick my head out from behind the monitors and start blogging about some of the experiences I have encountered with SharePoint 2007. A number of SharePoint bloggers have helped me through some tough spots and I would like to return the favor to the SharePoint community. First of all, my name is Eli Van Eenwyk. I am located in the sunny city of Buffalo (NY) where 2 feet of snow in the middle of October isn't unheard of (Come on, admit it…you are jealous…) J

    As a side note, I want to explain why I named my blog TeamEli. It all started while working onsite at one of our clients and some of their employees (whom I was working with) coined my code the ".Eli Framework" (similar to the .NET framework). This framework is alleged to be able to do anything you tell it to do. If you want it to convert WebSphere to SharePoint with the click of a button, it was DONE. As it turns out, this framework was too much for one person to manage, so we had to establish a team of developers and managers so that we could keep this framework living up to expectations. Hence, the name TeamEli. I didn't want you to think that I thought so highly of myself that I had to name a blog after myself, although if that is what you want to believe, I can't stop you. Heck, this name is better that my old high school nickname…but we will leave that story for another time.

    P.S. If this blog post doesn't turn out correctly or even show up on the right site, blame it on Word 2007. We geeks always have to try out the new things (yah yah…old news).

    If anybody has comments on any of my blogs to come, please feel free to comment.

    Eli


Need SharePoint Training? Attend a SharePoint Bootcamp!

Posts (c) their respective authors. Everything else (c) 2007 SharePoint Experts