Jaap Vossers' SharePoint Blog

Just another WordPress.com site

Minimal implementation of a custom templated ASP.NET control using the ITemplate interface

with one comment

Below you will find a code snippet to demonstrate a minimal implementation of a custom ASP.NET control that allows page designers to specify a template which will be used by the control to render itself, using the ITemplate interface.

Markup:

   1:  <my:MyTemplateBasedControl runat="server" id="myTemplateBasedControl1">
   2:      <MyHeaderTemplate>
   3:          <div>
   4:              Some text <asp:Button runat="server" Text="And a button..." />
   5:          </div>
   6:      </MyHeaderTemplate>
   7:  </my:MyTemplateBasedControl>

Control code:

   1:  public class MyTemplateBasedControl : CompositeControl
   2:  {
   3:      public ITemplate MyHeaderTemplate { get; set; }
   4:   
   5:      public MyTemplateBasedControl()
   6:      {
   7:   
   8:      }
   9:   
  10:      protected override void CreateChildControls()
  11:      {
  12:          base.CreateChildControls();
  13:   
  14:          // If <MyHeaderTemplate></MyHeaderTemplate> was supplied
  15:          // in the page that contains this control, then this.HeaderTemplate
  16:          // will automatically be set for you with an object of type
  17:          // System.Web.UI.CompiledTemplateBuilder
  18:          if (this.MyHeaderTemplate != null)
  19:          {
  20:              // let's instantiate multiple instances of our template
  21:              for (int i = 0; i < 10; i++)
  22:              {
  23:                  // This will "convert" the string supplied inside
  24:                  // <MyHeaderTemplate></MyHeaderTemplate> into 0 or more controls.
  25:                  // Each of these controls will be added to this.Controls
  26:                  // since we pass in "this" into the InstantiateIn() method
  27:                  this.MyHeaderTemplate.InstantiateIn(this);
  28:              }
  29:          }
  30:      }
  31:  }

Result:

itemplate_result

Written by jvossers

May 12, 2010 at 3:35 pm

Posted in ASP.NET, Development

Released: SharePoint WebPartSlices

with one comment

I have recently released my sixth CodePlex project (list of all my CodePlex projects), titled SharePoint WebPartSlices.

To all the jQuery fans – Sorry, no jQuery this time! SharePoint WebPartSlices is a server-side solution that allows users to transform all Web Parts on a page into IE8 Web Slices simply by adding the webslices=1 querystring parameter to the url of the page containing the web parts to be transformed, basically allowing you to add web parts to your IE8 Favorites Bar.

webpartslices1

Voilà – No need to navigate to the original page to see the updated Web Part.

webpartslices2

Installation consists of a WSP deployment + Feature activation only.

SharePoint WebPartSlices on CodePlex

Written by jvossers

February 4, 2010 at 12:06 pm

Per-Location View Settings in SharePoint 2010 (Views per Content Type)

with 9 comments

What’s that supposed to mean? That’s what went through my head when I saw a new link which had appeared on the List Settings page (listedit.aspx) in SharePoint 2010.

When I clicked the link, I was directed to a page where I could manage the available views per “location”.

The word “location” can have many different meanings. My initial thought was that it was referring to folders inside the list and that this page is used to configure which views are available per folder.

This turned out to be correct. I added a folder to the list and was able to make my custom view appear on there, whilst hiding it from the root of the list.

Is that all? Why call it locations when you mean folders? Well, because it does not only apply to folders!

You can configure available views for ANY NODE in the “Metadata navigation”. As a result, In addition to views per folder – depending on how you set up your Metadata navigation for your list – you can:

  • Define views that are available only on items of a particular Content Type (my favourite, demonstrated below)
  • Define views that are available only on items that have a particular value for a field of type single-value choice.
  • Define views that are available only on items that have a particular term applied to it on a field of type Managed metadata.

Let me demonstrate how to make our “Books Grouped by Author” view available only to our Book content type in our Products list, whilst hiding it for all other type of products in the list.

Below is a summary of all the steps. I will only discuss the last two steps where we configure Metadata navigation and the Per-location view settings, as this what this article is all about.

  1. Create custom list Products
  2. Create content types:
    1. Book (Title, Price, Author)
    2. Movie (Title, Price)
    3. Music Album (Title, Price, Artist)
  3. Configure list to allow management of Content Types
  4. Associate Book, Movie and Music Album with list and delete Item Content Type
  5. Populate list with items for each Content Type
  6. Create view Books Grouped by Author
  7. Configure Metadata navigation
  8. Configure Per-location view settings

