Archive

Archive for the ‘Sharepoint 2010’ Category

Why do I see two copies of my Custom List Instance in a SharePoint Site?

March 13, 2013 Leave a comment

Introduction

 

Over my years in SharePoint development I have had the following issue occur.a couple of times.

Actually back in July 2010, I posted a blog entry which solved a problem with the Manage Content and Structure page which was related to duplicate lists in a site.

  • I create a custom List with a customised List Definition which uses a schema.xml to define the List Template
  • I create a Feature which uses the customised List Definition to create a new List Template with the <ListTemplate> feature element.
  • I configure the feature to create an Instance of the list using the <ListInstance> feature Xml element,
  • Activate the feature in a SharePoint Web, click Site Actions->View All Site Content.
  • Two instances of the list appear in the View All Content page, both reference the same SharePoint list.
    Figure below shows an example of two duplicate lists in the web.
    duplicatelistitemsinweb

 

I have then always wondered what causes this?

What is interesting is that one link points to one view and the other link points to a different view, this hint was the lead to help solve the issue.

 

Solution

 

I started the investigation by digging into the SharePoint databases now quick warning, “you should not read or edit the database, doing so will leave your SharePoint installation unsupported by Microsoft!”

However, I was very careful and did not make any changes to the database.

It was one of the tables that lead me to working out why I was having these duplicate links. This table was the BuildDependencies table. I performed a

SELECT TOP 1000 [SiteId]
      ,[DirName]
      ,[LeafName]
      ,[TargetDirName]
      ,[TargetLeafName]
      ,[DirectDependency]
      ,[DeleteTransactionId]
  FROM [BuildDependencies]
  Where [DirName] LIKE ‘sites/sitename%’

Looking through the results I could see that the list had two views one called ‘ByFeatures.asppx and the other ‘AllItems.aspx’

This was correct my List Schema had defined these two views and then it dawned on me, what if SharePoint is looking at the schema.xml to work out which list page to display in the View All Content page.

So I went into my schema.xml and low and behold there was an attribute on the <View> element called DefaultView. Now both the AllItems.aspx and ByFeatures.aspx had this set to TRUE.

listschema-defaultview

 

Eureka!

So to fix this I followed this process:-

  • Updated the schema.xml <View/> element for the AllItems.aspx view
  • Modified the DefaultView attribute and set it to FALSE
  • Redeployed the solution
  • Perform an IISRESET
  • Deactivate the Feature
  • Delete the list
  • Activate the Feature to create the list

Now I only see one instance of the list in the View All Content page.

However, there is a problem with this approach and that is you lose the data in the list!

 

To Fix Existing Lists with No data loss

So we need a way to fix the lists that have already been created, seeing as the existing lists are not fixed by the schema changes then these properties must have been copied into the content database.

So to fix existing lists do the following:-

  • Browse to the list and open up the List Settings page using the Ribbon
  • Create a new View call it what you want, make sure you set it to default
  • This will reset the Default View attribute on the other views and make the new view the default view.
  • Modify the view that should really be the default view and tick the make default view checkbox. (This doesnt appear if you have multiple views with the default view set).
  • Update the view
  • Delete any views that are not needed

You should now see only one list instance in the View All Site Content page!

Introducing the SharePoint Cache Refresh Framework

July 8, 2012 Leave a comment

 

Introduction

 

Although a SharePoint developer should try their best to use the tools that SharePoint provides inevitably the client will ask for something that needs some custom code! Over the last few years the customer has demanded that the code be fast, reliable and scalable.

When this happens one of the first things you start to think about is performance.  Hand in hand with performance is caching so that you can reduce the number of expensive operations.

However, when you cache data you get into scenarios where users make a change but they are not reflected immediately. The users then start complaining because the cache has become stale.

There are a few solutions:-

  • Restart IIS / OWS Timer Service to flush the cache (not practical)
  • Decrease the lifetime of the cache object (increase the number of expensive ops)
  • Use Cache Dependencies to flush the cache

