Skip to main content

Mike Ammerlaan's Blog

Go Search
Mike Ammerlaan's Blog
  

About Me
I'm a program manager at Microsoft working on Windows SharePoint Services.  I focus on the developer platform, including features like ASP.NET integration, web parts, object model, events, site definitions and more.
This blog focuses on SharePoint and the SharePoint developer platform.
Back to blogging, and some samples

Been a while since I've blogged -- sorry about that!  Things have been busy around here, but I'll try to get back into the swing of things and post a bit more regularly.

Recently I was at TechEd and did a session on AJAX and SharePoint.  The samples for this session are here, and cover the basics of how to work with things like MS AJAX Extensions, UpdatePanels, Extenders, and script.  Sorry for the delay in getting this out.

At VSLive! 2007 In San Francisco on Tuesday
I'll be at VSLive! 2007 in San Francisco on Tuesday.
 
I'll be doing this session:
Extending Windows SharePoint Services 3.0 with Web Parts, Event Handling, and Workflow

Tuesday, March 27, 11:45 a.m. to 12:45 p.m.
(not sure what the room is, yet.)
Basically, I'll be talking about ways to extend SharePoint: the technologies you need to know to add new functionalities to existing things inside of SharePoint. 
 
If you're at VSLive! and interested in some of the best techniques for making your additions light up inside of SharePoint, please drop by!   I'll be looking to post slides and samples after the session.
The concept of a "Feature" in SharePoint
One of the major concepts in WSS3.0 is the "Feature".  The Feature is a container of various defined extensions for SharePoint.  It’s a set of XML files which are deployed to web front ends, that can be bundled in site definitions or individually turned on in SharePoint sites.  In the next few blog posts, I’ll try to cover some of the more esoteric capabilities of Features, but before I do that, it’s probably helpful to define a Feature, first.
 
The typical scenario is if you want to deliver a new "Ratings" capability for SharePoint.  You want to make it easy for someone to tag any particular item with a rating, and then aggregate those ratings and provide statistics on them.  To implement Ratings, you’d need to develop a custom list for storing ratings, and web parts for displaying those ratings.  To make this happen in SharePoint, you’d deliver that as a Feature.  The Feature would contain a list definition for defining how Ratings are stored, a list instance for defining the common store of Ratings, a web part definition for showing highly rated items, and perhaps a dashboard web page for aggregating different types of rating views together.   From the end users perspective, they could "activate" (turn on) your Ratings Feature in their site, and the Ratings list and web parts would be made available to them. (yes, ok, this is just a mythical sample.  I'll try to come up with code to illustrate this in a future post.)  The key point is that the Feature in SharePoint is a way to bundle all of these extensions together and get them provisioned into a SharePoint site.
 
Features have a scope, and can be associated with various scopes in SharePoint: web, site, web application, or farm.  Depending on the scope, different types of individual elements can be defined in XML.  For example, you can associate a List Instance at the Web Scope (every provisioned web will get a list provisioned along with it), but you can’t associate a List Instance at the Farm scope. 
 

Site- or web-scoped Features can also be referenced within a site definition, so that as new sites get created your features will get activated.
 
 
Ultimately, though, not every behavior or kind of change you’d want to implement can be expressed in XML.  For this reason, you can also define a feature receiver which contains callbacks which will get fired when the Feature is installed or activated.
 
Features are designed to be a way for developers to express building blocks for SharePoint, and for site admins to pick and choose new functionality they can add to their site.  Out of the box, Microsoft Office SharePoint Server and WSS have about 128 features defined, combined.  That’s a lot of building blocks :)
 
Ok, but why is it called a 'Feature"?   It’s kind of a bit awkward to talk about the "Feature feature".
 
Yep, the name "Feature" leads to some occasional contortions when you talk about it.
 
Why call it a feature?  There were a couple of reasons.  First, one goal was to make it possible for people to choose a site template, but over time add (or remove) capabilities as people needed them -- the philosophy is that choice of site template shouldn’t be a binding choice to force particular functionality for a site forever.  To implement this, we needed to express to site admins which set of capabilities they can turn on.  Calling these capabilities "Features" seemed to be more intuitive than calling them something a bit geekier, like "modules" or "components".  Because the UI term for these was "Features", it made sense to call the development capability called "Features" too.
 