Once we have successfully performed steps 1 to 6, we need to bring up the Metadata navigation settings screen for our list. The link to this page can be found on the List Settings page. In the Configure Metadata Hierarchies section, we need to select the “Content Type” item from the list on the left and move it to the right and press OK

As a result, we should now get a hierarchical navigation control on the left of our list.

Once that’s done, we need to bring up our Configure per-location view settings page. The link to this page can also be found on the List Settings page. On the left, there is a hierarchical control labelled “Location to Configure”. We need to use this to select the node (or Location if you like) to which we will be applying the configuration defined on the right. We start with the root node, which is selected by default. We don’t want our grouped view to be available at the root, so we select it in the “Views available at this location” list and move it to the “Views hidden from this location” list and press Apply. Next, we need to expand the “Content Type” node in the tree on the left and select Book. By default it is configured to inherit its settings from its parent, which it not what we want. Set this to No, and move the grouped view to the “Views available at this location” list. While we are at it, let’s move the All Items view to the “Views hidden from this location” list, so that our grouped view becomes the default view for the Book Content Type, and press OK.

Navigate to the list. When selecting Book in the Metadata Navigation on the left, the grouped view should now show instead of the All Items view. Note that  the Book Content Type node in the metadata navigation, is also the ONLY location where our grouped view is available.

On a final note, I noticed that the Per-location view settings link does not appear on the List Settings page when the list is contained in a Blank Site. I performed the actions above on a Team Site. Presumably certain Features needs to be activated to enable this functionality, however I currently don’t know which one. Also, I am not sure how much of this functionality depends on SharePoint Server 2010 and whether it will work on a SharePoint Foundation installation.

Written by jvossers

December 27, 2009 at 10:13 pm

Posted in SharePoint 2010

jQuery Developer Frameworks for SharePoint

with 2 comments

If you are into developing SharePoint solutions using jQuery, you should really have a look at the following GREAT CodePlex projects. Both projects have been developed by real experts in the SharePoint & jQuery field 🙂

jPoint – Developed by a team lead by Will Lawrence (@willhlaw)

jPoint is an open source javascript API and script deployment framework for Sharepoint. It leverages the speed and agility of jQuery to manipulate Sharepoint forms and pages, communicate to Sharepoint webservices, and to build jPart plugins.

jQuery Library for SharePoint Web Services – Developed by Marc D Anderson (@sympmarc)

This is a jQuery library which abstracts SharePoint’s Web Services and makes them easier to use. It also includes functions which use the various Web Service operations to provide more useful (and cool) capabilities. It works entirely client side and requires no server install.

Written by jvossers

December 16, 2009 at 12:06 pm

Released: SharePoint 2010 Developer Dashboard Visualizer

with 5 comments

As announced before, I have been working an open source project that visualizes the data in the Developer Dashboard in SharePoint 2010.

The good news is that SharePoint Developer Dashboard Visualizer is now up on CodePlex.

SharePoint 2010 Developer Dashboard Visualizer is a jQuery-based solution that extends the Developer Dashboard by plotting an interactive diagram with data from the Developer Dashboard, giving you an **instant** insight into where the bottlenecks are in your code.

(yes, well spotted… I was stupid enough not to rename my machine before installing SharePoint 2010)

The installer is just a WSP so it’s a quick and easy install!

Finally, a big thank you goes out to Bil Simser for being the first person to post a review for SharePoint Developer Dashboard Visualizer online.

Written by jvossers

December 13, 2009 at 10:12 pm

Context in SharePoint 2010 Business Connectivity Services (or the lack of it)

with 9 comments

The problem I see with Business Connectivity Services is the lack of context available when writing your custom code to retrieve and update data. As a result, custom BCS implementations are not very reusable because the lack of configuration options per External List.

Let’s look at an example.

