in

SharePoint Blogs

The Best Place for SharePoint-related Blogs

Eric Kraus SharePoint Blog

  • Search iFilters released for Microsoft Office documents

    Microsoft has released a filter pack (collection of iFilters) which will provide search indexing for a variety of Microsoft Office documents.  The filters are compatible with a majority of the big search products, including:

    SharePoint Portal Server 2003
    Windows SharePoint Services 3.0
    Microsoft Office SharePoint Server 2007
    Search Server 2008
    Search Server 2008 Express Edition
    Exchange Server 2005
    SQL Server 2005/2008
    Windows Desktop Search 3.1/4.0.

    The Microsoft Filter Pack provides iFilters for the following file type extensions:

    .docx (Microsoft Office 2007 Word Document)
    .docm (Microsoft Office Word Macro-Enabled Document)
    .pptx (Microsoft Office 2007 PowerPoint Presentation)
    .xlsx (Microsoft Office 2007 Excel Worksheet)
    .xlsm (Microsoft Office Excel Macro-Enabled Worksheet)
    .xlsb (Microsoft Office Excel Binary Worksheet)
    .zip (WinZip File)
    .one (Microsoft Office OneNote Section)
    .vdx (Microsoft Office Visio Drawing)
    .vsd (Microsoft Office Visio Drawing)
    .vss (Microsoft Office Visio Stencil)
    .vst (Microsoft Office Visio Template)
    .vsx (Microsoft Office Visio Stencil)
    .vtx (Microsoft Office Visio Template)

    NOTE The current release is available in English only supporting both x86 and x64 systems. 

    To download the Microsoft Filter Pack or to learn more visit:  http://www.microsoft.com/downloads/details.aspx?FamilyId=60C92A37-719C-4077-B5C6-CAC34F4227CC&displaylang=en."

    Posted Jan 12 2008, 07:58 AM by erickraus with 2 comment(s)
    Filed under: ,
  • MOSS Service Pack 1 and Office 2007 Service Pack 1 Released!

    Office 2007 SP1, WSS 3.0 SP1, and MOSS 2007 SP1 have been released on Microsoft.com

    The downloads can be found at:
    http://technet.microsoft.com/en-us/office/sharepointserver/bb735839.aspx

    There are over 600 specific bug fixes across the Office server products and it is highly encouraged to upgrade to this service pack.

    Here are links to additional information:
    MOSS SP 1 Fixlist KB - http://support.microsoft.com/?id=942390
    MOSS SP 1 Description KB - http://support.microsoft.com/?id=936984
    WSS SP 1 Fixlist KB - http://support.microsoft.com/?id=942388

    WSS SP 1 Description KB - http://support.microsoft.com/?id=936988

    How to Deploy SP 1 KB - http://support.microsoft.com/?id=945013

     

  • Enable Session State in SharePoint 2007

    Here’s a quick and dirty on how to enable Session State within your MOSS 2007 farm.

    I’ve been stuck on this many times before, so for my sake and hopefully a few others’, I decided to write a quick note on the process.

    First, the biggest difference to realize is that our session state will be stored in our SQL Server database.  This is required over the traditional memory-based session because of multiple application servers in a web farm architecture.

    Secondly, in order for our web applications to store session variables in SQL, we need to “prep” the database for session state data. 

    1.  Create a Shared Services Provider.  This is required in order to enable Session State and its content database is the location of our session data.  If you already have an SSP, you can use the existing one.

    2.  If needed, associate your web application with this SSP (done by default if it is your first SSP).

    3.  In Central Administration, under Application Management, choose Session State, and ensure that it is enabled.

    4.  From a command prompt, navigate to the Microsoft.NET 2.0 Framework directory
    (typically:  C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727)

    5.  Modify your web.config:

    Uncomment the following line: 
    <add name=”Session” type=”System.Web.SessionState.SessionStateModule” />

    Modify the following line:
    <pages enableSessionState=”true” ….. />

    6.  Run the following command:

    aspnet_regsql.exe –S  <server_name>  -d  <database_name>  -ssadd  -sstype c  -E

    where:
    <server_name>  is the database server where your database is located
    <database_name>  is the content database of your shared services provider

    Run aspnet_regsql.exe /?  for more information on the remaining options


  • Modify SharePoint Document Icons

    Here’s a quick easy way to modify the icons SharePoint displays for different file types.  This procedure can also be used to configure an icon for a custom file type you may have.

    Be sure to back up any files before making any changes!

    1.  Open the 12 Hive (C:\Program Files\Common Files\Microsoft Shared\web server extensions\12)

    2.  Browse to the ...\TEMPLATE\XML folder

    3.  Open the DOCICON.XML file

    4.  Modify an existing record, or add a new one.

    Here’s an example of an XML file that a customer of mine was working with and the corresponding entry I added:

    Invoice.cif  
    <Mapping Key="cif" Value="iccif.gif"  EditText="Customer Invoice File" OpenControl=""/>


    The Value property of the node points to the /_layouts/images virtual path which can be found in the 12 Hive in …\TEMPLATE\IMAGES   - put your (.gif) icon image there.

  • Missing Web Applications When Creating SSP


    Have you ever gone to create a Shared Services Provider only to discover that the Web Application dropdownlist(s) are missing your Web Applications?

    Here is a work-around to create the shared services provider manually using the stsadm tool.   (Only the required parameters are included)

    C:\Program Files\Common Files\Microsoft Shared\web server extensions\12\bin\stsadm.exe

    stsadm –o  CreateSSP
         -title SSP1
         -url http://MOSSSite
         -mySiteUrl http://MySite.MOSS
         -sspLogin domain\user
         -sspPassword password
         -indexServer MYSERVERNAME
         -indexLocation C:\Program Files\Microsoft Office Servers\12.0\Data\Office Server\Applications



    Full description of the stsadm –o createssp  operation:
    http://technet2.microsoft.com/Office/en-us/library/667e8d5f-461d-4611-a35b-22bd554f6f6b1033.mspx?mfr=true

  • SQL Profile Import with Forms Based Authentication

    This has come up several times now and I thought I would contribute a solution that has worked for me.

    The problem:  Need to create an Audience based on a profile of a SharePoint user.  The users is, however, stored in a SQL Server membership database (outside the context of SharePoint).  The user profile needs to be imported from the SQL Server membership database into SharePoint user profile store.  This process does come out of the box with LDAP (Active Directory), but not when using Forms Authentication and SQL Server.

    Background: 
    SharePoint Publishing Site
    Two Web Applications
        Port 1234: Windows Authentication
        Port 80: Forms Authentication (pointing to SQL Server membership database)

    Gotchas:
    -When creating new properties, the length attribute is not available via the SQL Server profile.  In this example, we have set it to 100.  You should consider an alternate solution (config file maybe?) to store the max length for each property.
    -To alleviate an Object Reference Not Set to Instance error, you must specify ALL of the attributes of a property (this code is already doing that).
    -Add a reference to the Microsoft.Office.Server.dll and Microsoft.SharePoint.dll
    -By default, profiles are imported with the account name:  Provider:UserName (e.g.  CustomAspNetSqlMembershipProvider:username1)  I have commented out the code to do this, but alternatively you can add the profile in with the account name set equal to the username.

    This code works great in a console application or windows service.  The code will connect up to the profile manager for SQL Server and loop through each profile.  For each profile, it will check to make sure that SharePoint has all of the profile properties (meta data).  If not, it will add the new property before updating the SharePoint profile with the SQL Server profile value.

    Don't forget, you will need to set up your SharePoint web.config with the connectionString membership and profile attributes in <system.web>. 

    ----------------------------------------------------------------------------------------------------------------------------------

    using System;
    using System.Web;
    using System.Web.Profile;
    using System.Configuration;
    using Microsoft.SharePoint;
    using Microsoft.SharePoint.Administration;
    using Microsoft.Office.Server;
    using Microsoft.Office.Server.UserProfiles;

    string providerName = "CustomAspNetSqlMembershipProvider";
    string userAcctAlgorithm = "{0}:{1}";
    string UserName = "";
    string UserType = "";

    SPFarm farm = SPFarm.Local;
    foreach (SPService serv in farm.Services)
    {
       if (serv is SPWebService)
       {
          SPWebService webServ = (SPWebService)serv;
          SPWebApplication webApp = webServ.WebApplications["SharePoint - 80"];
          SPSite site = webApp.Sites["http://mossdemo:80 "];

          //(SP) get the context for the site we have instantiated
          ServerContext serverContext = ServerContext.GetContext(site);

          //(SP) create a new instance of the user profile manager class using the context from above
          UserProfileManager upm = new UserProfileManager(serverContext);

          //(SQL) get membership profiles
          ProfileInfoCollection profiles = ProfileManager.GetAllProfiles(ProfileAuthenticationOption.All);
      
          //(SQL) for each membership profile in SQL Server
          foreach (ProfileInfo info in profiles)
          {
             //(SP) build our account name (provider + : + username)
             //string userAccount = string.Format(userAcctAlgorithm, providerName, info.UserName);
             string userAccount = info.UserName
             UserName = info.UserName;

             //(SQL) create a profile object for the user profile
             ProfileBase pb = ProfileBase.Create(info.UserName);

             //(SP) check if user account exists and get a reference to it, if not create a new one
             UserProfile up;

             if (upm.UserExists(userAccount))
             {
                up = upm.GetUserProfile(userAccount);
             }
             else
             {
                up = upm.CreateUserProfile(userAccount);
             }

             //(SQL) loop through the properties in the SQL profiles
             foreach (SettingsProperty sp in ProfileBase.Properties)
             {
                //(SP) check if SQL property is in SP profiles
                Property tempProp = upm.Properties.GetPropertyByName(sp.Name);

                //(SP) if the property is null, it does not exist, so we need to create a new property
                if (tempProp == null)
                {
                   //(SP) set property attributes
                   Property prpty = upm.Properties.Create(false);
                   prpty.Name = sp.Name;
                   prpty.Type = sp.PropertyType.Name;
                   prpty.DisplayName = sp.Name;
                   prpty.Length = 100;
                   prpty.PrivacyPolicy = PrivacyPolicy.OptIn;
                   prpty.DefaultPrivacy = Privacy.Public;
                   prpty.Description = sp.Name;
                   prpty.IsUserEditable = true;
                   prpty.ChoiceType = ChoiceTypes.None;
                   prpty.IsMultivalued = false;
                   prpty.UserOverridePrivacy = false;
                   prpty.IsReplicable = true;
                   prpty.IsColleagueEventLog = false;
                   prpty.IsAlias = false;
                   prpty.IsSearchable = true;
                   prpty.IsUpgrade = false;
                   prpty.IsUpgradePrivate = false;
                   prpty.IsVisibleOnEditor = true;
                   prpty.IsVisibleOnViewer = false;
                   prpty.Separator = MultiValueSeparator.Comma;
                   prpty.MaximumShown = 10;

                   //(SP) add the property to the user profiles store
                   prpty.Commit();
                }
               
                //(COMBINED) add the value from the SQL profile base to the SP user profile
                up[sp.Name].Clear();
                up[sp.Name].Add(pb.GetPropertyValues(sp.Name));
                up.Commit();
             }

          }

    }

  • DLL GacUtil and Reflector Shortcuts


    Here’s a little trick to help all of us SharePoint developers working with DLLs. 

    It adds the gacutil.exe -i and Reflector.exe command to the right-click context menu.

    Get Reflector.exe at: http://www.aisto.com/roeder/dotnet/


    Now, all you have to do is right click on a dll and presto!  (make sure reflector.exe path maps correctly)


    DLLShortcuts.reg (create in notepad and double click)

    Windows Registry Editor Version 5.00
    [HKEY_CLASSES_ROOT\dllfile\Shell]
    @="c:\\reflector\\reflector.exe "%1""
    [HKEY_CLASSES_ROOT\dllfile\Shell\InstallGAC]
    [HKEY_CLASSES_ROOT\dllfile\Shell\InstallGAC\command]
    @="\"c:\\Program Files\\Microsoft Visual Studio 8\\SDK\\v2.0\\Bin\\gacutil.exe\" /i "%1""
    [HKEY_CLASSES_ROOT\dllfile\Shell\Reflector]
    [HKEY_CLASSES_ROOT\dllfile\Shell\Reflector\command]
    @="c:\\reflector\\reflector.exe "%1""

    (Note:  Thanks to Maxim for the tip on accommodating spaces)






  • SharePoint Automated Deployment Using MSBuild

    MOSS Automated Build & Deploy with MSBuild 

    Here are the steps to create an MSBuild script to:

    1.      Label Visual Source Safe project with a new version

    2.      Get latest source code to a build server

    3.      Compile source code

    4.      Look for .DDF files

    5.      Build WSPs based on DDF files

    6.      Deploy WSP to MOSS Farm

     

    Pre-Requisites:
    MOSS 2007
    Visual Source Safe (optional) – ignore Visual SourceSafe targets
    .NET 2.0 Framework (for MSBuild.EXE)
    SDC Tasks DLLs -
    http://www.codeplex.com/sdctasks
    MakeCabSDK (for creating WSP files) – Unpack in C:\makecab   - http://support.microsoft.com/kb/310618
    MSBuild Editor (I prefer Notepad)


    (click on images to open in new window)


    I am going to assume that we are skilled in creating custom components for SharePoint, including features and also configuring DDF files. 

    If not, check out one of Ted Pattison or Andrew Connell’s postings on Developing Features/WSPs.
    http://tedpattison.net/downloads.aspx
    http://www.andrewconnell.com/blog/

    Ok, first let me sympathize that this can be a rough subject for a lot of developers.  I've tried to not jump too fast and break down the steps to creating these scripts.  Bare with my lengthy post. 

    First let’s create the xml file we will use to track our version numbers.  It is pretty straight forward.  The file is used to label the project(s) in Source Safe, then increment after each build.  Name the file version.xml.



    Next, let’s create our MSBuild file.  It’s a basic text document with a .msbuild extension.  I named mine test.msbuild.

    Next, let’s add PropertyGroup items.  These properties will act like variables for our script to reference.  We will use some of these variables in this script and use some in another script.



    Now, let’s add ItemGroup properties.  These properties will act like collection variable for our script.  We can use the variables in ItemGroup to execute commands against each item in the collection.  In this example, I am including all folders and sub-folders looking for all .proj files (.csproj and .vbproj) and also excluding any sub-folders named WSSDemo.  (Sorry Ted, you were slowing my script down).  :)  I also did the same for our DDF files.




    Next, we need to add references to some DLLs that contain tasks for us to perform operations such as Visual Source Safe interaction and XML manipulation.  Add the following lines of code to your msbuild file.




    The remaining steps will be adding the targets or custom actions to perform during the script execution.  First let’s update our XML file with a new revision number. 



    Next, let’s label our Visual SourceSafe project with the version number in our XML file.  Then let’s get latest of all of the projects under our “ProjectName” project in Visual SourceSafe.



    With the source code pulled locally, we can now execute an MSBuild target to compile all of the projects included in the ItemGroup.



    Finally, be sure that the DefaultTargets attribute of the Project element is set to the Last target in your document.  Additionally, confirm that for each Target element we created, it depends on the correct one previously.

    At this point, we could be done - if all we wanted to do was compile.  But, let’s take it a step further and create a second msbuild script for the SharePoint solution (WSP) creation process. 

    Same as above, create a text file with a .msbuild extension.  I named mine wsp.msbuild.  I reused the same top section of test.msbuild including the PropertyGroup and ItemGroup variables.



    Now, we need to add three targets.  One for adding the solution to the SharePoint farm, one for deploying the solution, and another for upgrading.  The upgradeSolution target is needed so that for each time after the first, you run this script, your code will be updated in the farm.  Otherwise, you would need to do a retractSolution, deleteSolution, addSolution, deploySolution – each time.  That’s a lot of timers to create.




    Again, make sure that the DefaultTargets attribute is set to the last target in your script and that all targets listed have dependencies set up appropriately. 

    Lastly, we need to create a batch file to call our two MSBuild scripts.  A simple deploy.bat file will do:


    C:\windows\microsoft.net\Framework\v2.0.50727\MSBuild c:\build\test.msbuild
    C:\windows\microsoft.net\Framework\v2.0.50727\MSBuild c:\build\wsp.msbuild
    pause



    You're all set.  You can use the deploy.bat file to kick off your scripts, or if you're really good...run them from TFS, CruiseControl, or Visual Studio.

    SourceFiles:

    Download:  test.msbuild  |   wsp.msbuild


    (this blog comes with no warranties - use at own risk)

     

  • Create Workflow Feature to Copy Content to New List

    This post is part of a two step tutorial that walks through the process of creating a custom workflow to copy abstract or summary text of a list item into a separate list. This could be used when the list item needs to be returned in security-trimmed search results where a user may not be authenticated or may not have permission to the original content list item. After creating the workflow, it will be deployed to MOSS using a feature.

     

    Pre-Requisite Installs

    1. Install .NET 3.0 (this comes with WSS/MOSS)
    2. Install the Microsoft Windows Software Development Kit for Vista and .NET 3.0 Runtime Components
    http://www.microsoft.com/downloads/details.aspx?FamilyID=C2B1E300-F358-4523-B479-F53D234CDCCF&displaylang=en
    3. Install Visual Studio 2005 extensions for .NET Framework 3.0 (WCF & WPF)
    http://www.microsoft.com/downloads/details.aspx?FamilyID=F54F5537-CC86-4BF5-AE44-F5A1E805680D&displaylang=en
    4. Install Visual Studio 2005 extensions for .NET Framework 3.0 (Windows Workflow Foundation)
    https://www.microsoft.com/downloads/details.aspx?familyid=5D61409E-1FA3-48CF-8023-E8F38E709BA6&displaylang=en

    5. Set up the content lists:
        a. Create two Document Libraries (or Custom Lists).
        b. The "source" list name is not important, but the "destination" list should be named "DestinationContent".
        c. Add a new single line of text column to each called "Abstract".

    Let's get started with the solution….

    1. First, let's open Visual Studio and create a new project
        a. Under the Visual C# Project Type, select SharePoint and choose a SharePoint Server Sequential Workflow
       
    b. Name the project: "CopyAbstractContent"
        c. Click Ok

    New Project Picture

    Notice that in Solution Explorer, we can see the template has created a Workflow1.cs file along with a DeploymentFiles folder.

    For simplicity and consistency, I typically remove this folder and create my deployment files separately. You have to modify the files provided anyway and creating them manually allows me a consistent structure across all of my solutions. Also, I delete the .bat file and remove the Post-Build Event to call the .bat file from the project properties.


    2. Delete the DeploymentFiles folder and create a folder called CopyAbstractContent

    3. Inside the new folder, create two XML files: Feature.xml and CopyAbstractContent.xml. We'll come back to these files later

    4. Double-click on the Workflow1.cs file.

    We should now see the designer view of our workflow. Notice the onWorkflowActivated1 event that has been created automatically. This activity will fire when the workflow is activated.

    Blank Workflow Picture

    We could enter all of our code in the onWorkflowActivated1 event, but as a best practice we should create our code elsewhere and leave this event to activation-type activities.

    5. From the Toolbox, select the Code activity and drag it under the onWorkflowActivated1 event.

    The screen should now look like this.

    Code Activity Picture

    Notice the red exclamation icon next to our Code activity. This is because we have yet to define the code which will fire when the event executes.

    6. Double-click on the Code activity in the designer window. Visual Studio will create a method for you to write code and automatically link it to the activity.

    There are two important things to note here. Two private fields have been created above our code activity event method. These are the workflowId and workflowProperties. The workflowId is a unique guid that is assigned to a given instance of a workflow. The workflowProperties object is a collection of properties that relate to the workflow.

    7. Add the following code to the activity event:


    private void codeActivity1_ExecuteCode(object sender, EventArgs e)
    {
      string title = workflowProperties.Item.Title;
      string tempAbstract = workflowProperties.Item.Properties["Abstract"].ToString();
     
      SPQuery qry = new SPQuery();
      qry.Query = string.Format("<Where><Eq><FieldRef Name=\"Title\" /><Value Type=\"Text\">{0}</Value></Eq></Where>", title);

      SPList lst = workflowProperties.Web.Lists["DestinationContent"];
      SPListItemCollection itms = lst.GetItems(qry);
     
      if (itms.Count == 1)
      {
        //update
        SPListItem itm = itms[0];
        itm["Abstract"] = tempAbstract;
        itm.Update();
        lst.Update();
      }
      else
      {
        //insert
        SPListItem itm = lst.Items.Add();
        itm["Title"] = title;
        itm["Abstract"] = tempAbstract;
        itm.Update();
        lst.Update();
      }
    }


    8. Close the Workflow1.cs file

    9. Strongly name the output assembly (Project properties, Signing tab)

    10. Compile the project to generate the CopyAbstractContent.dll file

    11. Back to the two XML files we created earlier. Open the Feature.XML file.

    12. Add the default feature snippet code
        a. Right click on the page
        b. From the context menu, double-click on Insert Snippet
        c. From the sub context menu, double-click on SharePoint Server Workflow
        d. From the sub context menu, double-click on Feature.xml Code


    13. Modify the following properties:
        a. Id (unique identifier for the feature we will use to deploy the workflow) VS2005 > Toos > Create GUID (Registry Format)
                Remove "{" and "}"
        b. Title (name of the workflow)
        c. Description (description of the workflow)
        d. Scope (location of where the feature will be deployed - e.g. [Farm], [Web], [Site] )


    14. Modify the first node under ElementManifests
        a. Change the Location to the name of your second XML file: CopyAbstractContent.xml
       
    b. Remove the second node: <ElementFile Location="MyForm.xsn"/>


    Feature Picture


    15. Open the CopyAbstractContent.xml file

    16. Repeat the same steps we performed earlier to add a snippet, but this time select the Workflow.xml Code option

    17. Modify the following properties:
        a. Name (name of the workflow)
        b. Description (description of the workflow)
        c. Id (unique identifier for the workflow template -- each instance of a workflow will have its own Id as well)
        d. CodeBesideClass (name of the namespace.class that contains the workflow)
        e. CodeBesideAssembly (signature of the strongly-named assembly that contains the class above) -- use a tool like Reflector to retrieve the signature


    18. Remove the following properties
        a. TaskListContentTypeId (allows to specifies a custom content type used for tracking workflow tasks)
        b. AssociationUrl (allows to override the association page for the workflow…we will use the default)
        c. InstantiationUrl (allows to override the instantiation page for the workflow…we will use the default)
        d. ModificationUrl (allows to override the modification page for the workflow…we will use the default)
        e. StatusUrl (allows to override the status page for the workflow…we will use the default)


    19. Delete the entire <MetaData>……</MetaData> node (and all nodes below)


    CopyAbstractContentWorkflow Picture


    That's it for the project setup!


    See blog on Deploying a Custom Workflow Feature - coming very soon

  • Content Query Web Part Alternative for WSS 3.0

    While working for a small client, I was tasked to create a web part for displaying list items from separate site collections/sites.  Typically, in MOSS, I would have chosen the Content Query Web Part, but because of the constrains: (1) client is using WSS 3.0 and (2) the site is hosted through a shared-hosting service provider - the CQWP or other custom development solution was not an option.

    First let me say that I’m sure this isn’t the only way to accomplish this.  Getting a little creative, I thought of other ways to simply retrieve the content from other lists.

    My solution?  XML Web Part

    Ok, here's my story:

    1. Create a list or library that you want to access content from (if you already have the list, skip this step)

    2. From the Actions menu, click on View RSS Feed

    A new window should open with an XML view of the items in your list.

    3. Copy the URL from the browser. 

    4. 
    On the destination page, add a new XML Web Part and choose Edit > Modify Shared Web Part

    5. In the XML Link text box paste the link to the RSS feed for your list.  You can shorten up the URL by removing the fully-qualified domain name:

    e.g. 
    http://www.site.com/web/_layouts/listfeed.aspx?List=<guidhere

    to 

    /web/_layouts/listfeed.aspx?List=<guidhere>

    6. Click on the XSL Editor button and paste the following XSL stylesheet code into the text box. 

    <?xml version="1.0" encoding="ISO-8859-1"?>
    <xsl:stylesheet version="1.0" xmlns:xsl="
    http://www.w3.org/1999/XSL/Transform">
    <xsl:template match="/rss">
    <html>
    <head>
    <link rel="stylesheet" type="text/css" href="/_layouts/1033/styles/core.css?rev=5msmprmeONfN6lJ3wtbAlA%3D%3D" mce_href="/_layouts/1033/styles/core.css?rev=5msmprmeONfN6lJ3wtbAlA%3D%3D"/>
      <link href="xsl.css" mce_href="xsl.css" rel="stylesheet" type="text/css" />
      <style type="text/css"> body { font-size:0.83em;} </style>
    </head>
    <body>
      <div class="Snippet" style="border-width:0; background-color:#FFF; margin:0em">
        <dl>
          <xsl:for-each select="channel/item">
            <dd><li style="list-style: square inside; color:gray;">
             <xsl:element name="a">
                <xsl:attribute name="href">
                  <xsl:value-of select="link"/>
                </xsl:attribute>
                <xsl:value-of select="title"/>
             </xsl:element>
           </li></dd>
           <dt>
             <xsl:value-of select="description" />
           </dt>
         </xsl:for-each>
        </dl>
      </div>
    </body>
    </html>
    </xsl:template>
    </xsl:stylesheet>

    You can customize this to your liking.  It is pretty basic to start, but it does the trick.

    7. Click OK

    8. Make any other customizations to the web part, and click OK to apply the changes.

    Done!

    Like I said, it's ugly, but it works.

    If anyone has any other suggestions on how to accomplish this, or a better stylesheet to use - please comment or message me!  I am definitely NOT an XSL guy…  :)

    Posted Sep 19 2007, 05:07 PM by erickraus with 9 comment(s)
    Filed under: ,
  • Copying Wiki Pages To New Wiki Page Library via PowerShell

    This process will copy a wiki page from one library to another. 

    Note: this process will set up the destination page as a "linked" document to the original.  I'm sure there is a way to remove the "link" via code, but manually you need to accomplish this by editing the wiki page and clicking "Unlink" in the upper right of the page.  Also, any wiki links that you set up pointing to your source wiki as an absolute hyperlink (<a href....>).  The link needs to be removed and brackets added back to point to the current wiki. 

    If you are simply moving the wiki pages, choose .MoveTo() instead of .CopyTo() on the list item object.


    $oldSite = new-object Microsoft.SharePoint.SPSite("http://sitename.url.com/");

    $oldWeb = $oldSite.AllWebs["/"];
    $oldList = $oldWeb.Lists["Wiki Pages"];
    "Got Destination List"

    "Beginning Copy"

    $itemCount = 0

    $oldList.Items | foreach-object{

    $tempItem = $_;
    $tempUrl = "http://newsite.url.com/newWikiPageLibrary/" + $tempItem.Name;


    $tempItem.CopyTo($tempUrl);
    $tempUrl;

    $itemCount = $itemCount + 1;


    }

    "Done Copying " + $itemCount + " items...";

     

  • Promote XML Nodes to Columns in Form Library

    Need to automatically promote the properties (nodes) of an XML document in a Form Library using a properties.xfp file? 

    This can be accomplished by publishing an InfoPath form to a Form Library as well; however, these steps walk through a similar solution if you are not using InfoPath.

     

    1. Create a form library named "Books" in SharePoint (UI)
    2. Using SharePoint Designer, expand the "Books" node and create an XML file "Properties.xfp" in the "Forms" folder.
    3. Inside the Properties.xfp, add the following XML (CASE SENSITIVE):

     

    <Fields FormAggregation="true">

    <Field Type="Text" DisplayName="ISBN" Name="ISBN" Node="Book/ISBN" />

    <Field Type="Text" DisplayName="Title" Name="Title" Node="Book/Title" />

    <Field Type="Text" DisplayName="Last Name" Name="LastName" Node="Book/Author/LastName" />

    <Field Type="Text" DisplayName="First Name" Name="FirstName" Node="Book/Author/FirstName" />

    </Fields>

     

    1. Save the Properties.xfp file
    2. Open up your favorite XML editor (I like Notepad or EditPlus2)
    3. Create a new XML file: "0735622825.xml"
    4. Inside the new "0735622825.xml" file, add the following XML:

     

    <?xml version="1.0" encoding="UTF-16"?>

    <Book>

    <ISBN>0735622825</ISBN>

    <Title>Microsoft Office SharePoint 2007 Administrator's Companion</Title>

    <Author>

    <LastName>English</LastName>

    <FirstName>Bill</FirstName>

    </Author>

    </Book>

     

    1. In SharePoint (UI), browse to the Books form library that you created earlier
    2. Upload the new XML file you just created
    3. Done!  You should see the new XML in for the form library with SharePoint automatically creating and promoting the fields into columns of the list.
  • Create WSP solution for a feature

    How to create a wsp solution file to deploy a MOSS 2007 or WSS 3.0 feature. Prerequisites: -Visual Studio 2005 -Microsoft Office SharePoint Server 2007 (or WSS 3.0) -SharePoint Server 2007 SDK (Download here: http://www.microsoft.com/downloads/details.aspx?familyid=6D94E307-67D9-41AC-B2D6-0074D6286FA9&displaylang=en...(read more)
  • Create Event Handler Feature in WSS 3.0 or MOSS 2007

    Creating a custom event handler feature to disable all updating for document libraries: Prerequisites: -Visual Studio 2005 -Microsoft Office SharePoint Server 2007 (or WSS 3.0) -SharePoint Server 2007 SDK (Download here: http://www.microsoft.com/downloads/details.aspx?familyid=6D94E307-67D9-41AC-B2D6-0074D6286FA9&displaylang=en...(read more)
  • SharePoint Object Model - Modify List Item Document via Code

    In this demo, I will connect to a SharePoint site and iterate through a document library. In the document library, I will download an XML file, modify it, and upload it back to the document library.  

    First things first...big lesson learned:

    ** Do your development on a server with Windows Server 2003 installed (a Virtual Machine would be a cost-effective alternative) **

    1.  Create an XML file and upload it to a document library.

    <?xml version="1.0" encoding="UTF-16"?>
    <Platform>WSS</Platform>

    2. In out code, create a new SPSite object using the URL to your Site where the document library you just created exists.

    SPSite site = new SPSite("http://mossdemo.itegos.com");
    SPWeb web = site.OpenWeb("/");


    Set the following property of the SPWeb object to allow the object model to make updates to items in the list

    web.AllowUnsafeUpdates = true;

    While this step is not required, you can create a CAML (Collaborative Application Markup Language) query to return a specified result set from your list or library.  In this example, I am

    SPQuery qry = new SPQuery();
    qry.Query = "<OrderBy><FieldRef Name='Title' /></OrderBy>";


    Using the web object we created at the start, create a SPListItemCollection to hold a collection of list items (documents or other).  Then, get a reference to the first list item in the list and hold it in a SPListItem object.


    //use the CAML query above to return a collection of list items from the first list in the web
    SPListItemCollection items = web.Lists[0].GetItems(qry); 

    SPListItem item = items[0];  //get the first item in the list
     

    Now, read the File object of the list item into a byte array so that it can be loaded into a stream object

    byte[] file = item.File.OpenBinary();
    MemoryStream ms = new MemoryStream(file);


    Next, create a new XML document and load it with the stream your just defined

    XmlDocument x = new XmlDocument();
    x.Load(ms);


    Using the XMLDocument object we just created modify

    x.GetElementsByTagName("Platform").Item[0].InnerText = "MOSS";Save the XML Document to a new memory stream

    MemoryStream msNew = new MemoryStream();
    x.Save(msNew);


    Get a reference to the folder where the new document will be uploaded.

    SPFolder fldr = web.GetFolder("Investing");  //another way to get a reference to the list...this calls a list by name

    SPFileCollection files = fldr.Files;


    Add the file with the same URL and update it to reflect your changes.

    files.Add(files[0].Url, msNew, false);
    files[0].Update();

    Don't forget to close out your memory stream objects.

    msNew.Close();ms.Close(); 


    Form Library Approach

    If you are working solely with XML documents, I would recommend using a Form Library instead of a custom list or document library.  With a few minor tweaks, you can set up the form library to promote XML nodes to list item columns.  Then, when changes are made to the XML document OR the column value, the two values will be synchronized automatically. 

    See blog:  Promote XML Nodes to Columns in Form Library

    List items (XML documents) can also be queried upon using a CAML query and the promoted fields/values:

    <Eq><FieldRef Name="Platform" Type="Text"><Value>WSS</Value></Eq>

    To make modify an XML document after promoting the fields, follow the same steps as above, but instead of retieving the File property of the item, simply update the property:
     

    SPListItem item = items[0];
    item.Properties["Platform"] = "MOSS";
    item.Update();


    That's it!
     

Need SharePoint Training? Attend a SharePoint Bootcamp!

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