Second, the design of features was in part influenced by the way things are defined in Windows Installer.  Windows Installer has the concept of "features" and "components".  Features are those things you see in some setups where you can pick and choose, in a tree view, which various bits of software to install.  For a brief moment the idea for SharePoint was to have features and components too, but to simplify things a little bit we just put features in (not components.)
 
Well, those are the reasons for the "Feature" name in any case :).  The main hope is that with the Features capability we’ve made it easier for developers to create more compartmentalized, reusable bits of functionality for SharePoint.
The SharePoint Developer Map - a useful overview of SharePoint

One of the things I've wanted to pull together is a way to understand the SharePoint platform in a nutshell.  Towards that end we created a developer map (hosted from here; look for WSS Platform.pdf.)  The idea behind this was to try to bucket and organize the list of tools that SharePoint provides for web application developers.

This is an abstracted overview:

Small Developer Map
 
Basically, this breaks down the SharePoint platform into several large buckets:

SharePoint Data Store.  The data store is the core of the SharePoint platform.  This consists of the site model (an SPSite is a hierarchical collection of SPWebs) plus the lists and libraries infrastructure that is part of every SPWeb.  A security model is integrated with this, and content management capabilities are built on top of this infrastructure as well.

Provisioning.  One of the strengths of SharePoint is the ability to support many, many sites based on particular site definitions.  How those site definitions are defined – and deployed to SharePoint servers, is described in the Provisioning bucket.  In some ways, provisioning is the most exciting to me because the site definitions and XML files really define the heart of what a SharePoint application looks like (well, to a developer).

Administration
.  This area describes how to integrate your central administration components and infrastructure in with SharePoint.

Services.  Services deliver some important bits of the value of developing on top of SharePoint – things like the notion that lists have RSS feeds or alerts.  This is the stuff you get "for free" when your data is hosted in SharePoint.

Pages and User Interface.  Of course, almost all applications built on top of SharePoint will likely have some web based user interface.  The Pages and User Interface bucket discusses things like web parts, the page model, and more.

Anyway, hopefully over the next few months I’ll be able to add some posts on the more obscure topics in each of these areas. 

If you haven't had an opportunity to take a look the developer map, and familiarize yourself with all of the technologies and features of the SharePoint platform, please take a look!

More on Ajax Integration from Eric
Eric Schoonover has a more detailed sample of some work he did with ASP.NET AJAX and MOSS on his blog. This may provide some more insight as to how to get UpdatePanels working smoothly in SharePoint. 
 
Note that he uses a dynamic approach to inserting the ScriptManager onto the page.   As I mention below, I don't think this is a recommended practice from the ASP.NET team, but it looks like he got it working for his scenario.  I'd generally still recommend just embedding the ScriptManager into the master page.
Slides from Berlin
While in Berlin for the SharePoint EU Conference I did a presentation on Customizing User Interfaces with SharePoint (how SharePoint builds on top of ASP.NET) and A Visual Tour of Customizing SharePoint.
 
The slide decks are:
The samples used are also in that folder.
 
The latter slides have some nice visualizations of the CSS classes in SharePoint, which hopefully are useful as you go about working with SharePoint:
 
Integrating ASP.NET AJAX with SharePoint
Ok, so now that this blog is going, now for a common topic I've been asked a bit about recently.  How does Microsoft ASP.NET AJAX integrate with SharePoint?  Here are some notes I've collected on this.
 
Microsoft ASP.NET AJAX 1.0: A Background
 
Microsoft ASP. NET AJAX 1.0 lets developers build Web 2.0 sites using the latest Ajax techniques. 
ASP.NET AJAX extends ASP.NET 2.0 and makes several new tools and techniques available to help you build applications more quickly:
  • Extensions to JavaScript.  ASP.NET AJAX extends the JavaScript library to bring standard object oriented concepts to JavaScript.  It brings a formal type declaration system, with support for inheritance.  It also provides a significant number of out of the box types, including types such as Sys.Net.WebRequest for working with web services.  Finally, it helps to abstract some cross-browser issues such as XML element traversal.  This makes it much easier to create robust JavaScript libraries and frameworks which are commonly needed by rich internet applications.
  • ASP.NET Control Extenders.  Extenders are additional ASP.NET controls which can extend the functionality of existing controls with additional Ajax capabilities.  A common example is an extender which allows existing textbox controls to have autocomplete functionality with no modification to the extended control.   (The autocomplete extender is included with the ASP.NET AJAX Control Toolkit.)
  • UpdatePanels.  UpdatePanels allow your existing ASP.NET controls and web parts to achieve the fluid, no-postback updates of Ajax-based applications with minimal re-coding of your control or part.  Quite simply, controls within the UpdatePanel control which ordinarily would post back to update their data will now be routed through an Ajax-style callback, resulting in a silent update back to the server.  This makes your application “postback” much less, making interaction with your control more seamless.