ACME Ltd, an ISV focusing on selling SharePoint products, wants to develop and sell a BCS solution that allows customers to create External Lists based on data that resides in ANOTHER SharePoint site collection. In a nutshell, the External List will contain a “virtual” list item for each site in the target site collection. Now how does the BCS code know where this target site collection is? You could hardcode the url, or you could store the url in the appSettings in the web.config for your web app. These are both solutions that will give you headaches when you need more than one instance of this External List, each using the same BCS code, but retrieving data from different target site collections.

When I created a new Business Data Connectivity Model in Visual Studio 2010 for the first time and I looked at the code that was initially generated (Entity1Service.cs), I was surprised that there seemed to be no way to derive any of the following in code:

  • SPWeb instance or url of the site that contains the External List we are trying to load data for.
  • Name (or ID) of the External List we are trying to load data for. This, together with an SPWeb, would allow you to read per-list configuration data from SPList.RootFolder.Properties
  • Some string containing configuration data that applies to our BCS Entity to External List association. Something similar exists for EventReceivers and Workflow, so why does it not exist for BCS?

I would be very interested to hear people’s thoughts on this subject.

Written by jvossers

December 13, 2009 at 1:10 pm

How to interpret the information in the Developer Dashboard in SharePoint 2010

with 3 comments

When I first had a look at the Developer Dashboard in SharePoint 2010 I was a bit confused. The numbers shown in the nested unordered list on the left, representing load times in milliseconds, didn’t seem to actually cover 100% of the the request that was being handled. Basically it turns out that there are “gaps” that are not monitored, which is exactly why the sum of execution times for a certain set of child nodes in the list often don’t match the execution time of the parent. This is due to the SPMonitoredScope model.

Each node in the list represents a SPMonitoredScope that was created, either in SharePoint OOTB code or in code that you wrote yourself. When a second SPMonitoredScope is created before the first one is disposed, the second one will be treated as a child scope of the first one. In the context of a web request, the top level scope is instantiated in the SPRequestModule. Scopes that you instantiate yourself will most likely become child scopes of this “Request scope”.

Lets look at an example for a custom Visual WebPart that creates it’s own scopes.

   1:  protected void VisualWebPart1_Load(object sender, EventArgs e)
   2:  {
   3:      using (SPMonitoredScope mainScope = new SPMonitoredScope("VisualWebPart1_Load mainScope"))
   4:      {
   5:          Thread.Sleep(5000); // some processing that is not inside a subscope
   6:   
   7:          using (SPMonitoredScope subScope1 = new SPMonitoredScope("VisualWebPart1_Load subScope1"))
   8:          {
   9:              Thread.Sleep(1000);
  10:          }
  11:   
  12:          using (SPMonitoredScope subScope2 = new SPMonitoredScope("VisualWebPart1_Load subScope2"))
  13:          {
  14:              Thread.Sleep(1000);
  15:          }
  16:   
  17:          using (SPMonitoredScope subScope3 = new SPMonitoredScope("VisualWebPart1_Load subScope3"))
  18:          {
  19:              Thread.Sleep(1000);
  20:          }
  21:      }
  22:  }

Now let’s look at the resulting Developer Dashboard output.

scopes

Do you see what I mean?

Now on  a similar note, I have been working on a project that visualizes the data rendered by the Developer Dashboard. It’s just not easy enough to spot “peaks” without it. 

As you might have guessed, it’s a jQuery based solution. I am hoping to put it on CodePlex soon. Here is a sneak peek (click to enlarge):

devdashvis1

Written by jvossers

November 27, 2009 at 4:44 pm

Released: SharePoint LiveListData

with 20 comments

Last week I published my fourth CodePlex project, called SharePoint LiveListData. It is an “assembly-free”  solution which means that it contains no server side code. It is implemented as a jQuery plugin.

So what does it do? It uses AJAX to automatically reload any list-based Web Parts as soon as a change in the underlying list data is detected. You can also have your custom web parts refreshed, as long as they have a web part property that contains the ID of the list they depend on!

I have put online a screencast that demonstrates the the user experience.

