Skip to main content

Wouter

Go Search
Home
Contact Me
  

 ‭(Hidden)‬ Admin Links

SharePoint Connections Berchtesgaden in May

Just under a month away and the awesome SharePoint Connections event will visit Germany. This year I will host three sessions on SharePoint development. Topics ranging from high level 'component based development' stuff to low level details such as handling lists. I hope you will come have fun with me! The location is definitely up to par. A small search on Google gave me this picture. Who wouldn't want to combine some SharePoint with that?

 

 

 

Disabling IIS pinging permanently

Many times I have been frustrated with receiving the 'Your application pool was self destructed by IIS because of pinging blah blah' message during my debugging sessions of SharePoint (not sure but, is it true that SharePoint debugging sessions take longer on average, and therefore your see this message more often?)

Of course disabling pinging is not difficult at all. You find the option in the advanced settings of the application pool in question. 'Ping enabled' it's called if I am not mistaken.

However….

For many SharePoint folk it is not uncommon to recreate stuff during deployment, and among that stuff might be the web application you are deploying to. New web application means new application pool, which means new pinging enablement, meaning frustration in the making.

Today you have a chance to stop this frustration for now and ever-ever. You only have to run this script. Don't worry, it's safe. I said so, and it is written on the internets which means it must be true. You are also downloading from my demo site which only contains awesomeness anyhoo.

So, what do you get?

The script will turn off IIS.

Therefore you will never have issues!

Oh wait, yeah. It also goes to the XML configuration files of IIS to change the default value for 'Ping enabled' to false. Next, it goes to all the application pools already defined, and turns pinging off for those too. That means your existing application pools And your new ones will never ever ever ever frustrate you anymore. The only frustration now is your own. I take no ownership in that!

Hope it helps! And see you another great SharePoint day!

Reset the SharePoint config cache using PowerShell

In very, very, broad and general terms, there are two types of databases in SharePoint. The configuration database stores configuration data and you have content databases to store the content in the farm. The configuration database houses XML serialized objects. These objects are also cached on disc on each server in the farm. Sometimes, this cache can get out of sync and you have to reset the cache. This involves stopping the timer service, clearing out a special folder, and resetting a cache management file.

You can download this demo from my CodePlex site at http://woutersdemos.codeplex.com/releases/view/85474.

The following script automates this on all machines in the server farm by using PowerShell and the SharePoint object model to figure out which servers take part in the farm. If you do decide to run it, the following will be displayed.

The content of the generic script is as follows. Note that the entire script is generic and works on any SharePoint farm. PowerShell remoting should be configured to work correctly on your farm, which I hope is already the case J

First, get all server names of the valid servers in the SharePoint farm.

$Servers = Get-SPServer | ? {$_.Role -ne "Invalid"} |
  Select -ExpandProperty Address
Write-Host "This script will reset ...."
$Servers | Foreach-Object { Write-Host $_ }
Write-Host "Press enter to start."
Read-Host

Next, use PowerShell remoting to run a script block on each server. Use try / finally to ensure that the timer service will always be started again no matter what.

Invoke-Command -ComputerName $Servers -ScriptBlock {
  try { 

First, stop the timer service which has locks on the configuration cache.

    Write-Host "$env:COMPUTERNAME - Stopping timer service"
    Stop-Service SPTimerV4 

Retrieve the ID of the configuration database from the registry. This ID identifies the caching folder on disc.

    $ConfigDbId = [Guid](Get-ItemProperty '<registry key>' -Name Id).Id
    $CacheFolder = Join-Path -Path ([Environment]::GetFolderPath(
      "CommonApplicationData")) 
      -ChildPath "Microsoft\SharePoint\Config\$ConfigDbId"
    Write-Host "$env:COMPUTERNAME - Clearing cache folder $CacheFolder"

Clear out the cache.

    Get-ChildItem "$CacheFolder\*" -Filter *.xml | Remove-Item

Locate the cache ini file and reset it by writing the value '1' into the file.

    Write-Host "$env:COMPUTERNAME - Resetting cache ini file"
    $CacheIni = Get-Item "$CacheFolder\Cache.ini"
    Set-Content -Path $CacheIni -Value "1" 
  }
  finally {
    Write-Host "$env:COMPUTERNAME - Starting timer service"
    Start-Service SPTimerV4
  }
}

Presto! One generic script that you can call as an admin or make use of in an installation procedure.

Hope it helps!

Demo for my lists session @ SC12

For my session on advanced list customization, find the demos below. There are no slides.