With Microsoft ASP.NET AJAX 1.0, you can build more dynamic applications that come closer to the rich style of interruption-free interaction you may see in standard client applications.

Microsoft ASP.NET AJAX 1.0 and SharePoint

Windows SharePoint Services version 3 builds much more directly on top of ASP.NET 2.0; therefore, many of the capabilities of ASP.NET AJAX work directly with SharePoint. 
 
However, in a few cases there are some compatibility issues between ASP.NET AJAX and SharePoint which are anticipated to be addressed in the first service pack of Windows SharePoint Services.  For this reason, until that first Service Pack of Windows SharePoint Services, we are unable to offer formal support through Microsoft Product Support Services for usage of ASP.NET AJAX within a SharePoint Web site.  This post is intended to provide developers with some guidelines for evaluating ASP.NET AJAX and WSS3.0. 

Specifically, there are some limitations on usages of the UpdatePanel in your web parts and controls.  Some approaches are described below to address these limitations, but these are workarounds and as such may cause other issues in your application.

Here are some common scenarios in SharePoint you should be able to achieve with Microsoft ASP.NET AJAX 1.0:
  1. Building a more powerful, re-usable JavaScript libraries you can use in your web controls and parts
  2. Enabling your web services to render via JSON, resulting in easier usage in JavaScript/Ajax Applications
  3. Building a web part that takes advantage of Extender technology to provide richer interaction styles, such as autocomplete on a textbox.
  4. Using an UpdatePanel in your web part or control for more fluid, no postback interaction. (this will require some workarounds, however.)
Adding Microsoft ASP.NET AJAX Technology to SharePoint Pages
 
To extend your SharePoint site with Microsoft ASP.NET AJAX 1.0, you’ll need to perform a few steps. 
 
First, you will need to download and install ASP.NET AJAX on servers in your farm.
 
Second, you need to extend web.config with some settings to enable ASP.NET AJAX technology. 
 
Third, you will need to add the ASP.NET AJAX Script Manager into your master page to enable scenarios such as Extenders or UpdatePanels.
 
Installing ASP.NET AJAX on servers in your farm
 
You will want to install the full "ASP.NET 2.0 AJAX Extensions 1.0" from ajax.asp.net.
 
Extending SharePoint web.config files with Microsoft ASP.NET AJAX 1.0
 
Extending SharePoint web.config files with ASP.NET AJAX requires that you interleave some Ajax registration entries in-line with WSS registration entries.  To do this you will need to edit your SharePoint web.config file, typically in a directory like c:\inetpub\wwwroot\wss\virtualdirectories\80.
 
1. Add a <sectionGroup>element to the <configSections>tag:
 
<configSections>   
    <sectionGroup name="system.web.extensions" type="System.Web.Configuration.SystemWebExtensionsSectionGroup, System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35">
      <sectionGroup name="scripting" type="System.Web.Configuration.ScriptingSectionGroup, System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35">
          <section name="scriptResourceHandler" type="System.Web.Configuration.ScriptingScriptResourceHandlerSection, System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" requirePermission="false" allowDefinition="MachineToApplication"/>
        <sectionGroup name="webServices" type="System.Web.Configuration.ScriptingWebServicesSectionGroup, System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35">
          <section name="jsonSerialization" type="System.Web.Configuration.ScriptingJsonSerializationSection, System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" requirePermission="false" allowDefinition="Everywhere" />
          <section name="profileService" type="System.Web.Configuration.ScriptingProfileServiceSection, System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" requirePermission="false" allowDefinition="MachineToApplication" />
          <section name="authenticationService" type="System.Web.Configuration.ScriptingAuthenticationServiceSection, System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" requirePermission="false" allowDefinition="MachineToApplication" />
        </sectionGroup>
      </sectionGroup>
    </sectionGroup>
</configSections>   
 
2. Add a <controls> section as a child of the <system.web>/<pages> tag.
 
    <pages>
      <controls>
        <add tagPrefix="asp" namespace="System.Web.UI" assembly="System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"/>
      </controls>
    </pages>   

