Nick's profileSharePoint DevelopmentBlogListsNetwork Tools Help

Blog


    August 31

    Change Document Library Created By and Modified By fields

    After a solid week of banging my head off my desk, I have finally mashed up a way to programmatically assign the Created By and Modified By fields in a SharePoint Document Library.  In my previous post, I mentioned moving a file from one Document Library to a newly created Document Library in a separate Site Collection.  That is all well and good.  Inserting the document worked perfectly, except for the fact that Created By and Modified By were both ‘System Account’.  This was not a proper solution.  The correct result would be the originator of the workflow’s LoginName being assigned to those columns.

    In the end, I realized that simply using RootFolder.Files.Add() meant that the Created By and Modified By fields were Read-Only.  After some more forum trolling I was able to mash up a method that took SPUser (the originator) of the workflow and pop their LoginName into both of those fields.  I ended up having to use the SPFileCollection object and after obtaining the newly created file, I had to edit the Item of that File.  The method is shown below:

    image

    Using objFolder.Files.Add(strFiletoUpload, contents, userCreatedBy, userModifiedBy, timeCreated, timeModified) would throw an error due to Created By and Modified By being Read-Only at the time of insert.  Modifying the item of the file after the insert proved to be the right solution.  Don’t forget to update the item!

    Checking out a file on behalf of another user

    Over week or two I have been busy creating a custom sequential SharePoint Workflow using Visual Studio 2008.  The client requested that a new Document Workspace be created if a user were to select a custom link I added in the EditControlBlock in the dropdown menu for an item in a Document Library.  The steps are as follows:

    1. Create DocumentWorkspace.
    2. Assign Permissions to new workspace.
    3. Copy the document that was selected into the newly created site’s Shared Documents library.
    4. Checkout the original document in the library in which the workflow was activated.
    5. E-mail the owner and members that the site was created.

    Step 4 was proving to be quite difficult due to the fact that when you call SPFile.Checkout() in the SharePoint object model, it will always check the file out as the system administrator.  After trolling the various forums I managed to nail down this one method.

    image

    Every SharePoint object created and action taken after the impersonatedSiteCollection will be made under the context of the user that activated the workflow.  This way the original user has control over Checkin/Checkout going forward.

    July 16

    WSS/MOSS PeoplePicker Customization

    Recently, I had to extend the PeoplePicker’s functionality to include lookup’s in a one-way trusted domain.  I found some great posts but decided to consolidate into one post as there were a couple of caveat’s (a.k.a. ‘Command Line Error’s in stsadm).

    1. Open a command prompt and change your directory to C:\Program Files\Common Files\Microsoft Shared\web server extensions\12\BIN.
    2. Run the following STSADM command:  stsadm.exe -o setapppassword -password [insert a random password].
      • The random password can be anything you choose. (It’s used to encrypt/decrypt the password connecting to the other domain/forest)
      • The above command must be run on each web front end of your farm installation.
    3. Run the following STSADM command:
      • stsadm.exe –o setproperty –pn peoplepicker-searchadforests –pv <list of forests or domains> -url <webapp>
        • <list of forests or domains> could equal Domain:MyDomain.com or Forest:MyDomain
        • example:  stsadm.exe –o setproperty –url http://testapp –pn peoplepicker-searchadforests –pv “domain:testpoc.com,username,password”
    4. You can add multiple domains/forests by separating everything within the –pv value with a semi-colon….which is probably a good idea if you are adding in the domain/forest connected via the one-way trust.

      Those are the two commands that you need to run in order to lookup users in another domain that is connected by a one-way trust.  For more information, please refer to the following link:  http://technet.microsoft.com/en-us/library/cc263460.aspx

      April 09

      SharePoint 2007 Virtual Earth Custom Web Part

      Hello, again.  Consider yourself lucky because I’m dropping two posts in a single day!  A rarity, for sure.

      About five months ago I created a Virtual Earth page for a client’s distributor locations around the world.  The tricky part was pulling all of this location data from a SharePoint list.  As most of you already know (or maybe you don’t), the Virtual Earth routines are all client side JavaScript.  Knowing that, you will then realize that accessing SharePoint List items is done through either A.) the SharePoint Object Model in .Net or B.) SharePoint list web services.

      Initially, I built out a separate .Net web application that pulled all of the location data from the list, wrote out separate JavaScript arrays for the location data to the client, and then pointed the Virtual Earth routines at those arrays in order to build map points.  Heavy, I know.  And by heavy, I mean lethargic on Page Load.  But hey, give me a break, mixing server side and client side code is never a fun time.  It’s also incredibly difficult to maintain.  In the end, it was the most stable method.  Stability is paramount in this case as the application is being hosted on a public website.  (In case you want to see it in action, head on over to this SITE ).

      Rewind again another month.  I stumbled upon an updated version of the Windows Live Server Controls.  Granted it’s in CTP release and nowhere near ready for primetime, I decided to tinker with their Virtual Earth Server Control.  With just one relatively simple routine I was able to process every location in the SharePoint list with absolutely zero client side code! 

      Now, instead of fussing with a separate web application stuffed into a Page Viewer Web Part, users can simply drag and drop the Virtual Earth web part onto the page!  And because I am such a sweetheart and am totally against leading people on, I have embedded a short YouTube clip as proof.

      (Sadly, there is no audio so you will be unable to hear my soothing radio voice.  Sorry, world.)

        

      You will notice that I simply put the SharePoint page in Edit Mode, search for the VirtualEarth web part, and drag/drop it onto the page.  Voila!  Next, I display the corresponding SharePoint list that houses the location titles, descriptions (address info), latitude/longitudes, etc.  Putting map locations in a list not only empowers users to manage and own their content, it cuts down on IT operations overhead.  A win-win, if you ask me.

      Customizing SharePoint Page Title and META Tags

      Recently, our group deployed a public SharePoint site for a client.  After deployment, the client requested the ability to control a page’s title and META tags at any given moment. For example, they wanted to change how product lines were indexed by Google, or how Google crawls the META tags of a particular page.  I was immediately frightened by the idea of giving them access to SharePoint Designer and letting them rip away at each page’s source.

      In the end, I decided to build a custom web part that the user could simply drop on the desired page.  Upon Page Load, this invisible web part queries a SharePoint List containing a mapping to other content lists within the site and obtains the user’s desired page title.  The code then finds the PlaceHolderPageTitle content place holder, clears the controls from it, and adds in an EncodedLiteral with the new Page Title text.

      The user also has the ability to create the Keywords and Description META tags for an individual page through this web part’s Personalization properties.

      This tool could prove to be quite powerful with regard to content management in the SharePoint public Internet site realm.  Try to view it from a site owner’s perspective.  Any person in charge of a product or product line now has far greater control over how a crawler will index their pages.  More importantly, it saves the people that deployed the site hours of headaches after someone accidentally rips out some relatively important source code on their home page!

      Below are some screenshots of the code and its results:

      private void OverridePageTitle(ArrayList queryStrings)
              {
                          EncodedLiteral pageTitle = new EncodedLiteral();
                          string literalText = string.Empty;  //you will want to build in a routine that populates this literalText

                          ContentPlaceHolder contentPlaceHolder = (ContentPlaceHolder)Page.Master.FindControl("PlaceHolderPageTitle");

                          contentPlaceHolder.Controls.Clear();

                          pageTitle.Text = literalText;
                          pageTitle.EncodeMethod = SPEncodeMethod.HtmlEncode;

                          contentPlaceHolder.Controls.Add(pageTitle);
                }

               

          private void CreateMETA(string metaTagName, string metaTagContent)

          {

                   HtmlMeta mKey = new HtmlMeta();

                   mKey.Name = metaTagName;

                   mKey.Content = metaTagContent;

                   Page.Header.Controls.Add(mKey);

           }

       

      ScreenHunter_03 Apr. 09 14.44

      Page Title Before:

      TitleInfo

      Page Title After:

      TitleInfo

      Page META (Keywords/Description) before:

      NONE!

      Page META after:

      ScreenHunter_08 Apr. 09 14.53

      January 13

      An Invitation

      On January 28th, 2009, our company, Vitale Caturano, will be hosting an all day SharePoint event at Microsoft’s office in Waltham, MA.  My colleagues and I will be demonstrating various cutting edge SharePoint capabilities ranging from Virtual Earth to Microsoft Silverlight.   Yours truly will be demonstrating how to leverage your SharePoint list data and display it within Microsoft Virtual Earth.  The event is entirely free.  There won’t be any sales situations, or services pushes., I promise.  This event is purely informational in order to give you an in depth perspective on what SharePoint can do for your firm.

      So, don’t be shy, register over at www.vitale.com/sharepoint.

      Focus%20On%20Series%20SP3

      SharePoint List Multiple Values Gotcha

      If, like me, you have a gigantic frustration with the SharePoint List Web Services and the formatting it returns, you should read on.  I was recently developing a Virtual Earth web application that pulled location data from a SharePoint list.  I employed the Lists web service on my MOSS server.

      In this case, for a certain field in the list, multiple values were allowed.  Upon return of this field, each value was preceded by a good ol’

      1;#

       

      So, if there are four values being returned from that CAML query, it will look like 1;#[value1]2;#[value2']3;#[value3]4;#[value4]

      1;#[value1]2;#[value2']3;#[value3]4;#[value4]

       

      So, I went ahead and wrote a little Regular Expression for retrieving what you actually want, and putting it in a nice “value1, value2, value3, value4” format…as one would expect.  (Of course, there are a zillion different ways to do something like this, but this was the first thing that came to mind.

                   

      string Products = row["ProductsOffered"].ToString();

      Products =

      Regex.Replace(Products, ";#[0-9][;][#]", ", ");

      Querying a SharePoint list via the Object Model

      Leveraging the SharePoint Object Model in web part development is the simplest and most efficient method of interrogating SharePoint list data.  Items from the list are returned in a ListItemCollection.  More often than not, you’ll want to bind the ListItemCollection to a .Net web control such as a DropDown List or GridView.  In the code example below, there is a method of pushing that ListItemCollection into a DataTable.

      First, we want to get the correct context:

           SPWeb sweb;
           SPSite spsite = SPControl.GetContextSite(HttpContext.Current);

       

      Next, we will access the list, and create the ListItemCollection:

           SPList searchList;

            searchList = sweb.Lists[ListName];

            SPListItemCollection searchListCollection;

       

      Now that we have the list defined, we will be able to query it.  We will create the SPQuery object.  Essentially, we will assign the SPQuery object with a CAML query.  CAML (Collaborative Application Markup Language) has a bit of a different feel, and is quite light on documentation.  I have been using the  U2U CAML Query Builder to assist in creating CAML syntax.

      The GetItems method will push all of the items returned from the query into our SPListItemCollection object.

           SPQuery searchListQuery = new SPQuery();

           searchListQuery.Query = "<OrderBy><FieldRef Name='SortOrder' /></OrderBy><FieldRef Name='" + FieldName + "' />";

           searchListCollection = searchList.GetItems(searchListQuery);

       

      The final piece will be to read the SPListItemCollection into a DataTable.

            DataTable dtSPlist = searchListCollection.GetDataTable();

       

      Listed below is the entire function.  There is also an example of obtaining a unique data set from the list as well:

      public static DataView UniqueSPListDV(string ListName, string FieldName)
              {
                  SPWeb sweb;
                  SPSite spsite = SPControl.GetContextSite(HttpContext.Current);

                  using (sweb = spsite.OpenWeb())
                  {
                      SPList searchList;
                      searchList = sweb.Lists[ListName];

                      SPListItemCollection searchListCollection;

                      SPQuery searchListQuery = new SPQuery();

                     searchListQuery.Query = "<OrderBy><FieldRef Name='SortOrder' /></OrderBy><FieldRef Name='" + FieldName + "' />";

                      searchListCollection = searchList.GetItems(searchListQuery);

                      DataTable dtSPlist = searchListCollection.GetDataTable();

                      try
                      {
                          DataTable dtUnique = dtSPlist.DefaultView.ToTable(true, FieldName); //Fill dtUnique with distinct Unit values.
                          DataView dvUnique = new DataView(dtUnique); 

                          return dvUnique;
                      }
                      catch
                      {
                          DataView dvUniqueEmpty = null;
                          return dvUniqueEmpty;
                      }
                  }

              }

      December 11

      Inaugural Post!

      Greetings!  This post marks the start of my new blog.  The writings here will be mainly focused on tips, tricks, and tutorials for custom development in MOSS 2007 (as well as WSS 3.0).  I will also try to include any new developments within the MOSS developer community with regard to the latest and greatest tools and utilities.
       
      You may also want to check out Mauro Cardarelli's blog, or Nick Bisciotti's blog for additional SharePoint goodies.  Both are extremely informative on a wide range of SharePoint topics.
       
      Also, this site is best viewed with Internet Explorer 7.