Demos on CodePlex

Hope it helps! And have fun this afternoon!

Slides and demo for my sandboxing session @ SC12

For my session on real world sandboxed solutions, find the demos and slides below.

Slides on SlideShare

Demos on CodePlex

Hope it helps! And have fun this afternoon!

 

Explaining some of the GUID strangeness of SharePoint

As any SharePoint aficionado I spend quite some time in decompilers to find out why and how certain bits of SharePoint work. Today I came across a beauty that explains to some degree why for GUID values you sometimes must have {curly braces}.

The following screenshot is of the BaseXsltDataWebPart, the base class for all views in SharePoint. Notice the 'IsGuid' method and how it is hardcoded to check whether there are curly braces in the string formatted GUID. Funky stuff! This method is used by the base class to read fields from the list being queried. It is already widely known that you must have curly braces in field IDs, and you can have curly braces in most other places. Now you know why!

Advanced cache invalidation using HTTP

One common approach to enabling high performance web applications is to cache data that does not change frequently. SharePoint is no different in this and provides a host of caching options including blob caching, list item caching, object caching and of course the normal ASP.NET cache. This last caching infrastructure has the focus today. For that entire infrastructure I want to focus on only a small part of the equation; cache invalidation. Usually my preferred approach is to invalidate the cache when the data changes and reload the cache when the data is accessed. In essence this is not so difficult. Simply call Cache.Remove and later on do a Cache.Insert right? While this works for small deployments, as soon as you start to use some of the scaling features of SharePoint you bump into issues. What if you have extended your web application into multiple zones? What if you have multiple web servers? In both cases you will have to deal with multiple caches since each server / zone combination utilizes its own cache. The Cache.Remove code would only invalidate the cache on a single server, in a single zone! This article provides an elegant solution for invalidating a cache across the entire farm.

Code for this article.

It's about context!

At the core the issue is simple. You have multiple HTTP contexts, one per server/zone, each with a separate cache. Your code usually executes in only one of them. We want the code to execute in all contexts so that the cache gets invalidated everywhere. One approach that is almost entirely built-in to the caching infrastructure of ASP.NET is to use a dependency on a file. In ASP.NET you can make use of the native Windows ability to notify your application that files have changed. The ASP.NET cache makes use of this ability to allow cached data to be invalidated when this happens. Typically the scenario is that you load a file from disc into the cache and then monitor changes on that file to invalidate the data. However, you can also make use of this native ability to invalidate the cache in every zone on every server by placing the file in a file share and configuring the cache with a UNC path. You can have each server listen to the same file and hence update all caches at once. The upside to this approach is that it is already implemented for you. There is very little code required. There are also slight downsides to this approach. You will have to create a file share with your solution, something you cannot do natively with WSPs. You will have to configure the location of this share so you code call Cache.Insert with the right parameters. You will have to think about on what server to create the file share. This makes one server more special than another. This could potentially become an issue when changing the farm topology. Next, some organizations I work for have pretty strict rules around creating file shares, meaning, that it is not allowed to create any. One last note about this approach is that granular refreshes become more difficult. You'll want to differentiate between the various pieces of data you cache and only invalidate some of it. You could for instance use one file per type of cached data or similar constructs to provide the granularity. It's not so pretty though!

A new approach to an old problem

Recently I have developed another approach which alleviates many if not all of these issues. The approach involves notifying each HTTP context of a change in the cached data by simply sending a request to a known HTTP end point that runs within that context. The code running at that end point can simply perform the Cache.Remove to remove the changed data. There is one big concern with this approach and that is load balancing. If you have multiple front end servers and you send your HTTP request to a host such as http://intranet or http://www.contoso.com how do you ensure you hit all the servers? Through load balancing all your requests might go to a single machine! The simple solution to this issue is to craft a better HTTP request. You can send an HTTP request to the IP address of a single server to work around any load balancing. By applying the HOST header you can still target the correct IIS web site hosted on the server and hence call into the right context.

Let's go!

In this demo the first step is to create a well-known HTTP end point for your cache invalidation code to hit. A simple HTTP handler will do just nicely. Notice how we can simply access the HTTP context and the cache from the HTTP handler.

public class InvalidateCacheHandler
    : IHttpHandler
{
    public bool IsReusable
    {
        get { return true; }
    }

    public void ProcessRequest(HttpContext context)
    {
        context.Cache.Remove("TestKey");
        context.Response.StatusCode = (int)HttpStatusCode.OK;
    }
}
Now that we have our end point defined the next step is to ensure that the HTTP handler is actually called on each server and for each extended zone. For this we need to retrieve the host name or IP address of each server, all the zones and craft a HTTP request for each of combination of the two.