Want to know how it works? Allow me to describe using some pseudo code..

  • OnDocumentLoaded
    • Make a single call to WebParts.asmx web service using AJAX to return an xml document with all web parts on the current page
    • Parse returned xml and find all web part nodes that contain a ListID element (which holds the value for the ListID web part property)
    • Create and populate a javascript object that contains a list of all ListIDs that we found in the returned xml, plus a list of all WebPartIDs per ListID, also retrieved from the xml (more or less creating a hashtable with the key being the ListID and the value being an array or WebPartIDs).
    • LOOP with interval = $configured_interval
      • Make a single call to Lists.asmx web service using AJAX to retrieve “LastDeleted” and “Modified” properties for each ListID in the hashtable that was created earlier.
      • For each ListID in hashtable
        • compare values for LastDeleted and Modified with those values retrieved as part of the previous loop iteration for this ListID (unless it’s the first iteration).
        • If a change in one of the two property values has been detected (indicating that someone inserted, updated or deleted an item) mark this ListID as “UpdatePending”, storing it on our javascript object that holds our ListIDs and WebPartIDs.
      • If any of the ListIDs are marked as UpdatePending
        • Make an AJAX request to page that is currently loaded in the browser (allowing us to get a fresh copy of the current page containing the new list data)
        • For each ListID marked as UpdatePending
          • For each WebPartID associated with ListID in our javascript hashtable object thingy
            • Replace div with matching WebPartID attribute in current document with “same” div in AJAX response (which contains the new list data).

This is basically how it works in a nutshell.

For examples on usage, check out the downloads tab on the SharePoint LiveListData CodePlex site, where you can also download the script!

Written by jvossers

November 3, 2009 at 11:40 pm

A developer’s thoughts on the Microsoft SharePoint Conference 2009 in Las Vegas

with 5 comments

After having attended the Microsoft SharePoint Conference in Las Vegas last week, I decided to write a blog post in which I will summarise my thoughts on SPC09 and SharePoint 2010 from a Developer point of view.

The majority of the sessions I attended were developer-oriented sessions.  There are so many new promising features that will greatly increase developer productivity.  I seriously can’t wait to start my first SharePoint 2010 project!

Let’s just walk through some of the new features that I think are most promising.

Client Object Model

The Client Object Model is a richer alternative to the already existing SharePoint web services. Before SharePoint 2010, anyone writing code that would run somewhere else then on the actual SharePoint server could not use the Server Object model but instead had to rely on using the SharePoint web services.  If you knew how to use the Server Object model, that didn’t necessarily mean you knew how to deal with the web services, since they are so different!

SharePoint 2010 Introduces the Client Object Model which comes in three flavours: Javascript, .NET CLR and Silverlight. It basically means that your code can call into the Client Object Model, which exposes a programming interface that is very similar to the Server Object model programming interface. The idea is that you can apply your knowledge of the Server Object Model to the Client Object Model.

I am particularly looking forward to using the Javascript Client Object Model, combined with jQuery. Any half-decent developer will now be able to build rich, AJAX-enabled UI’s in SharePoint 2010 without too much effort.

REST API

The REST API is another feature that will simplify the process of consuming data from client applications by exposing a very simple HTTP based interface. It basically allows you to fetch or update/insert/delete data in SharePoint. You can specify what data you want to work with by constructing a url that SharePoint understands. The url will include parameters for the web, the list and possibly a filter that SharePoint will use to scope the operation to. If you are simply performing a fetch of the data, the server will return XML or JSON (depending on what you asked for by adding the right HTTP header to your request) for you to consume in your client application.

Again something that will be very useful in a javascript client, with or without jQuery, as you can perform AJAX requests in the background to fetch or modify data. Fetched data returned as JSON can easily be converted into javascript objects for further consumption in your javascript code.

For .NET clients there is a thing called ADO.NET Data Services which allows you to create DataSources that point to a REST url, which can then be used as the DataSource for databound controls. One of the sessions at SPC09 demonstrated how easy it is to set up a grid with insert/update/delete support, simply by binding it to such a datasource. Amazing!

SPMetal + LINQ

Cool! Now you won’t have to write those pesky CAML queries anymore AND you won’t have to access SPListItem field values through an indexer that returns an object that isn’t strongly typed – which in turn means that you don’t have to perform any casting anymore. Querying is now done via LINQ, which I am sure you have heard of before. You can actually perform inner joins in LINQ allowing you to use only one query to return all Employee items where Employee.Company.CompanyName == “Microsoft”. In SharePoint 2007 you need to perform two separate queries to achieve this. I am curious how this works under the hood. My understanding is that your LINQ query is translated to a CAML query which is then executed. If that’s true then presumably they have extended the CAML query schema to support JOINs. Does anyone have an answer to this?