The last option is the best as it supports options when data is being shared across multiple application domains however it doesn’t help when you have a number of servers in your SharePoint farm.

This is why I built the framework. The framework allows you to control the caching of objects across the SharePoint Farm.

The way it works is pretty straightforward and it comes with a small API to allow you to use it in your solutions.

 

Solution Overview

 

The framework is made of a few components:-

  • Cache Configuration SharePoint List to manage the configuration
  • Cache Configuration Refresh Timer Job to perform the cache update
  • Cache Configuration Manager – API to manage the Cache Refresh Configuration
  • Cache Refresh PowerShell Cmdlets to administrate the framework
  • Base Classes for Managing Configuration Objects

The way that the framework work is that an object is cached with a dependency to a particular file on the server’s file system. This uses .NET built in CacheDependencies which run a file watcher against the file. When the file being watched is modified a callback occurs and the cache item is removed from the HTTPRuntime.Cache.

The Cache Refresh Framework provides a method using SharePoint Timer Jobs to run a process which modifies these files across all SharePoint Servers in a farm. This flushes the object from the Cache on each of the servers in the farm so that next time they load the object it is loaded from the Data Access Layer / Storage Mechanism rather than the Cache.

The framework supports multiple cache profiles so that you can group objects to be refreshed together or target them differently.

The following section explains some usages and the process in more detail.

 

Usage

 

The framework can be used to allow caching of objects such as:-

  • Configuration items
  • Navigation items
  • XML elements
  • Plain Old C# Objects (POCO)
  • Data Transfer objects (DTOs)

A common example is:-

  • A user of the system makes a change to the configuration.
  • The SharePoint Application calls into the Cache Refresh Framework tell it to refresh a particular Cache Configuration
  • The Cache Refresh Framework gets the Cache Configuration and runs the timer job for that configuration on all servers in the SharePoint farm using the SharePoint Farm Timer Service.
  • Each server runs the actual job which modifies a file
  • The Cache Dependency picks up the change to the file and flushes the cache
  • The next time the application gets that object it get its from the data access layer rather than the cache.

SharePoint Cache Refresh Framework Diagram

 

 

Deployment, Configuration, How To Examples

 

The framework has been uploaded to Codeplex as the SharePoint Cache Refresh Framework Project and there are a number of guides which cover:-

These can be found in the Documentation Section

 

Finally

 

Currently the framework is an alpha release, so there might be some issues with it, so please don’t try it on your production environment without plenty of testing. There are some known issues and I will look to improve the framework and fix those issues as they are found. However, I am excited about getting the framework out there and getting feedback on it.

If you have any problems, or find bugs then report them on the SharePoint Cache Refresh Framework site using the Issue Tracker forum.

If you have any ideas for additional functionality then please add a Discussion item.

Finally, please let me know if you find it useful and how you have used it!

Thanks

Simon

Content Subscriber Timer Job Error “A content type failed to be syndicated: System.Xml.Schema.XmlSchemaValidationException”

July 2, 2012 Leave a comment

Introduction

We are using SharePoint’s Managed Metadata Service Application’s Content Type Hub model to manage the Content Types and Site Columns.

I’d highly recommend the following Technet Article for more information, Plan to share terminology and content types

Anyway, the approach to adding new metadata to the Content Types is using Feature Upgrading which has been interesting and has caused a few problems, which I have blogged about in the past.

Whilst researching the different options for the upgrade process I stumbled over a problem when using PowerShell to add a field to the Site Collection. This problem really only appears when you are using the Field within a Content Type that is being published to other site collections as part of a Content Type Hub.