Given a web application, we can start to build out this code.

void InvalidateCacheForWebApplication(SPWebApplication webApp)
{
}

First, we use the web application to access all the servers in the farm. This gives us the host name of each server, which might be an IP address. Although not entirely necessary the code translates each host name into an IPv4 IP address using the power of a little .NET and the System.Net namespace.

IEnumerable<IPAddress> serverAddresses = webApp.Farm.Servers
    .Where(server => server.Status == SPObjectStatus.Online)
    .SelectMany(server => Dns.GetHostAddresses(server.Address))
    .Where(ip => ip.AddressFamily == AddressFamily.InterNetwork);

Next, enumerate over each zone and over each IP address. This is the matrix to where we must send HTTP cache invalidation calls. Note that we might hit a single server twice if it has more than one valid IP address. Oh well…

foreach (SPAlternateUrl zoneUrl in webApp.AlternateUrls)
{
    foreach (IPAddress ipAddress in serverAddresses)
    {
    }
}

Inside the double loop we craft the HTTP call. We want to send the HTTP request directly to a specific server. The server will then identify the right IIS web site using the HOST header. This means we must setup the host header for the HTTP request, which, I am afraid, is not supported in .NET 3.5. The common workaround is to use the HttpWebRequest.Create method to set up the HOST header and then use a WebProxy class to configure the destination for the request. This combination will send the request to the right server and to the right IIS web site on that server.

UriBuilder ipUri = new UriBuilder(Uri.UriSchemeHttp, 
    ipAddress.ToString(), zoneUrl.Uri.Port);
UriBuilder hostHeaderUri = new UriBuilder(zoneUrl.Uri);
hostHeaderUri.Path = "_layouts/CooleCacheCode/InvalidateCache.ashx";
HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(hostHeaderUri.Uri);
request.UseDefaultCredentials = true;
request.Proxy = new WebProxy(ipUri.Uri, false);

After having crafted the HTTP request we need to, well, request the data. We can use the HTTP response code to see if the server answered and therefore has invalidated the cache.

try
{
    HttpWebResponse response = (HttpWebResponse)request.GetResponse();
    if (response.StatusCode != HttpStatusCode.OK)
    {
        // something wrong 
    }
}
catch (WebException)
{
    // something really wrong 
}

Kickass! We now have the code to invalidate caches across our entire server farm. A big benefit is that changing topologies means exactly no change to this code. There is no chance of someone accidentally deleting the file share and we now also have the power of adding granularity to the code by using HTTP query strings to identify the cached item that should be invalidated. All in all a pretty sweet solution!

Hope it helps!

Declarative Fun: Provisioning Web Part Connections in sandboxed solutions

One of my current projects involves the new sandboxed deployment model. It is pretty fun and challenging to translate requirements into testable code. With the promise of deploying into environments like Office 365 there is a strong will to work around the limitations of the sandbox. Of course without resorting to solutions based on a senseless full trust proxy. One of the limitations is that there is no SPLimitedWebPartManager class. This means it is not possible to modify the Web Parts on a page using code. This is a bit of an issue since I want to deploy two related Web Parts that are connected together using a Web Part Connection. Overcoming the issue was fun enough for me to write about. So here goes. Web Parts, Web Part Connections and all fit for sandboxed deployment.

Find the sample project here.

Provisioning Web Parts

First step is to provision a Web Part to the page. Since the imperative approach using the SharePoint object model is not available in the sandbox we can only use declarative XML. My Web Parts are deployed to a page using a <Module> element which provisions a bunch of <File> elements, each of which contain various <AllUsersWebPart> elements.

<Elements xmlns="http://schemas.microsoft.com/sharepoint/">
  <Module Name="Module1">
    <File Path="Module1\default.aspx" Url="demo.aspx">
      <NavBarPage ID="1002" Name="Demo page" Position="End" />
      <AllUsersWebPart ID="testProvider" 
                       WebPartZoneID="Left" 
                       WebPartOrder="1">
        <![CDATA[...]]>
      </AllUsersWebPart>
    </File>
  </Module>
</Elements>

This approach allows you to deploy a custom page which has preconfigured Web Parts. One note is that you cannot use this approach to deploy new Web Parts to existing pages since you will blast the existing page out of the water (try changing demo.aspx to default.aspx and see).

