Tuesday, June 20, 2006

Best Practices: Using Disposable Windows SharePoint Services Objects


Scott Harris and Mike Ammerlaan have published a technical article entitled Using Disposable Windows SharePoint Services Objects. All SharePoint developers should consider this MSDN article a must read. Specifically, Scott and Mike are informing us that failing to explicity dispose of certain SharePoint Services objects can result in problematic server behaviors such as:


  • Frequent recycles of the Microsoft Windows SharePoint Services application pool, especially during peak usage
  • Application crashes that appear as heap corruption in the debugger
  • High memory use for Microsoft Internet Information Services (IIS) worker processes
  • Poor system and application performance

  • Several of the SharePoint Services objects use unmanaged code and memory to do the majority of their work. As such, classes like SPSite and SPWeb do not release from memory in a timely manner. Developers should explicity dispose of IDisposable objects such asSPSite and SPWeb when their applications finish using them. Moreover, developers cannot rely on the garbage collector to release them from memory automatically.


    The 22 page MSDN technical article provides background on why it is necesarry to explicitly dispose of those objects which implement the IDisposable interface and further serves as an authoritative guide to the proper procedures for handling and disposing of SharePoint Services objects. Several techiques and best practice examples are given.




    Monday, May 15, 2006

    RSS Feed Monitor for Microsoft Office SharePoint Server 2007 Beta Released


    RSS Feed Monitor 2007

    Use Feed Monitor 2007 to aggregate content from one or more RSS-enabled Lists in Microsoft Office SharePoint Server 2007.

    Register to download RSS Feed Monitor for Microsoft Office SharePoint Server 2007 Beta

    Screen Shots

    (Click for Larger View)

    RSS Feed Monitor: Aggregated Blogs and Styled Constellations

    • Aggregate RSS List Feeds from across Microsoft Office SharePoint SharePoint Server 2007 Sites

    RSS Feed Monitor: Choose one or more lists to aggregate

    • Convenient List browser for configuring RSS Feeds to be aggregated

    RSS Feed Monitor: Fine-grained control over element styles using CSS

    • Fine-grained control over element styles via with CSS

    Thursday, April 13, 2006

    Programmatically generate/update data for an InfoPath Form and save it in a SharePoint Form Library


    Here's a message that a SharePoint Solutions student sent to me regarding how to programmatically generate/update data for an InfoPath form and save it in a SharePoint Form Library. Thanks David!

    Hi Tony,

    Here is the snippet for one technique to parse an InfoPath form stored in a form library. Before using this code I created a form library with the form template containing around 20 text fields. I also created an empty form in the form library based on this template (BLANK.xml). This example opens an empty form (BLANK.xml) from the form library, reads it into an xml document, parses the xml document to update the fields, and then saves the xml document as a new file back to the form library.

    // opens the site
    SPWeb webSite = new SPSite(txtUrl.Text).OpenWeb();

    // gets the blank file to copy
    SPFile BLANK = webSite.Folders["Test1"].Files["BLANK.xml"];

    // reads the blank file into an xml document
    MemoryStream inStream = new MemoryStream(BLANK.OpenBinary());
    XmlTextReader reader = new XmlTextReader(inStream);
    XmlDocument xd = new XmlDocument();
    xd.Load(reader);
    reader.Close();
    inStream.Close();

    //gets the root element from the xml document
    XmlElement root = xd.DocumentElement;

    //the loop counter is started at 2 to skip past the namespace tags and start at the data fields
    for(int index=2; index<root.ChildNodes.Count; index++)
    {
    //insert code to parse the xml to update the fields
    }


    // saves the XML Document back as a file
    System.Text.ASCIIEncoding encoding=new System.Text.ASCIIEncoding();
    SPFile newFile = webSite.Folders["Test1"].Files.Add("Test_Document.xml", (encoding.GetBytes(xd.OuterXml)), true);

    XPath queries could also be used to find and update fields in the xml instead of or in addition to looping through the nodes of the xml document. Another alternative to this would be to use the myschema.xsd from the .xsn file and load a strongly typed dataset based on that schema with the xml, update the fields in the dataset, then write the dataset to xml and appending the proper header tags at the top xml to include the InfoPath namespace information. This could also be slightly modified to open an existing form in a SharePoint form library, update the data elements, and save it back to the form library.


    David Pearson
    Programmer Analyst Intranet Solutions
    HNI Corporation

    Sunday, February 26, 2006

    Tasks For You Web Part for SharePoint Portal Server Released


    Tasks For You Web Part

    Do you need to publish Tasks from SPS and/or WSS Task Lists to SharePoint Portal Server Audiences?


    The ability to target content to Audiences in SharePoint Portal Server 2003 is one of the hallmark features of the product. Unfortunately, out-of-the-box, only Portal Listings can be targeted to specific Audiences (in conjunction with the Grouped Listings web part). Now, with the Tasks for You web part from SharePoint Solutions, you can target any Task from any Task List, whether in SPS or WSS, to any Audience!

    Advanced features include the ability to include/exclude specific Audiences from being displayed by the web part.



    14 Day TrialIf you'd like to download a fully-functional TrialWare version of the Tasks For You Web part for evaluation on your own servers, please visit the Product Downloads page.


    Wednesday, February 22, 2006

    Announcements For You, Documents For You Web Parts for SharePoint Portal Server Released


    Documents For You Web Part

    Do you need to publish documents from SPS and/or WSS Document Libraries to SharePoint Portal Server Audiences?


    The ability to target content to Audiences in SharePoint Portal Server 2003 is one of the hallmark features of the product. Unfortunately, out-of-the-box, only Portal Listings can be targeted to specific Audiences (in conjunction with the Grouped Listings web part). Now, with the Documents for You web part from SharePoint Solutions, you can target any document from any document library, whether in SPS or WSS, to any Audience!

    Advanced features include the ability to include/exclude specific Audiences from being displayed by the web part.

    14 Day TrialIf you'd like to download a fully-functional TrialWare version of the Documents For You Web part for evaluation on your own servers, please visit the Product Downloads page.





    Announcements For You Web Part

    Do you need to publish Announcements from SPS and/or WSS Announcement Lists to SharePoint Portal Server Audiences?


    The ability to target content to Audiences in SharePoint Portal Server 2003 is one of the hallmark features of the product. Unfortunately, out-of-the-box, only Portal Listings can be targeted to specific Audiences (in conjunction with the Grouped Listings web part). Now, with the Announcements for You web part from SharePoint Solutions, you can target any Announcement from any Announcement List, whether in SPS or WSS, to any Audience!

    Advanced features include the ability to include/exclude specific Audiences from being displayed by the web part.

    14 Day TrialIf you'd like to download a fully-functional TrialWare version of the Announcements For You Web part for evaluation on your own servers, please visit the Product Downloads page.

    Sunday, February 12, 2006

    Free SharePoint Portal Server Web Part: Events for You


    The Events for You Web Part functions in a manner very similar to the Links for You Web Part that can be found on the Home Page and Personal MySite page of SharePoint Portal Server. With this free Web Part, Event Items from the Events List located in the portal’s root web are presented to portal users based on their Audience membership. The Events for You Web Part can also be configured to override a user’s Audience membership, targeting Events to a definable set of one or more Audiences. In order to function properly, the Events for You Web Part requires that the Events List located in the portal’s root web be customized with the addition of an “Single line of text” type column named Audience. The Audience column can contain a semicolon delimitted list of Audiences for targeting that particular Event Item. The Events for You Web Part also requires that the Events List has the “Current Events” view.

    Here’s a screenshot of Events For You in action:

    E4U ShowOff

    Setup Instructions

    Follow these steps to setup your portal’s Events List for use with the Events for You Web Part:

    Modify Events ListModify Settings and ColumnsAdd new column
    1. Modify Events List2. Modify Settings and Columns3. Add a New Column
    Single Line of Text Type ColumnPopulate Audience Column Values
    4. Single Line of Text Column Type5. Poplulate Audience Values

    Customizing Behavior

    Once you have the Events list setup and populated with data, you can customize how the Events for You Web Part behaves:

    Modify Shared Web PartDeselect 'Use default user audiences'Target Specific Audiences
    1. Modify Shared Web Part2. Deselect ‘Use default user audiences’3. Target Specific Audiences

    Technical Perspective: A few highlights

    The Events for You Web Part makes use of the SPQuery object and CAML to query the Events list.

    SPQuery query = null;
    string caml = string.Empty;
    SPListItemCollection results = null;

    // CAML uses ISO8601 date format: yyyy-mm-ddThh:mm:ssZ
    string todaysDate = SPUtility.CreateISO8601DateTimeFromSystemDateTime(DateTime.Today).ToString();

    try
    {
    query = new SPQuery(events.Views["Current Events"]);

    // Build the CAML Query to get all Events which belong to the current Audience (a)
    // and have start date of today or in the future
    // Apparently there is a problem with using CAML to get recurring events, so they're not supported.
    // More info about DateRangesOverlap element at
    http://wss.collutions.com/Lists/FAQ/DispForm.aspx?ID=320
    caml = string.Format("<Where><And><Contains><FieldRef Name='Audience'/><Value Type='Text'>{0}</Value></Contains>"
    + "<And><Geq><FieldRef Name='EventDate' /><Value Type='DateTime'>{1}</Value></Geq><DateRangesOverlap>"
    + "<FieldRef Name='EventDate'></FieldRef><FieldRef Name='EndDate'></FieldRef><FieldRef Name='RecurrenceID'>"
    + "</FieldRef><Value Type='DateTime'><Month/></Value></DateRangesOverlap></And></And></Where><OrderBy><FieldRef Name='EventDate'/></OrderBy>",

    audienceName, todaysDate);
    query.Query = caml;
    results = events.GetItems(query);

    // If the results collection contains items, we have some hits
    if(results.Count > 0)
    hasEvents = true;
    }
    catch(ArgumentException ex)
    {
    // 'Current Events' View doesn't exist
    _messages.Text += "<p>This portal's 'Events' List must have a 'Current Events' View defined in order for this web part to function properly.</p>";
    _hasHandledErrors = true;
    break;
    }
    catch(NullReferenceException ex)
    {
    // No items in results collection
    _hasHandledErrors = true;
    break;
    }
    catch(Microsoft.SharePoint.SPException ex)
    {
    // 'Audiences' column not defined
    _messages.Text += "<p>This portal's 'Events' List must have a 'Single line of text' type Column named 'Audience' defined in order for this web part to function properly.</p>";
    _hasHandledErrors = true;
    break;
    }

    The AudienceManager object is used to determine Audiences for the current user:

    // Returns an array of audience names for the current portal user
    public static string[] GetUserAudiencesNamesArray(string url)
    {
    // Get the portal context
    SPSite portal = new SPSite(url);
    PortalContext context = PortalApplication.GetContext(portal.ID);

    // Get the list of audiences for the user
    AudienceManager manager = new AudienceManager(context);
    string[] names = new string[manager.GetUserAudienceIDs().Count];
    IEnumerator enumer = manager.GetUserAudienceIDs().GetEnumerator();
    int i = 0;
    while(enumer.MoveNext())
    {
    AudienceNameID temp = (AudienceNameID)enumer.Current;
    names[i] = temp.AudienceName;
    i++;
    }
    return names;
    }

    The MSOPGrid_doBuilder() JavaScript function located in ows.js is used to launched the Audience Chooser Custom Property Builder:

    private void RegisterJavaScripts()
    {
    try
    {
    // Client-side code to apply changes
    string applyFunction = "ApplyProperties" + _qualifier;
    string EmbeddedScriptFormat = "<script language=jscript>function " + applyFunction + "(){\n";
    EmbeddedScriptFormat += "document.forms[MSOWebPartPageFormName].MSOTlPn_Button.value = 'apply';\n";
    EmbeddedScriptFormat += "document.forms[MSOWebPartPageFormName].elements['" + _shortId + ":MSOTlPn_AppBtn'].click();\n";
    EmbeddedScriptFormat += "}\n";
    EmbeddedScriptFormat += "</script>\n";
    if(!Page.IsClientScriptBlockRegistered(applyFunction))
    Page.RegisterClientScriptBlock(applyFunction, EmbeddedScriptFormat);
    // Client-side button click handler
    string onClick = "MSOPGrid_doBuilder('"
    + "_layouts/1033/Audience_Chooser.aspx" + "', " + "EventsForYou" + _qualifier
    + ", '" + "dialogHeight:510px;dialogWidth:560px;help:no;status:no;resizable:yes" + "');";
    onClick += applyFunction + "();";
    _button.Attributes.Add("OnClick", onClick);
    // Client-side checkbox click handler
    _chkDefaults.Attributes.Add("OnClick", applyFunction + "()");
    }
    catch (Exception ex)
    {
    System.Diagnostics.Trace.WriteLine(string.Format("{0} {1} {2}",ex.GetType().ToString(), ex.Message, ex.StackTrace), "ERROR");
    }
    }

    The source code and binaries for the Events for You Web Parts are released to public domain. Download source and binaries from the links below.

    EventsForYou-1.0.0.0.zip

    EventsForYou-1.0.0.0–Source.zip

    Leveraging Custom Property Builders in SharePoint Web Parts


    A few months ago, I posted an article about decorating your custom SharePoint web part's properties with the HtmlDesignerAttribute to provide users with a richer, more functional interface for setting custom web part properties. These specialized user interfaces for setting web part properties are called Custom Property Builders.

    While it is possible to create your own Custom Property Builders, there are several Custom Property Builders provided with SharePoint out-of-the-box. In this article, I'll take a few moments to expand on a few of the Custom Property Builders that come with SharePoint, and review how to leverage these Custom Property Builders in your own Web Parts.

    To begin with, here's a table with some (not all!) of the Custom Property Builders that are installed with SharePoint. A few are specific to SharePoint Portal Server, and others come with Windows SharePoint Services.

    LocationFunction
    _layouts/1033/Audience_Chooser.aspx Audiences Picker
    _layouts/1033/CategoryPickerPopUp.aspxAreas Picker
    _layouts/1033/PickerContainer.aspxSelect Users, Distribution Lists, and Security Groups
    _layouts/1033/zoombldr.aspxBasic Text Editor

    One of the simplest Custom Property Builders to use is zoombuilder.aspx, which provides a basic text editor for setting a string-based web part custom property.

    _layouts/1033/zoombldr.aspx

    Communication with the Custom Property Builder from you web part's code is done through a hidden form field. This hidden form field is used to pass data into and receive output back from the Custom Property Builder. Place the code to create this hidden form field in the overridden OnPreRender() method of the Tool Part.

    protected override void OnPreRender(EventArgs e)
    {
    base.OnPreRender(e);
    if(Page != null)
    {
    // Get the calling Web Part's Instance
    WebPart1 wp = new WebPart1();
    wp = (WebPart1)this.ParentToolPane.SelectedWebPart;
    // Get the value for the custom web part property
    string parameters = wp.Text;
    // Create a unique identifier for the hidden form field
    string uniqueId = "MyCustomProperty" + this.UniqueID.Replace(":","_");
    // Place hidden form field on the page
    Page.RegisterHiddenField(uniqueId, parameters);
    }
    }

    You’ll want to have the property value change take effect as soon as the Customer Property Builder is closed. To do this, you’ll need to programmatically “click the Apply button”. Here’s the JavaScript function to click the Apply button, which should also be placed in the Tool Part’s overridden OnPreRender() method.

    string shortId = this.UniqueID.Substring(0,this.UniqueID.IndexOf(":"));
    string EmbeddedScriptFormat = "<script language=jscript>function ApplyProperties(){\n";
    EmbeddedScriptFormat += "document.forms[MSOWebPartPageFormName].MSOTlPn_Button.value = 'apply';\n";
    EmbeddedScriptFormat += "document.forms[MSOWebPartPageFormName].elements['" + shortId + ":MSOTlPn_AppBtn'].click();\n";
    EmbeddedScriptFormat += "}\n";
    EmbeddedScriptFormat += "</script>\n";
    if(!Page.IsClientScriptBlockRegistered(“applyFunction”))
    Page.RegisterClientScriptBlock(“applyFunction”, EmbeddedScriptFormat);

    Now, to Apply the return value of the Custom Property Builder to your web part property, place the necessary code in the Tool Part's overridden ApplyChanges() method. The ApplyChanges() method will be called after you programmatically “click the Apply Button”.

    public override void ApplyChanges()
    {
    // Get the calling Web Part's Instance
    WebPart1 wp = new WebPart1();
    wp = (WebPart1)this.ParentToolPane.SelectedWebPart;
    // Create a unique identifier for the hidden form field
    string uniqueId = "MyCustomProperty" + this.UniqueID.Replace(":","_");
    // Set the web part property with the value from the hidden field
    wp.Text = this.Context.Request.Params[uniqueId];
    }

    Launching the Custom Property builder from your custom Web Part's Tool Part is done through JavaScript. SharePoint provides a JavaScript Method for doing this called MSOPGrid_doBuilder(). For your reference MSOPGrid_doBuilder() is located in the ows.js file. MSOPGrid_doBuilder() takes as parameters the path to a Custom Property Builder's location, the Element ID for the hidden form field, and some details on how to the display the Custom Property builder's dialog window. You'll want to call MSOPGrid_doBuilder() from the OnClick event of an element in the Tool Part. This snippet is from the CreateChildControls() method of a Tool Part.

    string designerUrl = "_layouts/1033/zoombldr.aspx";
    string designerProperties = "dialogHeight:510px;dialogWidth:560px;help:no;status:no;resizable:yes";
    string uniqueId = "MyCustomProperty" + this.UniqueID.Replace(":","_");
    Label lbl = new Label();
    // Client-side button click handler
    string onClick = "MSOPGrid_doBuilder('" + designerUrl + "', " + uniqueId + ", '" + designerProperties + "');ApplyProperties();";
    lbl.Attributes.Add("OnClick", onClick);

    That's about it for handling how to launch a Custom Property Builder and passing data to/from your web part. The zoombldr.aspx is about the simplest Custom Property Builder, using just an regular text string for input and output. Other Customer Property Builder will use comma delimited strings of data for input/output. For example, Audience_Chooser.aspx takes and returns a list of Audience GUIDs e.g. 'E76ADC57-C430-4464-AFA0-028A625D5C2D','332F0A00-55ED-4ae3-BCE3-9B465B675E6F','53C26C1D-4422-4625-BA94-6DCB63F4800E'.

    With a bit of reverse engineering you can figure out how to use each of the Custom Property Builders. As further reading, here's a post from SharePoint MVP Gary Bushey that covers using the PickerContainer.aspx Custom Property Builder to select Users, Distribution Groups, and Security Groups from AD.

    To wrap up, here are some screenshots for a few of the Custom Property Builders installed with SharePoint:

    _layouts/1033/Audience_Chooser.aspx

    _layouts/1033/PickerContainer.aspx

    _layouts/1033/CategoryPickerPopUp.aspx

    Thursday, February 09, 2006

    Feed Monitor Beta 2 Now Available


    SharePoint Solutions is happy to announce the release of Feed Monitor Beta 2 for public testing.

    New in the Beta 2 release:

    • Improved support for retrieving content feeds through HTTP proxies and behind corporate firewalls.
    • Improved error handling and error reporting.
    • Lots of minor bugfixes.

    SharePoint Solutions' Feed Monitor provide an easy to use, high performance, highly configurable, dynamic experience for consuming syndicated content feeds in SharePoint. The Feed Monitor web part aggregates and presents content from Podcasts, video blogs, RSS, RDF and Atom syndication formats. In addition, the Feed Monitor web part provides a hierarchical catalog of content feed channels based on the OPML specification.

    For some screenshots of the Feed Monitor web part, see our blog.

    To explore the dynamic, rich user experience provided by SharePoint Solutions’ Feed Monitor web part, visit our public Feed Monitor demonstration sites.

    To participate in the public Beta of SharePoint Solutions’ Feed Monitor web part, visit the Feed Monitor Beta Program page for further information.

    Friday, January 27, 2006

    New Advisor Article on Creating List Rollups without Code


    I have a new article in this month's Advisor Guide to Microsoft SharePoint on how you can use Access 2003 and the Data View Web Part to display rollups of SharePoint Lists.

    Currently, the article is only available in the print version of the magazine, however they usually make the articles available online to subscribers after a month or so. Advisor Guide to Microsoft SharePoint is currently the only print magazine devoted solely to SharePoint Products and Technologies.

    Also, I will mention that I will be speaking at the 2nd-ever Advisor Summit on Microsoft SharePoint in Las Vegas on April 9 -13, 2006. I spoke at the inaugural event last year.

    At the April conference I will be speaking on the following topics:

    1. Creating Dashboards with Office 2003 Web Parts and Components
    2. De-mystifying SharePoint Portal Taxonomy Design

    If it is on par with last year's event, there will be lots of expert information shared and the venue is fantastic. Plan now to attend!

    Sunday, January 01, 2006

    Feed Monitor Web Part Beta 1


    SharePoint Solutions' has released our new Feed Monitor web part for public Beta testing. In creating the Feed Monitor web part, our design goals have been to provide an easy to use, high performance, highly configurable, dynamic experience for consuming syndicated content feeds in SharePoint. The Feed Monitor web part aggregates and presents content from Podcasts, video blogs, RSS, RDF and Atom syndication formats. In addition, the Feed Monitor web part provides a hierarchical catalog of content feed channels based on the OPML specification.

    To explore the dynamic, rich user experience provided by SharePoint Solutions’ Feed Monitor web part, visit our public demonstration sites available at the links below:

    Business Demo Site
    Business_homeBusiness_stock

    ‘Business – Home’

    ‘Business – Stock Market’

    Sports Demo Site
    Sports_homeSports_mlb

    ‘Sports – Home’

    ‘Sports – MLB’

    Easy to Use

    The Feed Monitor configuration and settings interface makes it easy for end users to display content feeds. Users can select from a catalog of available content feed channels, or manually add feed sources of their own.

    Catalog_of_available_fefedsManage_feedsFeed_property_builder

    Highly Configurable

    In addition to allowing users to select which specific elements ( such as author, published date, copyright notice, etc. ) of a content feed will be displayed, Feed Monitor also allows CSS compliant inline styles to be applied to each element when the content is presented. With the optional inclusion/exclusion of content elements and the application CSS styles, customization possibilities are endless.

    Displayed_elements Content_style

    Proxy Support for Fetching Content from Behind Firewalls

    Manually configure proxy settings for scenarios where the SharePoint Server exists behind a firewall.

    Proxy_configuration

    Rich User Experience

    The Feed Monitor web part takes advantage of SharePoint’s asynchronous data fetching and web part caching technolgies to provide end users with a high performance, rich user experience. Users can set the caching duration manually.

    Performance

    To participate in the public Beta of SharePoint Solutions’ Feed Monitor web part, visit the Feed Monitor Beta Program page for further information.