The PowerShell worked and the Site Column was successfully created using the method. SPFieldCollection.AddFieldAsXml() function. However, when it came to pushing the changes out to the other site collections using the Managed Metadata’s Content Type Subscriber timer job the following errors were logged to the SharePoint ULS Log:-

  • “The element ‘FieldTemplate’ in namespace ‘urn:deployment-manifest-schema’ has invalid child element ‘Field’ in namespace ‘http://schemas.microsoft.com/sharepoint/’. List of possible elements expected: ‘Field’ in namespace ‘urn:deployment-manifest-schema’.”
  • “Received an error message from import: The element ‘FieldTemplate’ in namespace ‘urn:deployment-manifest-schema’ has invalid child element ‘Field’ in namespace ‘http://schemas.microsoft.com/sharepoint/’. List of possible elements expected: ‘Field’ in namespace ‘urn:deployment-manifest-schema’.. The recommendation is:”
  • “A content type failed to be syndicated: System.Xml.Schema.XmlSchemaValidationException: The element ‘FieldTemplate’ in namespace ‘urn:deployment-manifest-schema’ has invalid child element ‘Field’ in namespace ‘http://schemas.microsoft.com/sharepoint/’. List of possible elements expected: ‘Field’ in namespace ‘urn:deployment-manifest-schema’.    “

Investigation

The investigation started by looking at the process of adding the field to SharePoint.

The process being used is as follows:-

  • Load a SharePoint Elements file which has fields defined in it.
  • An example of the element.xml file is shown below
<Elements xmlns="http://schemas.microsoft.com/sharepoint/">

<Field ID="{38384FAD-5BF2-42D6-9243-5BE95F17E5FD}" Type="Text" Name="ITSPFieldName" StaticName="ITSPFieldName" DisplayName="iThink SharePoint Field" Description="Field does something" Group="iThink SharePoint Site Columns" />

</Elements>

 
  • Load the file into PowerShell using the Get-Content Cmdlet
  • Get a reference to the Content Type Hub using Get-SPSite
  • Get the <Field /> element
  • Add a field using the <Field />element and the Site Collection’s Root Web Fields property and AddFieldAsXml() function

Here is a snippet of the PowerShell script that was being executed to do the above:-

$contenttypehub = Get-SPSite -Identity http://sharepoint/hub;
[xml]$elementFile = Get-Content .\myelement.xml;
$fieldXml = $elementFile.Elements.Field[0];
$addedFieldName = $contenttypehub.RootWeb.Fields.AddFieldAsXml($fieldXml.OuterXml);
if($addedFieldName -ne $null)
{
Write-Host "Added Field with InternalFieldName: " $addedFieldName;
}
else {
Write-Warning "Failed to Add Field with Xml: " $fieldXml.OuterXml;
}

Once the script has run then the field is created and is available for assigning to the Content Type. The field is added to the Content Type successfully. However as mentioned previously when the Content Type Subscriber Hub Timer job is run then the errors are displayed about the Field’s SchemaXml .

So what’s going wrong?

Well after examining the Field’s SchemaXml property, I could see the issue.

The field’s schema was displayed using the following script:-

$fieldName = "FOSScannedDocumentId";
$contenttypehub = Get-SPSite -Identity http://sharepoint/hub;
$checkField = $contenttypehub.RootWeb.Fields | ?{$_.InternalName -like $fieldName};
$checkField.SchemaXml;

The output of the command showed the Field’s Schema Xml had an added Element as shown below:-


<Field ID="{38384FAD-5BF2-42D6-9243-5BE95F17E5FD}" Type="Text" Name="ITSPFieldName" StaticName="ITSPFieldName" DisplayName="iThink SharePoint Field" Description="Field does something" Group="iThink SharePoint Site Columns"  xmlns="
http://schemas.microsoft.com/sharepoint/" />

So what was happening, well PowerShell is being well behaved and adding the namespace attribute from the parent <Elements> node to this child node. Unfortunately SharePoint is not expecting this additional attribute as part of the Field’s SchemaXml and it causes the validation of the Xml to fail. Hence the XmlSchemaValidationException.

Solution

The solution was to modify the string being passed into the AddFieldFromXml() function.

This was achieved by modifying the script to remove the xmlns attribute :-