Provisioning the connection

During initial development the project ran fine with just loose Web Parts. After a while the need arose for connected Web Parts as a means to show master/detail data. So the quest for a declarative approach began and quickly turned up the new WebPartConnection element on a <File>. It also turned up that no-one has actually bothered to document it yet.

Using the <WebPartConnection> you now seem to have a declarative way to define connections between Web Parts. I definitely prefer XML over code especially since it also allows me to define connections for Web Parts that I deploy as part of a sandboxed solution

Note that I do NOT mean that Web Parts who's codebase is defined within an assembly deployed as part of a sandboxed solution. But, I mean that you can deploy a Web Part to a page whose codebase is part of a normal full-trust assembly, such as all built-in Web Parts types (XsltListView, Image, etc..).

There are generally only four attributes you are interested in. The ID of the provider and the ID of the connection point within that provider. The same goes for the consumer. Here's a sample that I use for my custom testing class that you can find in the attached demo project.

<Elements xmlns="http://schemas.microsoft.com/sharepoint/">
  <Module Name="Module1">
    <File Path="Module1\default.aspx" Url="demo.aspx">
      <AllUsersWebPart ID="testProvider">...</AllUsersWebPart>
      <AllUsersWebPart ID="testConsumer">...</AllUsersWebPart>
      <WebPartConnection ID="testConnection"
                         ProviderID="testProvider"
                         ProviderConnectionPointID="providerID"
                         ConsumerID="testConsumer"
                         ConsumerConnectionPointID="consumerID" />
     </File>
  </Module>
</Elements>

Getting sexy… Including a Web Part Transformer

In my later code I want to connect a row provider to a filter consumer. Connecting these Web Parts through the browser means that you get to fill in a dialog such as the following. You can put in the field mappings between the provider and the consumer. We need to do the same using the <WebPartConnection> and luckily it allows you to do it to!

The not so sexy part is the amount of current documentation on the mystic <WebPartTransformer> element. Other than it being a descendant of the <WebPartConnection> which allows you to point to an assembly / namespace there is nothing know to the human race outside of those in possession of the SharePoint kernel (Robin, send me a copy ok?). Not even the Microsoft.SharePoint DLL itself gives a hint of this hidden jewel. It took a bit of testing but I figured out how to it works.

The <WebPartTransformer> element points to an Assembly / Namespace because it is used like a <%@Register %> directive in ASP.NET. You point to a namespace and then use ASP.NET page markup to define the transformer. Since the ASP.NET markup uses < and > tags you need to throw it all in a CDATA section. It also appears that you must use the WebPartPages control prefix to make it work as expected. Here's a small sample taken from the POC.

<WebPartConnection ID="testConnection2"
                   ProviderID="testProvider2"
                   ProviderConnectionPointID="providerIDRow"
                   ConsumerID="testConsumer2"
                   ConsumerConnectionPointID="DFWP Filter Consumer ID">
  <WebPartTransformer Assembly="Microsoft.SharePoint, ..."
                      Namespace="Microsoft.SharePoint.WebPartPages">
    <![CDATA[<WebPartPages:SPRowToParametersTransformer 
                  ConsumerFieldNames="URL" 
                  ProviderFieldNames="Test" />]]>
  </WebPartTransformer>
</WebPartConnection>

Voila. Web Parts with connections and even with transformers, all declarative and available inside the sandbox deployment model.

Hope it helps!

 

 

 

 

Bulldozing your SharePoint install

About a year ago I wrote about a PowerShell script that uninstalls all your solutions. It's great for refreshing your development laptop after an intense week of training or learning. It's also good for inflicting serious pain on your production farm would you be silly enough to run in there. I have upgraded the script a bit to make better use of SharePoint infrastructure for managing solutions (using the SharePoint Admin Service).

Here's the script V2.

Add-PSSnapin "Microsoft.SharePoint.PowerShell" -ErrorAction SilentlyContinue

$service = Get-Service SPAdminV4
if($service.Status -ne "Running")
{
    Write-Host "SharePoint Admin Service not running. Trying to start"
    try
    {
        $service.Start()
        Write-Host "SharePoint Admin Service started"
    }
    catch
    {
        Write-Host "Error starting the SharePoint Admin Service. Exiting."
        return
    }
}

