Serge van den Oever [Macaw]

SharePoint RIP. Azure, Node.js, hybrid mobile apps

  • NAnt question: evaluate NAnt expressions in text read from file

    I have a NAnt problem: I want to read file from text (actually xmlpeek from an XML document), and evaluate the NAnt expressions defined in the text. So for example:

    FILE: Input.txt:
    This is a ${word} text!

    FILE: PropertyTest.build:
    <project default="go">
     <target name="go">
      <property name="word" value="nice"/>
      <loadfile file="input.txt" property="message" />
       <echo message="${message}"/>
     </target>
    </project>

    CURRENT output:
    This is a ${word} text!

    WANTED output:
    This is a nice text!

    Any ideas?

  • Windows SharePoint Services Software Development Kit (SDK) – 3/9/2005

    New version of the SharePoint SDK(?)

    Windows SharePoint Services Software Development Kit (SDK) – 3/9/2005

    http://www.microsoft.com/downloads/details.aspx?FamilyID=1C64AF62-C2E9-4CA3-A2A0-7D4319980011&displaylang=en

    The installer installs the documentation in C:\WSSSDK. I’m not sure if it is really newer, because the first page says: Publish date of this SDK: January 2005.

    To keep yourself up-to-date of the newest downloads on SharePoint at Microsoft, look at:

    http://www.microsoft.com/downloads/results.aspx?sortCriteria=date&OSID=&productID=353C4E9D-9E78-4435-A360-01BB7F540D17

  • SharePoint DVWP: view XML results of your query

    When you create your own XSLT transformations in the data view web part you need to know the format of the XML resulting from the specifed query. Given this XML you can expiriment outside of FrontPage with an XSL tool like XSelerator to do real XSLT debugging. Note that outside of FrontPage (or online editing of the DVWP) you can’t use functions in the ddwrt namespace. 

    To get the XML results you can use a simple XSLT transformation. Edit the XSLT part of the DVWP via frontpage, or press the XSL Editor “Source Editor…” button in the toolpane of the data view web part:

    DVWPSourceEditor

    Now replace the current xslt transformation with the following code:

    To get a view like this:

    DVWPSourceViewSimple

    Or if you want to have a more fancy view like this:

    DVWPSourceViewLeftDVWPSourceViewRight

    use the following code which utilizes dp.SyntaxHighlighter

    With this more advanced view I had FrontPage crashing on save of the code. So maybe you can better stick to the simple view. Another problem I had with the advanced view is that the output was not always rendered correctly, I thing due to a shortcomming in the syntax highlighting code.

    One problem is that any typo in your query will result in an error message, use the back button to get back to your edit screen again and solve the problem (if your working with the online view). With FrontPage you can directly correct the problem because you have a complete source code view.

  • SharePoint DVWP: xslt limitations...

    John Jansen (Microsoft Office FrontPage) confirmed in a private e-mail conversation what I did find out the hard way:

    In the Xslt transformation of data view web parts the following functionality is blocked:

    • msxsl:script
    • xsl:include
    • xsl:import

    I can understand that msxsl:script is blocked, otherwise you could execute any server-side script. Why xsl:include and xsl:import is not supported I really don’t understand. Could be that they scan the script code string to be executed for the msxsl:script tag, and that handling inclusion of external code was to much work, but it makes data view programming really hard. Would be great if you could create a library of useful Xslt routines and include those in your custom xslt transformations.

    Another thing I have been working on is the possibility to register additional xslt extension object like the one in the ddwrt namespace (see also http://weblogs.asp.net/soever/archive/2005/01/03.aspx), but I never succeeded.

    Any ideas on extending the xslt transformations functionality in data view web parts?

  • Macaw Discussion Board... the way SharePoint discussions should work... and now do work!

    The Macaw Discussion Board

    This weblog post describes the immediate availability of a reworked and improved discussion board for Windows SharePoint Services and SharePoint Portal server providing last-post first views, a discussion thread view, and SWYRO (See What You Respond On). It is available on http://spsutil.sourceforge.net. This post is it’s documentation.

    Introduction

    It is great that SharePoint supports discussion lists, its a pity that their implementation is "suboptimal".

    The two biggest problems that I have with the discussion lists are:

    • When you reply on a discussion item, you don’t see the text you are replying on
    • Discussion items are displayed in the wrong order: oldest items first!

    Changing this behavior is not as easy as providing a new view. Some more work is required.

    We worked around these limitations more than a year ago, but I never found the time to make these modifications available to the community. Until now…

    The features

    There are two views on a discussion:

    • Complete thread index, latest started discussion thread at the top
      DiscThreadIndex
    • Latest posts view, shows the latest 40 posts with the newest post at the top
      DiscLatestPosts

    The thread index view provides the following information:

    • Title of first post in thread
    • Started by
    • Number of Replies
    • Last Post (date + poster)

    On selecting a thread, a hierarchical view of this discussion thread is displayed:
    DiscSingleThread

    If you are not sure from a certain reply on which post it is replying, you can select the “parent” link:
    DiscParentItem

    If you look at the content of a single post (for example after following a link from an alert e-mail), there is a view in thread link available to view the post highlighted in its complete discussion thread:
    DiscViewInThread

    Some other interesting features:

    • When you click on the name of a poster, you go to the UserInfo information on the user on WSS, and to the profile page of the user when on SharePoint Portal Server
    • Complete support for presence detection on all user names
    • Completely built on top of the standard WSS discussion board

    Availability

    The Macaw Discussion Board is available at http://spsutil.sourceforge.net. It is distributed as a SharePoint List Template: MacawDiscussionBoard1.0.stp.

    And if you are looking for the sourcode: it’s all there. Just fire up your FrontPage 2003 and you can look right in to it! I hope your XSLT skills are a bit up-to-spec;-)

    Installation

    The MacawDiscussionBoard List Template is constructed for usage in standard WSS sites. Usage in Portal Area’s is not tested. To test it out, create an empty top level site:DiscEmptySite

    Goto “Site Settings”, and select “Go to Site Administration”:
     DiscSiteSettings

    If you are on a top level site, you will see the option “Manage list template gallery”. If you don’t see this option, go to the top level parent of the current site and perform the actions from there:DiscTopLevelSiteAdmin

    On the List Template Gallery you can upload a new list template:
    DiscListTemplateGallery

    Specify the list template file, and press “Save and Closed”:
    DiscUploadTemplate

    The List Template is now available, select “Create” to add an instance of this new template:
    DiscTemplateUploaded

    Select the MacawDiscussionBoard:
    DiscCreate

    And you are done!! Congratulations!

    If you want a more permanent availability of the list template, and you are a SharePoint administrator, you can add the list template using the stsadm.exe tool on the SharePoint server. See the Administrators Documentation for more information.

    Troubleshooting

    If the Macaw Discussion Board list template does not appear under Discussion Boards in the Create screen, you are probably in a site or area that does not support the list template. Please test first is a standard WSS site.

    Limitations

    The Macaw Discussion Board has some limitations. For the Thread Index view, information on all items must be retrieved on server side. Happely enough NOT the body text;-). This means that performance can degrade on discussion lists which huge amount of posts. We have a discussion list with over 2500 posts without any problems. Let me know if you run into trouble, we can make somethig up.

    Configuration

    Some things on the discussion board can be configured like the styles of odd/even/selected posts in a discussion thread, the indenting in a hierarchical thread view, and the formatting of date/time. To do this configuration open the pages of the Macaw Discussion Board in FrontPage 2003.

    The following pages have configuration options (look for it in code view):

    AllItems.aspx:

            <!-- CONFIGURATION SECTION FOR DISCUSSION RENDERING -->
            <!-- format of date time rendering, uses standard .NET format as specified in http://authors.aspalliance.com/aspxtreme/aspnet/types/datetimeformatstrings.aspx -->
            <xsl:param name="PostDateTimeFormat">dddd, MMMM dd, yyyy H:mm</xsl:param>
            <!-- END OF CONFIGURATION SECTION FOR DISCUSSION RENDERING -->
     

    SingleThread.aspx:

            <!-- CONFIGURATION SECTION FOR DISCUSSION RENDERING -->
            <!-- style for odd/even/selected items in the thread -->
            <xsl:param name="OddItemStyle">background-color: #dddddd;</xsl:param>
            <xsl:param name="EvenItemStyle">background-color: #eeeeee;</xsl:param>
            <xsl:param name="SelectedItemStyle">background-color: Yellow;</xsl:param>
            <!-- format of date time rendering, uses standard .NET format as specified in http://authors.aspalliance.com/aspxtreme/aspnet/types/datetimeformatstrings.aspx -->
            <xsl:param name="PostDateTimeFormat">dddd, MMMM dd, yyyy H:mm</xsl:param>
            <!-- message when page in called without 'discussion' parameter -->
            <xsl:param name="NoThreadMessage">The Single Thread view can only display information if a thread is specified.</xsl:param>
            <!-- indentation level in pixels for threaded items in the tree -->
            <xsl:param name="TreeIndentation">10</xsl:param>
            <!-- END OF CONFIGURATION SECTION FOR DISCUSSION RENDERING -->

    NewForm.aspx:

            <!-- CONFIGURATION SECTION FOR DISCUSSION RENDERING -->
            <!-- style for odd/even/selected items in the thread -->
            <xsl:param name="OddItemStyle">background-color: #dddddd;</xsl:param>
            <xsl:param name="EvenItemStyle">background-color: #eeeeee;</xsl:param>
            <xsl:param name="SelectedItemStyle">background-color: Yellow;</xsl:param>
            <!-- format of date time rendering, uses standard .NET format as specified in http://authors.aspalliance.com/aspxtreme/aspnet/types/datetimeformatstrings.aspx -->
            <xsl:param name="PostDateTimeFormat">dddd, MMMM dd, yyyy H:mm</xsl:param>
            <!-- message when page in called without 'discussion' parameter -->
            <xsl:param name="NoThreadMessage">The Single Thread view can only display information if a thread is specified.</xsl:param>
            <!-- indentation level in pixels for threaded items in the tree -->
            <xsl:param name="TreeIndentation">10</xsl:param>
            <!-- END OF CONFIGURATION SECTION FOR DISCUSSION RENDERING -->
     

    Applying the Macaw Discussion Board changes to an existing discussion list

    Note: The below procedure has not been extensively tested. You are on your own, so please know what you are doing!

    It is possible to apply the Macaw Discussion Board to an existing discussion list. You can do this using FrontPage 2003.

    • Make a backup of your site containing the discussion list to modify!!!
    • Install the Macaw Discussion Board somewhere so you can access it’s pages usintg FrontPage 2003
    • Lookup the list name of the existing discussion list (GuidExisting). Look for example at the code of the EditForm.aspx page. At the end you see the following line with the GUID which is the list name:
      <ListName xmlns="http://schemas.microsoft.com/WebPart/v2/ListForm">{2F9B130C-EDE0-47D5-AF8C-E0A9B696DFEA}</ListName>
    • Lookup the list name for the installed Macaw Discussion Board (GuidMDB)
    • Make a copy of all pages in the existing list (make for example a backup directory in the List folder (at the same level as you .aspx list pages). Don’t move the pages, otherwise the interrnal links for the list pages gets messed up!
    • Copy over the pages of the Macaw Discussion Board instance to the existing list, overwriting the existing pages of your list instance.
    • On all pages do a replace of the Macaw Discussion Board instance GUID (GuidMDB) with the GUID of the original list (GuidExisting).
    • Remove any pages that are not also in the Macaw Discussion Board instance
    • Done!!

    If there is a need for an application that performs these actions, please let me know and *maybe* I’m in the mood to create one!

    Licensing

    Macaw Discussion Board License Agreement

    You can use this Software for any commercial or noncommercial purpose, as long as the Macaw Discussion Board is not marketed and sold as if it is your own application. In return, we simply require that you agree:

    • Not to remove any copyright notices from the Software.
    • That if you distribute the Software in source code form you do so only under this License (i.e. you must include a complete copy of this License with your distribution), and if you distribute the Software solely in object form you only do so under a license that complies with this License.
    • That the Software comes "as is", with no warranties. None whatsoever. This means no express, implied or statutory warranty, including without limitation, warranties of merchantability or fitness for a particular purpose or any warranty of noninfringement. Also, you must pass this disclaimer on whenever you distribute the Software.
    • That neither Serge van den Oever [Macaw] nor any contributor to the Software will be liable for any of those types of damages known as indirect, special, consequential, or incidental related to the Software or this License, to the maximum extent the law permits, no matter what legal theory it's based on. Also, you must pass this limitation of liability on whenever you distribute the Software.
    • That if you sue anyone over patents that you think may apply to the Software for a persons use of the Software, your license to the Software ends automatically.
    • That the patent rights, if any, licensed hereunder only apply to the Software, not to any derivative works you make.
    • That your rights under this License end automatically if you breach it in any way.

    FAQ

    Q1: Why is there no threaded view with newest thread on top. Same as the default view for a standard discussion board, but then implemented “right”?

    A:1 We have such a view at my company, but I could not get it working;-) There also is not really a need for such a view in my opinion. I never use the view at work, and no forum implementation uses such views.

    Q2: How about multilanguage support, do you support any other language than English?

    A2: I have no idea what happens if you install this on a site that is in another language. All texts in the discussion board will definitly remain in English. There is even a chance of broken link to the administrative pages because they link to the /_layouts/1033 directory. If anyone has any information on this (and information on making "language-neutral" templates)...

    Q3: When I add new views to the discussion list, they don’t become visible in the left menu.

    A3: This is by design. Because the wrong pages ended up at the left menu, I did add the links above “Actions” (The “Discussion” menu) manually. If you want to add a view, modify the pages AllItems.aspx (Thread Index), Latest.aspx and SingleThread.aspx.

    Acknowledgements

    Thanks to my colleagues Arjan Paauw and Olaf Conijn for input in the implementation of the Macaw Discussion Board.

  • Cool: monoppix, try out Mono on linux directly from CD

    I was amazed by the Knoppix version of Linux, that you could direcrtly run from CD and even USB memory stick. Great to have a look at some things you can do with Linux. Now someone created a special edition featuring the Mono technology, a free .Net framework implementation.

  • SharePoint DVWP: display profile page on user link

    FrontPage 2003 has a great feature when converting a CAML view on a list to a XSLT data view. One problem in this conversion is that the link on a user name changes from for example UserDisp.aspx?ID=1 naar UserDisp.aspx?Force=True&ID=1. This forces the display of the information available in the UserInfo table on a user. This happens even if SharePoint Portal Server is used, and in the CAML viewt he profile page of the user in the user its my site was displayed.

    This “wrong” URL is generated by a DDWRT function URLLookup.

    You can get back the correct behaviour by removing the Force=True as follows:

    Look for a line similar to:

    and convert it into:

  • SharePoint query-language... documented...!

    I feel bad for blaming Microsoft for having no documentation on the dsQuery language… its there: http://msdn.microsoft.com/library/default.asp?url=/library/en-us/spptsdk/html/soapmqueryRequest_SV01071735.asp. Click through on the keywords and you end up in the CAML keywords…

     Reyn wrote even some piece of code to generate these queries in an easy way from C# code. See his weblog entry at http://dotnet.org.za/reyn/archive/2004/07/13/2738.aspx, and the code download at http://www.reyn.co.za/index.php?pr=SP_Query_Builder.

  • SharePoint query-language... completely undocumented....

    When you convert a SharePoint list view (defined in CAML) to a XSLT Data View, Frontpage generates a query that looks like:

    And the strange thing is that virtually NO information is available on the query syntax.Why o why are such large portions of SharePoint still undocumented?

    If anyone has some pointers for me to documentation on this stuff, please let me know!!

  • New version of SharePoint SDK's

    I love this new service of Microsoft to keep you up to date of updates and new software on Microsoft Download Center. Sign up at http://go.microsoft.com/fwlink/?LinkId=39737.

    This way I heard of the new SharePoint SDK’s that are out (jan05 version):

    WSS SDK: http://www.microsoft.com/downloads/details.aspx?FamilyID=1C64AF62-C2E9-4CA3-A2A0-7D4319980011

    SPS SDK: http://www.microsoft.com/downloads/details.aspx?familyid=aa3e7fe5-daee-4d10-980f-789b827967b0

    About the SPS SDK:

    What’s new in the January 2005 update for SharePoint Portal Server 2003:

    • Getting Started section that offers:
      • An expanded introduction to SharePoint Portal Server
      • Expanded Concepts and Architecture section with new topics about Profiles and Personalization, Search, and Enterprise Application Integration, and more
      • New Code Snippets section with code examples for topics such as the Audience, User Profiles, and Security object models
      • New FAQ section that offers answers to a wide range of questions about SharePoint Portal Server, including customization issues
    • Expanded Reference topics that address:
      • Microsoft SharePoint Portal Server Search SQL Syntax
      • Protocol Handlers
      • IFilter Administration

    If you are looking for the location where the SPS SDK is installed, on my machine it ended up at C:\SPPTSDK.

  • Q: accessing javascript functions/variables outside windows object

    Here a copy of a question I mailed to the creators of IeUnit. It is a very generic question, maybe someone somewhere out there in blogspace can help me out on this.

    I try to achieve something that I don’t seem to get done…

     

    In IeUnit a window is opened (through cscript) to access my web page using code like:

     

    win = WScript.CreateObject("InternetExplorer.Application");

     

    We then navigate to the page to test:

     

    win.navigate(accesstest.htm”);

     

    where accesstest.htm is a page containing the following html:

     

    <html>

    <head>

    <title>My test title</title>

    <script language="javascript">

    var getThis=10;

    document.getThat=20;

    </script>

    </head>

    <body>

    </body>

    </html>

     

    I can now display things like:

     

    win.document.title à My test title

    win.document.getThis à 10

     

    but….

     

    How can I access the getThis variable in the page?

     

    And why do I need this: I’m creating an IeUnit extension lib for testing SharePoint pages. I want to access the Web Part Page Services Component, defined in a variable WPSC. But I can’t access this variable from my test classes.

  • NAnt intellisense in VS.NET 2003

    I know, a zillion people wrote about intellisense in VS.NET for NAnt files already, but just as a reminder for myself I write this blog entry:

    • Create a file NAntGenerateSchema.build with the following NAnt code, modify the SchemaFile property for your installation diretory/version of VS.NET:

      <?xml version="1.0" encoding="utf-8" ?>
      <project name="GenerateNAntSchemaForVS.NET" default="genschema">
          <property name="SchemaFile" value="C:\Program Files\Microsoft Visual Studio .NET 2003\Common7\Packages\schemas\xml\NAnt.xsd"/>
          <target name="genschema">
              <nantschema output="${SchemaFile}" target-ns="http://nant.sf.net/schemas/nant.xsd"/>
          </target>
      </
      project>

    • Call this script each time you add some extra tasks dll’s or when you move to a new version of NAnt, because it generates a schema based on the available NAnt tasks.

    • Add you NAnt build file to your VS.NET project (if possible).

    • Open the .build file in VS.NET using File->Open…->File…, and then notice the extra options in the lower right corner of the open file window, select Open With…:
      FileOpenExtraOptions

    • Now select to open this file as selected below, also click Set as Default:
      FileOpenOpenWith

    • Set in the properties window for this file the targetSchema to the NAnt schema:
      NAntSchema

    • Repeat for all your build files. Done.

  • SharePoint web part development: resources you should read

    When you dive into web part development for SharePoint 2003 and need some reading on the topic, have at least a look at the following articles:

    And if you don’t wan’t to go the hard way… have a look at Smart Part, a generic web part that allows hosting of user controls. Have a look at Jan’s blog for more info: http://weblogs.asp.net/jan/

  • Reduce SharePoint page rendering time by utilizing asynchronity in web parts

    You never know which web parts end up in a SharePoint page. That is the power of web parts: combine them the way you see fit. But what if one web part accesses a web service that takes 3 seconds to complete, and another web part renders content from a database that takes 4 seconds…. If the web parts are not programmed with asynchronity in mind, you will end up with a rendering time of 7 seconds for your page, instead of just over 4 seconds as could be achieved when you follow “the rules”…

    The SharePoint web part framework has great support for asynchronous actions in SharePoint, including support for timeouts on asynchronous actions.

    For more information on this topic see:

  • Unit testing SharePoint

    We are doing extensive development for SharePoint Portal Server for one of our large customers. Besides producing a lot of interesting code, we are also settings up a kind of software factory for SharePoint development. More on this in later posts.

    We now have the continuous integration builds and automatic deployments up and running. Units tests against the business code can be executed, and FxCop checks are done on the code.

    The next step is automatically testing the deployment against a set of pages, where each page represents (part of) a use case. Are web parts functioning? Do they give the output you expect? Are skinning actions done by the MacawSharePointSkinner successful?

    I’m currently looking into IeUnit. This looks like a very powerful web page testing framework, you run javascript tests that can directly talk against the DOM in IE, these tests can be executed from the command line, and the results can be output in an XML format that can be interpreted and merged by CruiseControl.Net (our Continuous Integration platform).

    The test framework is extensible, so it would be great to extend it with the knowledge of zones, web parts, and other SharePoint specific functionality.

    Did someone already go in this direction, or do you have other tips on testing the resulting web pages of SharePoint Portal Server? Please enlighten me!

  • CruiseControl.Net 0.8 is out!!

     Hurray! CruiseControl.Net 0.8 is out with some great new features and bugfixes!! Have a look at http://confluence.public.thoughtworks.org/display/CCNET for more information.

    No clue what CruiseControl.Net is? Get reading!

     

     

  • Again: Reporting Services web parts in SP2

     Jan Thielens has a weblog entry with some screenshots about the new Reporting Services SP2 SharePoint web parts. Have a look at http://weblogs.asp.net/jan/archive/2005/01/21/358073.aspx.

    It is now also possible to get SQL server SP4 (beta) and Reporting Services SP2 (beta) at http://www.microsoft.com/sql/evaluation/betanominations.asp.

    Jan is a bit disappointed in the web part functionality… maybe Bryant must continue on his development on the RS Web Parts and make it an open source community project as he suggests at http://blogs.sqlxml.org/bryantlikes/archive/2005/01/24/2638.aspx.

     

  • VS.NET and hintpath problems...

    In a project we are working with multiple developers AND a build server on a large set of Visual Studio solutions. Problem is that when we have references to a folder with shared assemblies, the relative path to those assemblies specified by a hintpath directive in the .csproj file ends up wrong. The solution file opens up on one system. but fails on another system (reference not found). We also have problems in our automated builds (using the NAnt solution task).

    A fix to this is setting a registry entry to the folders with shared assemblies, if the assembly can't be found, this path is checked.

    Add a key with any name to HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\VisualStudio\7.1\AssemblyFolders, and set its (Default) value of type REG_SZ to the path with your assemblies.

  • The dirty world of SharePoint programming

    Sometimes SharePoint drives you mad. Case of today:

    When you add a QuickLink to a person in SharePoint portal server you get a link to the /mysite/public.aspx page with on the URL in most cases an accountname parameter, so for example http://server/mysite/public.aspx?accountname=DOMAIN%5cusername. There are also situations where instead of an accountname parameter we got the parameter sid. No problem: convert the SID to accountname, done! Not. This SID is not a standard Windows SID. But the public.aspx page knows how to find the profile for this person... If you disassemble the (obfuscated) code that converts a sid to a usable profile object you see that a LOT of shit happens... to much to reproduce in your own code. But there is a dirty solution to retrieve any property from a user it's profile, while providing any of the following options on the URL:

    accountname=....
    guid=...
    sid=...
    preferredname=...

    Make a page: GetProfileProperty.aspx

    <%@ Register Tagprefix="SharePoint" Namespace="Microsoft.SharePoint.WebControls" Assembly="Microsoft.SharePoint, Version=11.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %>
    <%@ Register Tagprefix="SPSWC" Namespace="Microsoft.SharePoint.Portal.WebControls" Assembly="Microsoft.SharePoint.Portal, Version=11.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %>

    <SPSWC:ProfilePropertyLoader runat="server" />
    <SPSWC:ProfilePropertyValue PropertyName="AccountName" ApplyFormatting="false" runat="server" />

    Call it like GetProfileProperty.aspx?accountname=domain\user

    In the sample code the AccountName is returned, but you can use any property name, or even make the property itself a parameter.

    In your code you have to execute a call to the page using the WebRequest class. The result is the property value in plain text.It is an extra roundtrip, but sometimes you don't have many alternatives...

  • SharePoint, Data View web parts and functions in the ddwrt namespace

    THIS BLOG POST TURNED INTO AN MSDN ARTICLE. SEE http://msdn.microsoft.com/library/default.asp?url=/library/en-us/odc_SP2003_ta/html/OfficeSharePointDDWRT.asp FOR THIS ARTICLE. BUT… ALSO CHECK THIS BLOG POST, IT CONTAINS SOME INFO CENSORED IN THE ARTICLE;-)

    Summary

    Topic: Data View web part, XSLT, XSLT Extension Object, ddwrt namespace, Windows SharePoint Services, SharePoint Portal Server 2003, FrontPage 2003

     

    SharePoint has a powerful type of web parts: Data View web part (DVWP) that has the ability to provide an XSLT transformation on XML data retrieved from a data source. FrontPage 2003 has great support for defining the data source to retrieve XML data from, for WYSIWYG creating of XSLT views on this data, and for converting CAML list views (WSS list views) to XSLT.

     

    In the XSLT generated by FrontPage an XSLT Extension Object is used to provide functions in the ddwrt namespace to perform often needed functionality like accessing properties of a list or firing events to connected web parts. This article tries to shed some light on these undocumented but much used functions.

    Introduction

    This is an article I started exactly one year ago, but never finished. I was using one of the most powerful features you get when using FrontPage in combination with Windows SharePoint Services (WSS) and Microsoft Office SharePoint Portal Server 2003 (SPS): the ability to create Data View web parts (DVWP). It is one year later, Christmas again, and in the meantime not much information appeared on the subject of this article: the functions available in the ddwrt namespace as used in the FrontPage generated Data View XSLT code.

     

    Many introductory articles have already been written on the topic of DVWPs, so I will not repeat all this useful information. I consider those articles as prerequisite reading and will try to go from there by showing the available functions, and what they do.

     

    Disclaimer: I’m on vacation and only have access to Reflector, the Microsoft.SharePoint.dll and Word, so no possibility to check out things. I have to rely on my notes taken in the past, and the disassembled code using Reflector. If you find any untruthful information or if you have any additional information: let me know and I will correct/include it in this article.

     FrontPage and DVWPs

    One of the first things to mention is that although FrontPage is a great tool to create a DVWP, all the logic is already available in SharePoint (WSS) itself (see also http://weblogs.asp.net/soever/archive/2004/05/14/131698.aspx). This logic consists of the following parts:

     

    • Microsoft.SharePoint.WebPartPages.DataViewWebPart, a class available in the Microsoft.SharePoint.dll assembly that implements the DVWP functionality.
    • Microsoft.SharePoint.WebPartPages.DdwRuntime, an internal class available in the Microsoft.SharePoint.dll assembly that is made available as a XSLT Extension Object that provides a set of functions in the ddwrt namespace. The set of functions this article is about!!
    • Data view web part definition, a .dwp file describing the assembly implementing the web part and the configuration parameters for the web part.

     

    It is possible to create data DVWPs without using FrontPage. It is difficult, but it is possible. A DVWP is just a .dwp file which is an XML file that contains information for the data query and the XSLT transformation.

     

    One thing FrontPage does really good is the conversion of a SharePoint list view (defined in Collaborative Aplication Markup Language, or CAML for short) to an XSLT transformation that transforms the data retrieved using the list web service to the same view as defined in CAML. In the past I wrote a weblog entry (http://weblogs.asp.net/soever/archive/2004/03/10/87295.aspx) about how FrontPage accomplishes this wizardry using an XSLT transformation that is available in your office directory.

     

    Besides the CAML transformation, FrontPage provides WYSIWYG functionality to create a nice view on data. It does this by interactively defining an XSLT transformation on XML data retrieved from multiple types of data sources.

    DataViewWebPart, Vars and the ddwrt namespace

    It is the Data View web part implemented in the class Microsoft.SharePoint.WebPartPages.DataViewWebPart that utilizes the internal class Microsoft.SharePoint.WebPartPages.DdwRuntime to provide utility functions. John Janssen stated in a usenet discussion: “They were created to maintain parity between data views and list views (so that in the convert case the data view behaves just the same as the list view).” But the problem is that we want to give our own twist to how the result works, otherwise we didn’t have to convert them in the first place! The utility functions are made available by creating an XSLT Extension Object. To take a peek in the kitchen have a look at the obfuscated function Microsoft.SharePoint.WebPartPages.DataViewWebPart.q(). In this functions three important things happen:

    1. The DdwRuntime class is added as an Extension Object
    2. The Vars name-value collection as available in the XSLT transformation through ddwrt:Vars[“name”], filled with all kind of interesting information
    3. A large set of XSLT parameters is defined.

     

    The powerful thing of the Vars collection is that this collection is persisted over page request in the ASP.NET viewstate, so it can be used to persist information from the XSLT transformation of the current page request to the XSLT transformation of the next page request.

     

    The Vars name-value pairs that I could find:

    Name

    Value

    Filter

    Empty string

    View

    {GUID}, the “StorageKey”of the web part. Don’t know yet what this means.

    FreeForm

    FALSE

    WPQ

    WPQ1

     

    XSLT parameters I could find (no namespace):

    Parameter

    Value

    HttpHost

    URL of the top level site of the current web

    Language

    LCID of the language used on the site, for example 1033 for an English site

    ImagesPath

    Url of the images path, in the context of the current web, so for example http://server/sites/test/_layouts/images/

    HttpPath

    Url of the path to the appropriate OWSSVR.DLL file in the context of the web we are in. For example http://server/sites/test/_vti_bin/owssvr.dll?CS=109, where CS=109 means that the UTF-8 character set is used for all communication to owssvr.dll.

    HttpVDir

    Root directory of the current subsite, so for the page http://server/sites/test/default.aspx, the value is http://server/sites/test/.

    PageUrl

    The directory of the currently requested page. For example http://server/sites/test/default.aspx.

    Project

    The root folder of a list, if the current page request is in the context of a list. This is the name of the folder that contains all the files used in working with the list. In most cases this is the Forms folder.

    View

    {GUID}, the “StorageKey”of the web part. Don’t know yet what this means.

    ListProperty_TemplateUrl

    When the current page request is in the context of a list, and the list is a Document Library:

    Url of the template document for this document library.

    ListUrlDir_FALSE

    When the current page request is in the context of a list: Complete Url to the root folder of the list(see Project).

    ListUrlDir_TRUE

    When the current page request is in the context of a list: Name of the root folder, same as Project (see Project).

    URL_New,URL_NEW

    When the current page request is in the context of a list: Url to the page for creating a new item in the list (newform).

    URL_Edit, URL_EDIT

    When the current page request is in the context of a list: Url to the page for editing an existing item in the list (editform).

    URL_Display, URL_DISPLAY

    When the current page request is in the context of a list: Url to the page containing the default view of the list (displayform).

     

    If you look at the XSLT code generated by FrontPage you will find a large set of additional XSLT parameters. To have a look at the values of a lot of these parameters you could include the following XSLT code that writes out their values to the HTML code generated for the DVWP:

     

    <!-- Dump parameters -->

    PageUrl: <xsl:value-of select="$PageUrl"/><br/>

    HttpHost: <xsl:value-of select="$HttpHost"/><br/>

    List: <xsl:value-of select="$List"/><br/>

    URL_Display: <xsl:value-of select="$URL_Display"/><br/>

    HttpVDir: <xsl:value-of select="$HttpVDir"/><br/>

    View: <xsl:value-of select="$View"/><br/>

    FilterLink: <xsl:value-of select="$FilterLink"/><br/>

    Language: <xsl:value-of select="$Language"/><br/>

    dvt_adhocmode: <xsl:value-of select="$dvt_adhocmode"/><br/>

    dvt_adhocfiltermode: <xsl:value-of select="$dvt_adhocfiltermode"/><br/>

    dvt_fieldsort: <xsl:value-of select="$dvt_fieldsort"/><br/>

    dvt_sortfield: <xsl:value-of select="$dvt_sortfield"/><br/>

    dvt_groupfield: <xsl:value-of select="$dvt_groupfield"/><br/>

    dvt_groupdisplay: <xsl:value-of select="$dvt_groupdisplay"/><br/>

    dvt_sortdir: <xsl:value-of select="$dvt_sortdir"/><br/>

    dvt_groupdir: <xsl:value-of select="$dvt_groupdir"/><br/>

    dvt_filterfield: <xsl:value-of select="$dvt_filterfield"/><br/>

    dvt_filterval: <xsl:value-of select="$dvt_filterval"/><br/>

    dvt_filtertype: <xsl:value-of select="$dvt_filtertype"/><br/>

    dvt_firstrow: <xsl:value-of select="$dvt_firstrow"/><br/>

    dvt_p2plinkfields: <xsl:value-of select="$dvt_p2plinkfields"/><br/>

    dvt_nextpagedata: <xsl:value-of select="$dvt_nextpagedata"/><br/>

    dvt_grouptype: <xsl:value-of select="$dvt_grouptype"/><br/>

    dvt_sorttype: <xsl:value-of select="$dvt_sorttype"/><br/>

    dvt_groupsorttype: <xsl:value-of select="$dvt_groupsorttype"/><br/>

    dvt_apos: <xsl:value-of select="$dvt_apos"/><br/>

    filterParam: <xsl:value-of select="$filterParam"/><br/>

    ImagesPath: <xsl:value-of select="$ImagesPath"/><br/>

    ListUrlDir: <xsl:value-of select="$ListUrlDir"/><br/>

    EMail: <xsl:value-of select="$EMail"/><br/>

    ListUrlDir_TRUE: <xsl:value-of select="$ListUrlDir_TRUE"/><br/>

    URL_DISPLAY: <xsl:value-of select="$URL_DISPLAY"/><br/>

    URL_EDIT: <xsl:value-of select="$URL_EDIT"/><br/>

    URL_New: <xsl:value-of select="$URL_New"/><br/>

    WebQueryInfo: <xsl:value-of select="$WebQueryInfo"/><br/>

    URL_Edit: <xsl:value-of select="$URL_Edit"/><br/>

    URL_Lookup: <xsl:value-of select="$URL_Lookup"/><br/>

    <!-- Dump parameters -->

     

    The ddwrt namespace, a reference

    And now we come to the meat of this article. A reference guide to the set of functions implemented in the ddwrt namespace. Have a look at the XSLT code generated by FrontPage, and you know what I’m talking about: those functions starting with ddwrt:.

     

    What follows is an overview of all public functions in the internal class DdwRuntime that is automatically available in the XSLT code in a DVWP.

     

    public DdwRuntime();

    Nothing really interesting is happening here, and you don’t call the constructor yourself. This function is automatically called on instantiating the DdwRuntime class as an XSLT Extesion Object. Don’t bother about it.

     

    public string AutoHyperLink(string szStr, bool preserveWhitespace);

    This function returns the passed szStr string parameter. The preserveWhiteSpace parameter is ignored.

     

    public string AutoNewLine(string szStr);

    This function goes through the string szStr and does the following replacements:

    From

    To

    &

    &amp;

    \

    &#39;

    < 

    &lt;

    > 

    &gt;

    \n

    <br/>

    <space>

    If not the first space in a row, translated to &nbsp;

    So: “a b” à “a b”, but “a  b” -> “a &nbsp;b”

    &quot;

    \x00a0

    &nbsp;

    So the function converts a plain text string containing special characters (in the HTML sense) and newlines to a string that can be inserted into HTML and remains formatted in the same way.

     

    public string ConnEncode(string szData);

    This function goes through the string szData and does the following replacements:

    From

    To

    #

    &23

    &

    &26

    &27

    *

    &2A

    ;

    &3B

    \

    &5C

    So the function converts a string to a format that can be passed as a parameter in the URL string. If you look at the name of the function, this function is used to encode the connection information that is communicated between connected web parts. Web part connection information is probably encoded because connection information between web parts on separate web part pages are passed on the URL. Creating web part connections between web parts on different web part pages is not available through the web interface for defining web part connections, but FrontPage 2003 does provide functionality to make web part connections between web parts on different pages.

     

    public string Counter();

    The Counter() function returns an incremental number. The number even increases over pages refreshes so you are ensured of a new number on each call, even over page requests.

     

    public string FieldFilterImageUrl(string szFieldName);

    If the parameter szFieldName equals the name of the currently selected filter field (assumable the internal name of the field), this function returns the text /_layouts/images/filter.gif , otherwise it returns the text /_layouts/images/blank.gif.

     

    public string FieldFilterOptions(string szName);
    This function always returns an empty string.

     

    public string FieldPrefix();

    This function always returns the text urn:schemas-microsoft-com:office:office#, this is the namespace used for all fields defined in for example a SharePoint list.

     

    public string FieldSortImageUrl(string szName);

    If the parameter szName equals Desc,  the text /_layouts/images/rsort.gif is returned, otherwise the text /_layouts/images/sort.gif is returned,

     

    public string FieldSortParameters(string szName);

    This function always returns an empty string.

     

    public string FilterLink();

    This function always returns an empty string.

     

    public string FormatDate(string szDate, long lcid, long formatFlag);

    The parameter szDate is converted to a DateTime. Based on the formatFlag parameter which can have a value from 0..15, a new DateTime string is constructed in the given locale lcid. This result is returned by the function.

    Flag

    Formatting string

    Result

    1 (0001)

    “d”

     todo, see standard .net docs

    3 (0011)

    “D”

     todo, see standard .net docs

    4 (0100)

    “t”

     todo, see standard .net docs

    5 (0101)

    “g”

     todo, see standard .net docs

    7 (0111)

    “f”

     todo, see standard .net docs

    12 (1100)

    “T”

     todo, see standard .net docs

    13 (1101)

    “G”

     todo, see standard .net docs

    15 (1111)

    “F”

     todo, see standard .net docs

     

    public string FormatDateTime(string szDate, long lcid, string szFormat);

    The parameter szDate is converted to a DateTime. Based on the szFormat parameter which is a standard DateTime formatting flag, a new DateTime string is constructed in the given locale lcid using GetDateTime(szDate).ToString(szFormat, lcid).

     

    public string GenDisplayName(string szValue);

    The parameter szValue is converted to a DateTime, and returned in the format “d” using GetDateTime(szValue).ToString(“d”, CultureInfo.InvariantCulture). If the conversion to a DateTime fails, the value of the szValue parameter itself is returned.

     

    public string GenFireConnection(string szConnectStr, string szOtherPostback);

    Fire a connected web part event with a call to __dopostback(), which is the function called in ASP.NET to do a post back to the server. This function uses the GenFireServerEvent() function to do the actual firing of the event. The following event text is “fired”: __connect={szConnectStr};szOtherPostback. See http://www.kbalertz.com/kb_838685.aspx for an example of firing a connection event from XSLT code.

     

    public string GenFireServerEvent(string szEventStr);

    Fire a server event with a call to __dopostback()(), which is the function called in ASP.NET to do a post back to the server. The szEventStr is the actual event text to “fire”.

     

    protected DateTime GetDateTime(string szDate);

    This function returns DateTime.Parse(szDate).ToUniversalTime().ToLocalTime().

    The current coordinated universal time (UTC) is converted to local time, adjusting to the local time zone and daylight saving time.

     

    public string GetFileExtension(string szUrl);

    This function returns the file extension of the give URL parameter szUrl.

     

    public static string GetStringBeforeSeparator(string szval);

    Given the string parameter szval, this function returns the part before the first “;” or “#” character. So for example for the string “abaca;dabra”, the string “abaca” is returned.

     

    public string GetVar(string szName);

    There is a name-value collection available in the called Vars. This function retrieves the value for the entry with the name szName from the collection.

     

    public bool IfNew(string szCreatedTime);

    This function returns true if the parameter szCreatedTime is “younger” than 2 days, otherwise false is returned.

     

    public bool IsPrivilegedUser();

    This function returns true if the current user doing the page request is a privileged user (administrator) in the current web, and false if the user is not an administrator. False is returned if the page request is not in the context of a SharePoint web. This function returns the result of a call to SPWeb.IsPriviledgedUser on the current web.

     

    public string Limit(string szInputText, int len, string szMoreText);

    Given the string parameter szInputString, this function returns the first len characters, with the string szMoreText appended. Note: This function makes a mess of HTML strings, because the string is just cut off, without taking HTML formatting tags into account.

     

    public string ListProperty(string szPropName);

    This function returns the value of the given property szPropName when the page request is in the context of a list. There are some special properties defined that don’t really have to map to properties directly available on the list.

    Field name

    Information

     title

    The displayed title for the list.

     description

    The description for the list.

     direction

    Direction of the reading order for the list. This property contains the string ltr if the reading order is left-to-right,  rtl if the reading order is right-to-left, or it contains none.

     basetype

    Number with the base type of the list. Dive into list templates for more information on this topic. SharePoint contains the following base types:

    Name

    Description

    DiscussionBoard

    Discussion board.

    DocumentLibrary

    Document library.

    GenericList

    Generic type of list template used for most lists.

    Issue

    Issue-tracking list.

    Survey

    Survey list.

    UnspecifiedBaseType

    No base type specified.

    Unused

    Unused.

     servertemplate

    String with the name of the template the list is based on.

     defaultviewurl

    Url of the page providing the default view for the list.

     url

    Url of the list.

     rootfolderurl

    Url of the root folder of the list. The rootfolder is the folder that contains all the files used in working with the list. In most cases this is the Forms folder.

     version

    The version number of the list.

     name

    The internal name of the list.

    moderatedlist

    “1” if content approval is enabled, “0” if content approval is disabled.

    attachmentsdisabled

    “1”if attachements can be added to items in the list, “0”if attachements can not be added to items in the list.

    multiplemtgdatalist

    “1” if the list in a Meeting Workspace site can contain data for multiple meeting instances within the site, “0”if not.

    templateurl

    Url of the template document used to create a new document in a document library.

    webimagewidth

    If a picture library, the webimagewidth is the width value used to display images in a picture library (in pixels), otherwise an empty string.

    webimageheight

    If a picture library, the webimageheight is the height value used to display images in a picture library (in pixels), otherwise an empty string.

    thumbnailsize

    If a picture library, the thumbnailsize is the size in pixels of the height or width, whichever is longest, to use for thumbnails in the picture library, otherwise an empty string.

    itemcount

    Number of items in the list. Note that the value of the itemcount does not include folders in a document library but does include files within subfolders in a document library.

     

    public string MapToAll(string szProgID, string szExt);

    This function returns a concatenation of Icon|ProgID|Control, as defined in the “docicon.xml” file. If the specified parameter szProgID is not found in “docicon.xml”, the ProgID is determined by the extension specified in the szExt parameter. This function uses the function MapToControl() to determine the value of Control, and the function MapToIcon() to determine the value of Icon.

     

    public string MapToControl(string szProgID, string szExt);

    This function returns the value of Control for the given ProgID (szProgID) or extension (szExt). A Control is the control to open the document with, like SharePoint.OpenDocuments.

     

    public string MapToIcon(string szProgID, string szExt);

    This function returns the Icon for the for the given ProgID (szProgID) or extension (szExt). The Icon is the name of the gif file, without the complete path to the file.

     

    public string NameChanged(string szName, long id);

    I have no idea. Something happens with NameChangedCounters…

     

    public string PresenceEnabled();

    This function returns “true”/“false” if the current page request is in the context of a SharePoint web, and there is presence enabled/disabled for the web. If the current page request is not in the context of a SharePoint web, an empty string is returned.

     

    public string SelectOptions(string szName);

    Returns an empty string.

    public string SetVar(string szName, string szValue);

    There is a name-value collection available called Vars. This function sets the value szValue for the name szName in the collection.

     

    public string ThreadStamp();

    This function returns the current time (Now) in the format: yyyyMMddHHmmss

     

    public string Today();

    This function returns DateTime.Now.ToString("G", CultureInfo.InvariantCulture);

     

    public string TodayIso();

    This function returns DateTime.Now.ToString("s", CultureInfo.InvariantCulture);

     

    public string UrlBaseName(string szUrl);

    This function returns the basename of the given url szUrl. So for example for: /a/b/basename.ext, the value basename is returned.

     

    public string UrlDirName(string szUrl);

    This function returns the directory name of the given url szUrl.So for example for: /a/b/basename.ext, the value /a/b/ is returned.

     

    public string UrlEncode(string szUrl);

    This function returns HttpUtility.UrlEncode(szUrl). The string parameter szUrl is encoded so it can be safely used on the url.

     

    public string URLLookup(string ListName, string FieldAttributeName, string FieldPosition);

    It is not completely clear to me what you can do with this function. Especially the possible values for the parameters FieldAttributeName and FieldPosition are a bit unclear. The thing that puzzles me is the name of the function: UrlLookup(). So it dies not lookup a value of a property in the list, it returns an Url. The only real usage I could find is for looking up information in the special SPWeb list UserInfo, which contains information about all users that ever visited the web, if the current page request is in the context of a SharePoint web. If this function is called with the parameter ListName set to UserInfo, the following url is returned:

    /_layouts/<LCID>/userdisp.aspx?Force=True&ID=<ID of user>. Note that the Force=True parameter forces the redirection to a a page that displays the information as stored in the UserInfo table, instead of redirection to the public MySite page of a user when available (only for SharePoint Portal Server). Remove the “Force=True&” string from the result string in case of a SharePoint Portal Server environment.

     

    public string UserLookup(string UserName, string FieldName);

    The Fieldname parameter can be either Email, ID, or Login. The UserName parameter is in the format as defined by FieldName. This function always returns the specified user in login format: DOMAIN\User.

    public string Ascending { get; }

    Gets the string “Asc”.

     

    public string BlankGif { get; }

    Gets the string images/blank.gif.

     

    public string DefaultUrl { get; }

    Accessing this property triggers the caching of the XML file docicon.xml. This file contains the mapping from file extension to icons, and to the progid of the application to open a file with a given file extension with. I don’t know what exactly is returned.

     

    public string Descending { get; }

    Gets the string Desc.

     

    public NameValueCollection ExtensionCtrlMap { get; }

    Get a NameValue collection as defined in the XML file mapicon.xml, needs further investigation.

     

    public NameValueCollection ExtensionMap { get; }

    Get a NameValue collection as defined in the XML file mapicon.xml, needs further investigation.

     

    public NameValueCollection ExtensionTextMap { get; }

    Get a NameValue collection as defined in the XML file mapicon.xml, needs further investigation.

     

    public string Filter { get; }

    Gets the string Filter.

     

    public string FilterGif { get; }

    Gets the string images/filter.gif.

     

    public string FormFieldDecoration { get; }

    Gets the string urn:schemas-microsoft-com:office:office#.

     

    public string FreeForm { get; }

    Gets the string FreeForm.

     

    public string GetGuid { get; }

    Gets a GUID using new Guid().ToString("D", CultureInfo.InvariantCulture).

     

    public string GetProgID { get; }

    Gets an empty string.

     

    public string ListParameter { get; }

    Gets the string ListParam.

    public string MapString { get; set; }

    Get the contents of the complete XML file docicon.xml as a string. This string is cached on first access. The Set functionality overrides the information read from docicon.xml.

     

    public NameValueCollection ProgIDCtrlMap { get; }

    Get a NameValue collection as defined in the XML file mapicon.xml, needs further investigation.

     

    public NameValueCollection ProgIDMap { get; }

    Get a NameValue collection as defined in the XML file mapicon.xml, needs further investigation.

     

    public NameValueCollection ProgIDTextMap { get; }

    Get a NameValue collection as defined in the XML file mapicon.xml, needs further investigation.

     

    public string RootFolder { get; }

    Gets the string RootFolder.

     

    public string RSortGif { get; }

    Gets the string images/rsort.gif.

     

    public string SearchString { get; }

    Gets the string SearchString.

     

    public string SortDir { get; }

    Gets the string SortDir.

     

    public string SortField { get; }

    Gets the string SortField.

     

    public string SortGif { get; }

    Gets the string images/sort.gif.

     

    public string ThreadStampFormat { get; }

    Gets the string yyyyMMddHHmmss.

     

    public NameValueCollection Vars { get; set; }

    The Vars name-value collection is filled with all kind of interesting information. See the section DataViewWebPart, Vars and the ddwrt namespace for more information. This collection is persisted over page request in the ASP.NET viewstate, so it can be used to persist information from the XSLT transformation of the current page request to the XSLT transformation of the next page request.

     

    public string View { get; }

    Gets the string View.

     

    public DataViewWebPart Wp { get; set; }

    Gets or set the DataViewWebPart object we are currently working on.

    public string WPQ { get; }

    Gets the string WPQ.

     

    Conclusion

    I only touched on a small part of the magic world of Data View web parts. A lot more information is there to explore to grasp the complete power of the possibilities of this web part.

     

    Although the possibilities of DVWPs is almost unlimited, be aware of the following downsides of using them:

     

    • You need an experienced XSLT coder to do more advanced modifications beyond the standard possibilities of FrontPage, and you end up there pretty soon!
    • DVWPs are difficult to reuse from one situation to another situation, because certain information is hard coded in the DVWP. This makes is hard to maintain modifications made to DVWPs over multiple instances of DVWPs.
    • It is difficult to deploy DVWPs due to the way certain information is hard coded in the DVWP

     

    One last point I wanted to mention is that it is not possible to create JScript code in your XSLT code, due to security reasons. So all extension code available in your XSLT must either come from standard XSLT code, or from the functions as described in this article.

    References

    Have a look at the following links for more information on Data View web parts:

     

    Working With the Data View Web Part: http://www.sharepointcustomization.com/resources/whitepapers/webpartdocs/dataview_wp.doc

     

    SharePoint: The power of the DataView Web Part

    http://msevents.microsoft.com/CUI/WebCastEventDetails.aspx? EventID=1032256050

     

    One of the guys from the Microsoft Team who does a lot of newsgroup work is John Janssen. Look him up in relation to DVWPs with the following queries:

     

     

  • SharePoint RunTimeFilter and audiences... an investigation

    In the web.config file of SharePoint Portal Server you find the line:

     

    <RuntimeFilter Assembly="Microsoft.SharePoint.Portal, Version=11.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" Class="Microsoft.SharePoint.Portal.Audience.AudienceManager" BuilderURL="audience_chooser.aspx" />

     

    I was wondering what this line was doing here, and what other things you can implement using RunTimeFilter configurations. Fired up Google… nothing. Fired up reflector, and after some disassembling I came to the following (possibly non-valid) conclusions:

     

    Microsoft.SharePoint.Portal.Audience.AudienceManager implements the interface Microsoft.SharePoint.WebPartPages.IRuntimeFilter.

     

    This is an interface in the Windows SharePoint Services namespace, so my assumption is that the runtime filter mechanism is also supported in WSS.

     

    The interface that must be implemented is:

     

    public interface IRuntimeFilter
    {
    // Methods
    [PermissionSet(SecurityAction.LinkDemand, Unrestricted=true)]
    bool CheckRuntimeRender(string IsIncludedFilter);
    [PermissionSet(SecurityAction.LinkDemand, Unrestricted=true)]
    ArrayList InitializeStrings(CultureInfo cultureInfo);
    [PermissionSet(SecurityAction.LinkDemand, Unrestricted=true)]
    bool IsFilterActive();
    [PermissionSet(SecurityAction.LinkDemand, Unrestricted=true)]
    string ValidateIsIncludedFilter(string persistedString);
    }

     

    What these methods exactly should do is not documented, so after some disassembling of Microsoft.SharePoint.Portal.Audience.AudienceManager:

    :

     

    public bool IsFilterActive()
    {
      if (PortalApplication.GetContext() == null)
      {
        return false;
      }
      return true;
    }

     

    So this filter is only active if there is a portal context, that means only for SharePoint Portal Server, not for WSS. Makes sense for audience manager because this functionality is only available on the portal.

     

    public bool CheckRuntimeRender(string isIncludedFilterOrg)
    {
    :

    }

     

    This method seams to do an intersection between the selected target audiences for a web part, and the list of audiences the current user is part of. This is probably done for each web part, because targeting to audiences can be applied per web part. This would mean that the RunTimeFilter mechanism is only there for web part filtering: is a web part displayed or not for the current user (anyone?). Intersection computation is done through the stored procedure DBO.Orgle_MatchOrgleList. If there is an intersection the web part is rendered.

     

    public string ValidateIsIncludedFilter(string PersistedString)
    {

    :
    }

     

    Not sure what happens here… I think the PersistedString parameter is the string returned by the selection of the audiences. Probably a concatenation of audience ID's. There is some translation going on to guid's returning a new comma separated string of guid's.

     

    public ArrayList InitializeStrings(CultureInfo ci)
    {
    :

     

    :

    }

    Looks like this function does some initial initialization of a string table based on a culture… which is ignored in the AudienceManager. Still not completely understand the complex way things are implemented in this function, but the result is that the texts to be used for the functionality for targeting (the "Target Audiences" section in the "Advanced" part of web part configuration) is retrieved. Strings like "Target Audiences" and "Select" (for on the button).

     

    The aspx page specified in the RunTimeFilter tag (BuilderURL="audience_chooser.aspx") is hooked up to the button for the selection of the audiences.

     

     

    If you look at the hooked up pages for audience selection in the current implementation, you see the following code:

     

    <%@ Page language="C#"

    Inherits="Microsoft.SharePoint.Portal.SitePage,Microsoft.SharePoint.Portal,Version=11.0.0.0,Culture=neutral,PublicKeyToken=71e9bce111e9429c" %>

    <%@ Register Tagprefix="SPSWC" Namespace="Microsoft.SharePoint.Portal.WebControls" Assembly="Microsoft.SharePoint.Portal, Version=11.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %> <%@ Register Tagprefix="SharePoint" Namespace="Microsoft.SharePoint.WebControls" Assembly="Microsoft.SharePoint, Version=11.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %>

     

    <html dir="ltr">

    <head>

    <SPSWC:PageHeadTags runat="server" TitleLocId="AudienceChooser_PageTitle_Text" OldExpires="0" PageContext="SiteAdminPage"/>

    <SPSWC:ExternalHtmlResourceElement runat="server" HtmlElement="Script" FileContext="SharedScript" FileName="audpicker.js" />

    </head>

    <body>

    <form runat="server" ID="AudienceChooser2" method="POST" action="Audience_Chooser2.aspx">

    <Sharepoint:FormDigest runat="server" id="FormDigest" />

    <SPSWC:PageLevelError id="AudiencePageLevelError" runat="server" />

    <SPSWC:AudiencePicker id="AudiencePicker" SupportRuntimeFilter="true" runat="server" />

    </form>

    </body>

    </html>

     

    With the actual real implementation in the server control

    <SPSWC:AudiencePicker id="AudiencePicker" SupportRuntimeFilter="true" runat="server" />, meaning the class: Microsoft.SharePoint.Portal.WebControls.AudiencePicker

     

     

    A simple test reveals that only one entry of RunTimeFilter is allowed in the web.config. This is a pity, it is not possible to implement your own web part display filtering on top of the existing one. If you really want to this can probably be easily done by implementing a new filter and call in this filter multiple other filters. On the other hand: if you want to change this, you probably want to change this completely.

     

    I never was really impressed by the way that audiences were implemented. Can be that I don't really understand the intended way of usage;-) Some of my problems with it are (incomplete list):

     

    • Audiences are precompiled, so not "real-time"
    • Audiences are rules based on profile properties (coming from active directory), often there is already a company directory available in large organizations, and replication of all the needed information to the profile is not always the way you want to go
    • Due to the the restricted possibilities in the audience definitions you can make I always end up with way to many audiences. For example: if you have an audience definition depending on the country and office you are in, you have to define country*office audiences, instead of targeting to a country, and/or an office

     

    On top of my head the only places audiences are used are in listings and in web part targeting. Web part targeting can be overruled by implementing your own RunTimeFilter. For listings and the targeting in here you probably need to reimplement all the portal web parts showing listings because you have to implement your own filtering on listings.

     

    How it works with listing I did not investigate yet. Maybe a topic for a next weblog entry!

     

    If anyone has more info on this stuff, please reply!!!

     

    Disclaimer: all made assumptions are speculative, based on disassembling and (I hope) some common sense.

  • SharePoint lists... did you know?!

    I use SharePoint a lot... as a developer. Ok, our intranet runs on SharePoint, and I know my way around as a user (I did build a large part of it) but most of the time I REALLYwork with SharePoint I'm diving in the object model, programming against it. A few days ago I was scoring use-cases together with collegue developers for a huge SharePoint implementation for a customer. In those use-cases there was a description of some sorting functionality in a list that we thought would take a long time to implement. We called in the analist who wrote the use-case to blame him for writing way to difficult use-cases, and he looked at us as if we were really stupid. And he was right.

    As a developer you sometimes forget to look at the functionality that is available just out of the box. One of those things is the standard functionality that is available in the SharePoint lists. Most people knowledgable of SharePoint will think: what is your point? Didn't you know this? Why do you bother me with this: read the f*cking manual. For those other people who forgot to read the manual, I would like to enumerate some things about lists that are "out of the ordinary".

    Did you know that:

    • Lists based on the "Links" list have a "Change Order" option in the menu bar of it's views that allow you to reorder the list items
    • Lists based on "Tasks" and "Issues" have an "Assign to:" field that is a lookup to users in the UserInfo list for the web the list is on. This list contains all users that ever visited the list. What does this mean:
      • Users who did not visit the web yet are not in the list
      • Users who ever visited the web site, but whom's account is now removed is still in the list (Should be like this: task/issue can be assigned to user that is now gone, if you edit the task/issue to change something, the user shouls still be in the list, otherwise it must always be reassigned on edit.)
      • System accounts that crawl the list are in the list (we filter those out using the MacawSharePointSkinner)
    • Lists based on "Issues" have an option to sent the "Assigned To" person a notification e-mail (General Settintgs ->Email Notification) on changed item or when ownership is assigned.
    • Lists based on "Issues" have a "View reports" action with reports to track issue trends
    • Lists based on "Contacts" have "Export Contact" functionality in the menu of an entry that created a vcard file
    • Lists based on "Contacts" can "link to Outlook", this creates a read-only contacts list in outlook, with in each item a link to update the contact. This list in outlook stays up to date automatically
    • Lists based on "Contacts" can import contacts from the address book
    • Lists based on "Events" can "link to Outlook", this creates a read-only calendar in outlook, with in each item a link to update the event. This list in outlook stays up to date automatically
    • Lists based on "Discussion" support threading on items, and that this list sucks for discussions (in my opinion). We rewrote the new/edit/view pages to se things like the thread you are replying on, the complete thread of a single discussion item, see the newest discussion thread first. This makes it usable.
    • List items can have multiple files attached
    • There are no events available on lists, only on libraries. When I asked Mike Fitzmaurice about this on the PDC 2003 he answered that it was due to lack of time. There was a big launching customer who needed events on libraries, so this was implemented.

    All this functionality is somewhere available in the list definitions, so if you define your own template you can combine all this functionality!!

    Maybe I will write some more on the libraries (Forms/Documents/Pictures) in the future. Who knows...

    Are there any other hidden gems out there that is good to know about... let me know in a response on this post.

  • WSS logging level

    A few weeks ago I had a problem with WSS. Really strange things happened, but nothing was written to the eventlog. After some searching I found the logging file written by WSS, but the amount of information logged is really minimal. SPS has much more extensive logging, see manual, but WSS specific things are even on an SPS server logged to the WSS logging mechanism.

    After some searching I found on http://wss.sharepointtips.com/pages/III%20-%20Administration.aspx on Q: 04 the following text:

    "STS 1.0 had logging to C:\WINNT\system32\LogFiles\W3SVC1 (and W3SVC2, W3SVC3 etc.)

    WSS has (RTM) a configurable registry key that you can set to control how verbose the logging is.
     
    Critical events will be logged to the application log in the event viewer.
     
    The stsadm.exe comman line utility uses a log file called stsadm.log which is stored in the temp directory of the person running this utility.
     
    The log for the w3wp process (w3wp.log) is stored in the windows temp directory."
     
    As stated in this text, the logfile can be found in c:\windows\temp\w3wpMSSharePointPortalAppPool.log (in my case). This name depends on name of the identity pool your SharePoint site is running under.
     
    Especially the sentence "WSS has (RTM) a configurable registry key that you can set to control how verbose the logging is." puzzeled me. We opened a call to Microsoft Support or more information on this and got back the following answer:
     
    Location to change the LogLevel
    HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Shared Tools\Web Server Extensions\6.0
    Change the LogLevel to Value Data of 9

    The Loglevel is by default set to 0. If you look in this container you also find the key MaxLogSizeKB. I assume this specifies the maximum log file size, don't know what happens if this size is reached.

    More logging is available after setting this registry key, not overwhelming, but more than it was before! Strange those kind of things are not just documented....

     

  • NAnt: concatenate filenames

    I'm currently constructing some NAnt build scripts for our continuous integration build environment for SharePoint development. One thing  I want to do is that on the development server is that I want to install compiled web part assemblies and their references assemblies using the InstallAssemblies tool. This tool has in the command line version the option to install a set of assemblies using the "assembly:x,y,z" parameter. This parameter needs to have the assembly files separated by ','. I concatenate those filenames using the following code:

    <project name="concat.test" default="concat.filenames" basedir=".">
     <target name="concat.filenames" description="concatenate filenames">
      <property name="concatenated.filenames" value=""/>
      <foreach item="File" property="filename">
       <in>
        <items>
         <include name="files\*.*" />
        </items>
       </in>
       <do>
        <property name="concatenated.filenames" value="${concatenated.filenames}${filename},"/>
       </do>
       <!-- now remove the trailing ',' -->
      </foreach>
      <property name="concatenated.filenames" value="${string::substring(concatenated.filenames, 0, string::get-length(concatenated.filenames) - 1)}"/>
      <echo message="${concatenated.filenames}"/>
     </target>
    </project>

    Result: [echo] C:\projects\NantTest\files\file1.txt,C:\projects\NantTest\files\file2.txt,C:\projects\NantTest\files\file3.txt