3. Add the following tag to the <assemblies> tag, within <compilation>:

      <assemblies>
       <add assembly="System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"/>
      </assemblies>

4. Add some new registrations to the end of the <httpHandlers> section:

 <httpHandlers>
      <add verb="*" path="*.asmx" validate="false" type="System.Web.Script.Services.ScriptHandlerFactory, System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"/>
      <add verb="*" path="*_AppService.axd" validate="false" type="System.Web.Script.Services.ScriptHandlerFactory, System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"/>
      <add verb="GET,HEAD" path="ScriptResource.axd" type="System.Web.Handlers.ScriptResourceHandler, System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" validate="false"/>
  </httpHandlers>
 
5. Add a new registration to the HttpModules section, beneath any existing registrations.

  <httpModules>
      <add name="ScriptModule" type="System.Web.Handlers.ScriptModule, System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"/>
  </httpModules>

 
6. Add a SafeControl entry for the System.Web.UI namespace from Microsoft Ajax Extensions, within the <SharePoint>/<SafeControls>section:

  <SafeControls>
      <SafeControl Assembly="System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" Namespace="System.Web.UI" TypeName="*" Safe="True" />
  </SafeControls>
 
7. Finally, add the following configuration tags at the bottom of web.config, near the bottom before the end <configuration> tag.

  <system.web.extensions>
    <scripting>
      <webServices>
      <!-- Uncomment this line to enable the authentication service. Include requireSSL="true" if appropriate. -->
      <!--
        <authenticationService enabled="true" requireSSL = "true|false"/>
      -->
      <!-- Uncomment these lines to enable the profile service. To allow profile properties to be retrieved and modified in ASP.NET AJAX applications, you need to add each property name to the readAccessProperties and writeAccessProperties attributes. -->
      <!--
      <profileService enabled="true"
                      readAccessProperties="propertyname1,propertyname2"
                      writeAccessProperties="propertyname1,propertyname2" />
      -->
      </webServices>
      <!--
      <scriptResourceHandler enableCompression="true" enableCaching="true" />
      -->
    </scripting>
  </system.web.extensions>
  <system.webServer>
    <validation validateIntegratedModeConfiguration="false"/>
    <modules>
      <add name="ScriptModule" preCondition="integratedMode" type="System.Web.Handlers.ScriptModule, System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"/>
    </modules>
    <handlers>
      <remove name="WebServiceHandlerFactory-Integrated" />
      <add name="ScriptHandlerFactory" verb="*" path="*.asmx" preCondition="integratedMode"
           type="System.Web.Script.Services.ScriptHandlerFactory, System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"/>
      <add name="ScriptHandlerFactoryAppServices" verb="*" path="*_AppService.axd" preCondition="integratedMode" type="System.Web.Script.Services.ScriptHandlerFactory, System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"/>
      <add name="ScriptResource" preCondition="integratedMode" verb="GET,HEAD" path="ScriptResource.axd" type="System.Web.Handlers.ScriptResourceHandler, System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
    </handlers>
  </system.webServer>
 
Adding a ScriptManager into a SharePoint MasterPage
 
Many components of ASP.NET AJAX require the inclusion of a .NET ScriptManager control within a page. 
Although it may be possible in some cases to dynamically insert a script manager from within a control, in many cases the control may not be able to insert the script manager early enough in the page lifecycle depending on how the control is used, making this tricky to get right.  Also, the control implementer will need to ensure that multiple instances of their control (or other controls) do not result in the addition of multiple script managers within the page. For these reasons, dynamic insertion of a ScriptManager control from another control is not recommended.

To statically embed a script manager into a page, it is recommended that you add the ScriptManager into the master page of a site.

To do this, open up the master page for your site.  Typically, this will be located at <site url>/_catalogs/masterpage.  You can edit this file by opening it in an editor such as Microsoft SharePoint Designer, or directly in Notepad by opening your master page library via DAV (typically \\server\<pathtosite>\_catalogs\masterpage.) 
Add the following into the markup of your page.  A recommended location is right beneath the WebPartManager registration  (search for  <WebPartPages:SPWebPartManager id="m" runat="Server" />):
    <asp:ScriptManager runat="server" ID="ScriptManager1"></asp:ScriptManager>
 
Using UpdatePanels within SharePoint
 
UpdatePanels are a very useful addition to ASP.NET AJAX, and represent the simplest way to convert existing, standard ASP.NET controls and parts to take advantage of Ajax techniques.  However, there are some changes within Windows SharePoint Services which may get in the way of working with ASP.NET AJAX.

Windows SharePoint Services JavaScript has a “form onSubmit wrapper” which is used to override the default form action.  This work is put in place to ensure that certain types of URLs, which may contain double byte characters, will fully work across most postback and asynchronous callback scenarios.  However, if your scenarios do not involve double byte character URLs, you may successful disable this workaround and gain the ability to use ASP.NET AJAX UpdatePanels.

To do this, you may need to register a client startup script which disables this workaround, in addition to resetting the default form action:
<script type='text/javascript'>_spOriginalFormAction = document.forms[0].action; _spSuppressFormOnSubmitWrapper=true;</script>

This script may be directly embedded in the page, or could be emitted by a control that uses the UpdatePanel.  The following is an example of a very simple ASP.NET Web Part which uses UpdatePanel capabilities:

using System;
using System.Collections;
using System.Text;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI;
namespace MS.Samples
{
    public class AjaxUpdatePanelPart : WebPart
    {
        private Label label;
        private TextBox textBox;
        protected override void  CreateChildControls()
        {
      base.CreateChildControls();
            this.EnsureUpdatePanelFixups();
            UpdatePanel up = new UpdatePanel();
            up.ID = "UpdatePanel1";
            up.ChildrenAsTriggers = true;
            up.UpdateMode = UpdatePanelUpdateMode.Conditional;
            this.Controls.Add(up);
            this.textBox = new TextBox();
            this.textBox.ID = "TextBox";
            up.ContentTemplateContainer.Controls.Add(this.textBox);
            this.label = new Label();
            this.label.Text = "Enter your name.";
            up.ContentTemplateContainer.Controls.Add(this.label);
            Button button = new Button();
            button.Text = "Say Hello";
            button.Click += new EventHandler(HandleButtonClick);
            up.ContentTemplateContainer.Controls.Add(button);
        }
        private void HandleButtonClick(object sender, EventArgs eventArgs)
        {
            this.label.Text = "Hello " + this.textBox.Text;
        }
        private void EnsureUpdatePanelFixups()
        {
            if (this.Page.Form != null)
            {
                string formOnSubmitAtt = this.Page.Form.Attributes["onsubmit"];
                if (formOnSubmitAtt == "return _spFormOnSubmitWrapper();")
                {
                    this.Page.Form.Attributes["onsubmit"] = "_spFormOnSubmitWrapper();";
                }
            }
            ScriptManager.RegisterStartupScript(this, typeof(AjaxUpdatePanelPart), "UpdatePanelFixup", "_spOriginalFormAction = document.forms[0].action; _spSuppressFormOnSubmitWrapper=true;", true);
        }
    }
}

Output Caching and ASP.NET AJAX
 
ASP.NET AJAX infrastructure is not compatible with output caching features.  This output caching infrastructure is a featured component of managed content pages such as those supported by web content management features in Microsoft Office SharePoint Server.  For this reason, many scenarios which involve output cached features may not be able to take advantage of components like UpdatePanel.  However, you will be able to successfully use other ASP.NET AJAX features, such as the JavaScript library, combined with your output cached pages.

Compatibility with output caching is targeted for a future release of ASP.NET AJAX infrastructure.
 
Conclusion
 
Microsoft ASP.NET AJAX 1.0 provides great building blocks for building rich Ajax-enabled applications.  Combined with the power of the SharePoint platform, and knowing some of the integration limitations, you can build powerful Web2.0 applications that bring together the best of both of these technologies.
Welcome!
Now that we have this nifty hosted SharePoint server, I figured it's a good time to start a blog.
 
Hello! I'm Mike Ammerlaan, a Program Manager on the Windows SharePoint Services team.  I focus on the developer platform, including things like web parts, ASP.NET integration, features, solutions, object model, and the like.  Before working on SharePoint for v3, I also worked on Excel and Combat Flight Simulator 3.
 
Hopefully over the next few months I'll be able to post some more information on interesting SharePoint features and capabilities.  Thanks for stopping by!
 
 
These postings are provided "AS IS" with no warranties, and confers no rights.

 Developer Resources

  SharePoint on MSDN
  Windows SharePoint Services SDK
  SharePoint Developer Screencasts
  2007 EU SharePoint Conference Files
  Visual Studio Extensions for SharePoint

 ‭(Hidden)‬ Admin Links