$deployedSolutions = Get-SPSolution | ?{$_.Name -ne "powerpivotfarm.wsp"}
if($deployedSolutions)
{
    foreach($solution in $deployedSolutions)
    {
        if($solution.Deployed -eq $true)
        {
            Write-Host Uninstalling ($solution.Name)
            if($solution.ContainsWebApplicationResource)
            {
                $solution | Uninstall-SPSolution -AllWebApplications -Confirm:$false
            }
            else
            {
                $solution | Uninstall-SPSolution -Confirm:$false
            }
            while($solution.Deployed -eq $true)
            {
                Write-Host "Waiting for solution to uninstall" -Verbose
                Sleep 2
            }
        }
        Write-Host Deleting ($solution.Name) 
        $solution.Delete()
    }
}

   

Hope it helps!


 
 

Creating a Silverlight application for SharePoint in 10 smalls steps

In this post I will show you how to create a Silverlight application that is hosted in SharePoint. Ease and grace are the keywords of course, no funky stuff.

1. Create a SharePoint project

First you need to create a SharePoint project. You can choose most of the templates. I typically use 'Empty SharePoint Project'. I could not help but name my project SilverPoint, which sounds better that ShareLight.

2. Configure the trust level

After creating the project you will hit the SharePoint Customization Wizard. The approach in this blog post allows you to use either the sandboxed or the farm solution. I will create a farm solution since I want to deploy my Silverlight XAP file into the 14\TEMPLATE\LAYOUTS\ClientBin folder. A sandboxed solution would not be allowed to deploy files into this directory.

3. Add a Silverlight project

Next add a Silverlight Application project to your solution. I will not add any custom code to the Silverlight project at this point since we'll focus on getting the Silverlight application into SharePoint.

4. Configure the deployment site

After creating the Silverlight Application you will hit the New Silverlight Application wizard. You can choose not to host the Silverlight application in a testing web site since you will use SharePoint to host it.

5. Add a Web Part to the SharePoint project

The Silverlight application needs to be loaded onto a page in SharePoint. An easy way to achieve this is to use a Web Part. Add a normal, non-visual, Web Part item to the SharePoint project. Since this Web Part will host the DemoApp Silverlight application I chose to name my Web Part DemoAppPart.

After adding this Web Part your project should be similar to the following.

6. Configure Project Output References

In the Solution Explorer, right-click the DemoAppPart folder and choose Properties in order to show the properties of this project item. In the Properties window that appears select the Project Output References property and press the ellipsis button (…) to edit the output references. Add a new output reference and configure it with the following settings.

Deployment Type:

TemplateFile

Project Name:

DemoApp

Deployment Location:

LAYOUTS\ClientBin\<projectName>

The <projectName> in the Deployment Location is only there to reduce the chance of collisions on the server with other people's projects.

7. Delete the Web Part code

There are a few approaches to loading up the XAP that we now deploy into the ClientBin folder. You could create your own Web Part that renders out an <object> tag. However, SharePoint already ships with a Silverlight Web Part that does just that. It's called the… SilverlightWebPart. So, that means we don't have to write any code but instead can deploy this Web Part. To not deploy any code is simple. Just delete the DemoAppPart.cs file

8. Reconfigure the Web Part definition

The .webpart file points to the class that SharePoint should load when adding the Web Part to a page. Currently the .webpart file is pointing to the class that was just deleted. To rebind the .webpart file to the built-in Silverlight Web Part you change one line in the .webpart file. Change the value for the <type> element to point to the Silverlight built-in Web Part.

From

<type name="SilverPoint.DemoAppPart.DemoAppPart, $SharePoint.Project.AssemblyFullName$" />

To

<type name="Microsoft.SharePoint.WebPartPages.SilverlightWebPart, Microsoft.SharePoint, Version=14.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" />

9. Bind the XAP file

The last step is to make sure that the Web Part loads the correct XAP without the user needing to specify this. You can make use of the settings in the .webpart file to provide this configuration value.

<property name="Url" type="string">
~site/_layouts/clientbin/SilverPoint/DemoApp.xap

</property>

10. Deploy and test

Hit F5 to deploy the solution and test the new Web Part.

Yay!

1 - 10 Next

 Projects

Databinding toolkit for Word 2007Use SHIFT+ENTER to open the menu (new window).
Open XML Activities for Windows Workflow FoundationUse SHIFT+ENTER to open the menu (new window).
Package ExplorerUse SHIFT+ENTER to open the menu (new window).
Windows SharePoint Services 3 Workflow DesignersUse SHIFT+ENTER to open the menu (new window).
Word 2007 Source ViewUse SHIFT+ENTER to open the menu (new window).