$removeNamespaceString = 'xmlns="http://schemas.microsoft.com/sharepoint/"';
[xml]$elementFile = Get-Content .\myelement.xml;
$fieldXml = $elementFile.Elements.Field[0];
$fieldXmlString = $fieldXml.OuterXml.Replace($removeNamespaceString, "");
$addedFieldName = $contenttypehub.RootWeb.Fields.AddFieldAsXml($fieldXmlString);

This script will find the string with attribute name of xmlns and replace it with a blank string.

Now, when the Field is added using this fixed version of the <Field/> element the Content Type Subscription timer job completes successfully!

Querying for Feature Upgrades error: The site with id cannot be found

June 20, 2012 4 comments

Introduction

I am involved in a large project which is creating a large number of SharePoint webs. The webs content and configuration are being modified using Features and Feature Upgrades.

We are using PowerShell to process the Feature Upgrades using Chris O’Brien’s excellent SharePoint Feature Upgrade Kit.

One of the issues that we started to see during testing was when looking for Features which are scoped at the Site Collection using the SPWebApplication object’s QueryFeatures(SPFeatureScope, Boolean) function.

The following PowerShell was being used:-

$webapp = Get-SPWebApplication http://dev.itsp.local;
$webapp.QueryFeatures("Site",$true);

When this code was run in SharePoint 2010 Management Console the following error was displayed.

An error occurred while enumerating through a collection:
The site with the id f6f2e2bb-46bf-4c46-995e-65055512114e could not be found..
At line:1 char:22 + $webapp.QueryFeatures &amp;amp;lt;&amp;amp;lt;&amp;amp;lt;&amp;amp;lt; (&amp;quot;Site&amp;quot;,$true); + CategoryInfo
: InvalidOperation: (Microsoft.Share...esultCollection:SPFeatureQueryResultCollection) [],
RuntimeException + FullyQualifiedErrorId : BadEnumeration

Investigation

Investigation started by looking at whether this error could be reproduced on other SharePoint environments which it could. Further testing was performed using different SharePoint builds including SharePoint 2010 Service Pack 1 and Cumulative Updates from June 2011 to December 2011.

The cause of the error seems to be when you have a site collection that has been deleted from SharePoint but had a feature that needs to be upgraded.

Looking in the Content Database for the Web Application revealed a entry in the AllSites table which looked like this:-

contentdb_deletedsiteentry

Reminder: Accessing the SharePoint databases is not supported by Microsoft and should not be performed in a production environment.

The row in the database has a column called Deleted which has a status of 1.

Using the Get-SPSite cmdlet the Site Collection could not be found. However, a colleague reminded me that there is a Get-SPDeletedSite. This returns back site collections that are found in the site collection recycle bin. The command returned a site collections that had been deleted a few weeks ago.

There is a function, Remove-SPDeletedSite but while this removes the site collection so it cannot be accessed via Get-SPDeletedSite, the error still occurs and the record is still found in the Content Database.

The issue seems to be down to the way that the SPWebApplication.QueryFeatures function works and does not filter the site collections which have been deleted and hence the error occurs.

Solution

Currently there is no fix for this issue that I am aware of. However, all is not lost and a workaround was possible by a few additional lines of PowerShell.

$webapp = Get-SPWebApplication http://dev.itsp.local;
$webapp.Sites | ForEach-Object {$queryFeatureResults += $_.QueryFeatures("Site",$true)};

This PowerShell command will enumerate through all the SPSite in the Web Application and call the same function but on each Site Collection. This gets around the problem with the QueryFeature() function finding the deleted site collection.

queryfeature-foreach-withresult

Save typing when Manipulating SharePoint Solution Files in PowerShell

December 6, 2011 5 comments

 

Introduction

 

One of the things that annoyed me with PowerShell and SharePoint are the following commands:-

  • Add-SPSolution
  • Update-SPSolution
  • Actually anything that requires a –LiteralPath parameter

Don’t get me wrong I think that using PowerShell to admin SharePoint is fantastic but these commands bug me because they require a full path to work correctly. Unfortunately you don’t seem to be able to use the full stop (or period) to represent the current directory.