SPMetal is the commandline tool that generates the classes to support LINQ Querying and strongly typed access to properties of an SPListItem.

Business Connectivity Services

This is the replacement for Business Data Catalog. It allows you to write data access code which can be used to connect alternative data source to SharePoint lists. SharePoint users won’t even notice that the “list data” they are working with is in fact stored somewhere else.

I really hope my code can access this external data as if it was contained in a standard SharePoint list, for example by using the SPList and SPListItem classes or performing LINQ queries. Does anyone have an answer to this?

Developer Dashboard

The developer dashboard helps developers with identifying poorly performing code by having diagnostic information related to your current request printed on the page. It is similar to the ASP.NET trace information, but more SharePoint-specific. It prints processing time for Web Parts (allowing you to instantly spot which one is causing the page to be so slow) and even processing time for the underlying Stored Procedures that are executed by SharePoint!

PowerShell

PowerShell is the new STSADM for SharePoint. Microsoft has invested heavily in PowerShell support for SharePoint by providing hundreds new SharePoint-specific Cmdlets! Looks very promising. I have this PowerShell book somewhere – I think I will pick it up again soon!

Visual Studio integration

Visual Studio 2010 integration for SharePoint 2010 development has strongly improved. I must say that for some reason I had assumed Microsoft would provide this level of integration when MOSS 2007 came out a few years ago (wishful thinking), but unfortunately we’ve had to depend on third party tools like WSPBuilder to produce our deployment artifacts. I guess it was necessary for us to go through this pain in order for us to be able to appreciate what’s coming our way now!

Custom Service Applications

There is no such thing as an SSP in SharePoint 2010. Instead there is a collection of Services Applications, to which you can add your own custom Service Application. The main focus lies on scalability – it supports load balancing and you can decide which servers in the farm will run your custom Service Application.

It is very important to plan properly and decide whether a custom Service Application is the right solution to your problem. Developing custom Service Applications might well be the most complex subject within SharePoint Development.

Written by jvossers

October 30, 2009 at 1:09 pm

Increasing the size of your VM disk using VMWare and GParted

with one comment

UPDATE: Although the instructions below still work, it appears that this method is a bit outdated since there is a much easier method out there!  VMWare ConverterCredits to Peter vd Berg, thanks!

Disclaimer: playing with partitions is always a risky thing and can mess up your machine. I cannot be held responsible for any harm done to your machine as a result of following the instructions below. The instructions happened to work for me, but I cannot guarantee that they will work for you!

Let’s say you have a VM that has a C: drive that reports low disk space on daily basis, and you spend every day cleaning up log files, hoping to free up at least 100 mb of disk space in your VM so you can continue your development stuff for another day…

This situation is actually quite common I think, but it seems that still a lot of people don’t seem to know how to properly deal with it. I think the problem lies with the fact that a lot of people seem to think that increasing the size of disk also automatically increases the size of the partition on it – which is not true.

After having read a few articles on the web and some experimenting I have written down a summarised set of steps in my own words which will help you increase the size of your disk and your partition inside a VM, without having to buy any commercial partitioning tools like Partition Magic.

  1. Backup all vm files
  2. Run vmware-vdiskmanager.exe to increase the disk size (this does NOT increase the partition the drive).
    “C:\Program Files\VMware\VMware Workstation\vmware-vdiskmanager.exe” -x 30Gb “D:\MY_VM.vmdk”
    Replace the value of –x parameter with the new size of the disk. vmware-vdiskmanager.exe comes with VMWare workstation, which unfortunately it’s not free – but you should be able to download a trial version from the VMWare site.
  3. Open the .vmx file with notepad and add the following line to make it easy to get into the bios:
    bios.bootDelay = “5000”
  4. Download the GParted live cd ISO image (open source alternative to partition magic) and mount it to the virtual machine using VMWare.
    http://sourceforge.net/project/showfiles.php?group_id=115843&package_id=271779
  5. Start up the VM and use F2 to go to the bios. Change the boot order to have the cd drive on top and reboot.
  6. Run GParted to increase the size of the c: partition.
  7. Change back boot order, remove bootdelay and unmount cd.

DONE

Written by jvossers

September 22, 2009 at 1:24 pm

Posted in Virtualisation