So you cannot do something like this:-

Add-SPSolution .\mysharepoint.wsp;

Instead you need to do this:-

Add-SPSolution c:\thisisareallylongpath\release1\section2\mysharepoint.wsp

Solution

Anyway, that got me thinking surely there is a better way and I can save myself some typing.

The solution is to use the command Get-Location.

So instead you can do this:-

$curdir = Get-Location;
Add-SPSolution–LiteralPath $curdir”\mysharepoint.wsp”;

Actually there is a PowerShell Alias called gl which is a shortcut for the Get-Location command.

So the shortest version in terms of saving your typing fingers is this:-

$curdir = gl;
Add-SPSolution –LiteralPath $curdir”\mysharepoint.wsp”;

Really hope that helps save you some time, also love to hear any other alternatives, there is bound to be an even better way of doing this.

Introducing SPUrlExpressionBuilder to resolve SharePoint URL Tokens

November 29, 2011 Leave a comment

Introduction

One of the great things when developing with SharePoint is being able to use URL tokens such as:-

  • ~SiteCollection – this will resolve to the current site collection root
  • ~Site – this will resolve to the current web root

For an extensive list of SharePoint URL tokens, take a look at Namwar Rizvi’s SharePoint Insight blog post, http://sharepoint-insight.com/2008/12/01/list-of-sharepoint-url-tokens/.

If you have done much with creating or modifying Master Pages or Page Layouts then these tokens become very useful to locate resources such as images, XSL or CSS files.

For example, to reference an image which is stored in a SharePoint Publishing web’s Site Collection Images folder you could use something like this:-

~SiteCollection/SiteCollectionImages/myimage.png.

Recently, I have been working with multiple language user interfaces and wanted to be able to display a different image based on the language. One of the steps to do this was to work out how to process these URL Tokens.

Solution

This is where the SPUrlExpressionBuilder class comes to the rescue. This class is part of the Microsoft.SharePoint.Publishing.WebControls assembly.

To evaluate a string with a url token like ~SiteCollectionUrl/Images/MyImage.png you can use the following SPUrlExpressionBuilder class’s method EvaluateUrlExpression().

string imagePath = SPUrlExpressionBuilder.EvaluateUrlExpression("~SiteCollection/Images/myimage.png").ToString();

 

Visual Studio Tip: Using SharePoint Site Url in Pre-Deployment and Post-Deployment scripts.

October 14, 2011 2 comments

Within Visual Studio 2010 SharePoint projects you might want to use the SharePoint Site Url that you have specified for your SharePoint project in Pre or Post Deployment scripts.

The SharePoint Site Url value can be retrieved using the $(SharePointSiteUrl) variable.

Usage

For example, this variable could be used in a pre-deployment script to deactivate certain features for the debug configuration.

To add the Pre Deployment script do the following:-

  • From Visual Studio 2010
  • Open your SharePoint Solution/Project
  • Click Project Properties
  • Click the SharePoint Tab
  • Add the following script to the Pre Deployment Script text box.
echo SiteUrl: $(SharePointSiteUrl)
if "$(ConfigurationName)" == "Debug" (
stsadm -o deactivatefeature -name "Feature1" -url $(SharePointSiteUrl) -force
stsadm -o deactivatefeature -name "Feature2" -url $(SharePointSiteUrl) -force
stsadm -o deactivatefeature -name "Feature3" -url $(SharePointSiteUrl) -force
stsadm -o deactivatefeature -name "Feature4" -url $(SharePointSiteUrl) -force
stsadm -o deactivatefeature -name "Feature5" -url $(SharePointSiteUrl) -force
)

Hope that helps.

For more information on Pre and Post-Deployment steps see this MSDN Link:

How to: Set SharePoint Deployment Commands (http://msdn.microsoft.com/en-us/library/ee231534.aspx)

 

U4FVW5JMFNEH

%d bloggers like this: