Monday, May 31, 2010

SharePoint 2010: The current page has been customized from its template. Revert to template.

The annoying warning ‘The current page has been customized from its template. Revert to template’ comes up in page when a page is customized . For example you have created a page mypage.aspx with master page ‘default.master’. Now if you change the master page to custom.master then you will find the message ‘The current page has been customized from its template. Revert to template’. If you make any change to the page then the page will be customized and you will find a message. I think by myself that the message is pretty much annoying and  concerning to any SharePoint developer/administrator. Till now there’s no known settings to stop the message.

 

First Solution (extreme solution):

The first solution I have found in sharepoint forum. The solution is to comment out the section in master page which shows the message. As per the solution, find the following section in master page and comment it out.
<div id="s4-statusbarcontainer">
    <div id="pageStatusBar" class="s4-status-s1">
    </div>
</div>

So the solution in this case to hide div permanently from the master page. But the problem here might be that if the same div is used to show another useful message then user will not find the message.

 

Second Solution (soft solution):

Another solution might be not to remove the div from master page. Rather to hide/show the message on the client side on page load. Remember the default master page is V4.master, so in case of default master page, use V4.master instead of Default.master. The logic is:
  1. set the div’s visibility to ‘none’ as shown below. So the div is not visible by default
    <div id="s4-statusbarcontainer" style="display:none">
        <div id="pageStatusBar" class="s4-status-s1">
        </div>
    </div>
  2. Run a script on page load which will check the message inside the div. And based on the message the div will be visible or not. I have put the following script in the master page’s head section. The script check if the display message is not ‘The current page has been customized..’ and if not so then display the message:
    <head>
    ...........................
    
    <script type="text/javascript">
    ExecuteOrDelayUntilScriptLoaded(hideWarning, "sp.js");
    function hideWarning() {
        var statusbarContainer = document.getElementById('s4-statusbarcontainer');
        if (statusbarContainer != null) {    
            var messageSpan = document.getElementById('status_1_body');
            if (messageSpan != null) {
                if (messageSpan.innerHTML.indexOf('The current page has been 
                                  customized from its template.') == -1)
                    statusbarContainer.style.display = 'inline';
            }
        }
    }
    </script>
    </head>
    In the above code snippet, the method ‘ExecuteOrDelayUntilScriptLoaded’ ensures that the method hideWarning is not invoked until the base SharePoint JavaScript file sp.js is loaded.

My final judgment is that SharePoint should provide a settings from site collection/web level to enable/disable the warning. sometimes admin wants to accept the warning but don’t want to show it to end users. Hope some SharePoint team will heed into this. Till that day we, sharepoint developer, need to find a way out. Hope someone out there will get a better idea.

Monday, May 17, 2010

SharePoint 2010: Add/Delete/update/search list items with Managed Client Object Model

Managed client Object model is a rich extension to SharePoint 2010. You can almost perform all kinds operations against SharePoint using Client OM. In this post I’ll show you how to use Managed client Object Model (OM) to manipulate list items. The code snippet I’ll use in the examples below is depend on a product list. The product list has four fields: Product Name, Product Description, Product launch date, available quantity. The product list is represented with a class as shown below:

public class Product
{
    public string ProductName { get; set; }
    public int ProductID { get; set; }
    public string ProductDescription { get; set; }
    public DateTime LaunchDate { get; set; }
    public int AvailableQuantity { get; set; }
}

Add new list item

To add a new item in a list you may or may not need to pass ListItemCreationInformation.  Let me explain when you need to pass ListItemCreationInformation or when not:

  • If you need to add item at the root (not under a subfolder) then you can ignore ListItemCreationInformation by passing null in place of ListItemCreationInformation.
  • If you need to add item somewhere inside subfolder then you need to create an instance of ListItemCreationInformation and set it’s Folderurl to url of the folder you want to save the list item.

The code snippet below add a new list item (Product item in my case):

public void AddNewProduct(string siteUrl, string folderPath, Product product)
{
    const string listName = "Product";
    using (var clientContext = new ClientContext(siteUrl))
    {
        var list = clientContext.Web.Lists.GetByTitle("Product");

        ListItemCreationInformation listItemCreationInformation = null;
        if (!string.IsNullOrEmpty(folderPath))
        {
            listItemCreationInformation = new ListItemCreationInformation();
            listItemCreationInformation.FolderUrl = string.Format("{0}/lists/{1}/{2}", siteUrl, listName, folderPath);
        }

        var listItem = list.AddItem(listItemCreationInformation);
        listItem["ProductName"] = product.ProductName;
        listItem["ProductDescription"] = product.ProductDescription;
        listItem["LaunchDate"] = product.LaunchDate;
        listItem["AvailableQuantity"] = product.AvailableQuantity;
        listItem.Update();
        clientContext.ExecuteQuery();

    }
}

The method in above code snippet takes a site url  and optional folder url and a product. If you want to add item in the root folder then you can pass folderPath parameter empty or null in the above method. Depending on whether you have passed folderPath or not, the ListItemCreationInformation will be initialized or not. If you don’t pass folderPath, the ListItemCreationInformation variable will be null. but if you want to add item in a specific subfolder then pass the folder name as parameter and the ListItemCreationInformation will be initialized and teh FolderUrl of the instance will be set with parameter folderaPath.

Delete list item

In the code snippet below, I have used the same product list. I have passed the product Id as parameter and the get the list item by id. Once I get the list item, I have invoked the DeleteObject method of the list item.

public void DeleteProduct(string siteUrl, int productId)
{
    using (var clientContext = new ClientContext(siteUrl))
    {
        var list = clientContext.Web.Lists.GetByTitle("Product");
        var product = list.GetItemById(productId);
        product.DeleteObject();
        clientContext.ExecuteQuery();
    }
}

Update List Item

The following code snippet shows how to update a product list.

public void UpdateProduct(string siteUrl, Product product)
{
    using (var clientContext = new ClientContext(siteUrl))
    {
        var list = clientContext.Web.Lists.GetByTitle("Product");
        var productToModify = list.GetItemById(product.ProductID);
        productToModify["ProductName"] = product.ProductName;
        productToModify["ProductDescription"] = product.ProductDescription;
        productToModify["LaunchDate"] = product.LaunchDate;
        productToModify["AvailableQuantity"] = product.AvailableQuantity;
        productToModify.Update();
        clientContext.ExecuteQuery();
    }
}

Get a single List Item

To get a lsit item you need to specify the fields you want to retrieve from the list item.

public Product GetProductById(string siteUrl, int productId)
{
    Product product = null;
    try
    {

        using (var clientContext = new ClientContext(siteUrl))
        {
            var list = clientContext.Web.Lists.GetByTitle("Product");
            var productItem = list.GetItemById(productId);
            clientContext.Load(productItem, pi => pi.Id, pi => pi["ProductName"], pi => pi["ProductDescription"], pi => pi["AvailableQuantity"], pi => pi["LaunchDate"]);
            clientContext.ExecuteQuery();
            product = new Product();
            product.AvailableQuantity = Convert.ToInt32(productItem["AvailableQuantity"]);
            product.LaunchDate = Convert.ToDateTime(productItem["LaunchDate"]);
            product.ProductDescription = productItem["ProductDescription"].ToString();
            product.ProductID = productItem.Id;
            product.ProductName = productItem["ProductName"].ToString();
        }
    }
    catch (Exception exception)
    {
        Console.WriteLine(exception.Message);

    }
    return product;
}

As shown in the example below, the field values I like to retrieve are passed in the ClientContext.Load method. If you want to retrive all fields (which is not recommended) then call the Load method with the list item, as shown below:

clientContext.Load(productItem);

Get Collection of List Items

To get a list of items as per any condition, you can use CAML  query (or in Linq to SharePoint extension). I’ve covered in another post on how to use Linq to SharePoint. One important point to notice here in the code snippet below is that if you want to look for items inside subfolders thenyou need to add an extra attribute Scope=’RecursiveAll’ in view tag.

public IList<Product> FindProductsByName(string siteUrl, string productName, bool includeSubfolder)
{
    IList<Product> products = new List<Product>();
    try
    {
        string scope = string.Empty;
        if (includeSubfolder)
        {
            scope = "Scope='RecursiveAll'";
        }
        

        using (var clientContext = new ClientContext(siteUrl))
        {
            List list = clientContext.Web.Lists.GetByTitle("Product");
            CamlQuery query = new CamlQuery();
            query.ViewXml = string.Format(@"<View {0}>
                                <Query>
                                    <Where>
                                    <Contains>
                                        <FieldRef Name='ProductName'/>
                                        <Value Type='Text'>{1}</Value>
                                    </Contains>
                                    </Where>
                                </Query>
                                </View>", scope, productName);
            ListItemCollection listItems = list.GetItems(query);
            clientContext.Load(listItems, li => li.Include(pi => pi.Id, pi => pi["ProductName"], pi => pi["ProductDescription"], pi => pi["AvailableQuantity"], pi => pi["LaunchDate"]));
            clientContext.ExecuteQuery();

            foreach (var productItem in listItems)
            {
                var product = new Product();
                product.AvailableQuantity = Convert.ToInt32(productItem["AvailableQuantity"]);
                product.LaunchDate = Convert.ToDateTime(productItem["LaunchDate"]);
                product.ProductDescription = productItem["ProductDescription"].ToString();
                product.ProductID = productItem.Id;
                product.ProductName = productItem["ProductName"].ToString();
                products.Add(product);
            }
        }
    }
    catch (Exception exception)
    {
        Console.WriteLine(exception.Message);

    }
    return products;
}

You can notice that I have passed the fields I want to load as per the query result in ClientContext.Load’s li.Include extension method. If you want to load all properties then you can call the Load method in a way as shown below:

clientContext.Load(listItems, li => li);

 

If you don’t specify a field to load but try to access it then you will get an exception of type ‘PropertyOrFieldNotInitializedException’ with the following message:

The property or field has not been initialized. It has not been requested or the request has not been executed. It may need to be explicitly requested.

Friday, May 14, 2010

Linq to SharePoint

SharePoint 2010 has added new Linq extension called Linq-to-SharePoint similar like Linq-to-Sql. In Linq to Sql, when you Visual Studio generate classes based on your database schema, under the hood a tool called SqlMetal is used. Though VS generates classes for you, you can use SqlMetal outside of VS for your own purpose. Linq to SharePoint is new extension which allows to generate DataContext (having classes representing lists) based on your sharepoint lists using SPMetal and you can use the DataContext for manipulating SharePoint list in an object-oriented fashion. So you don’t need to worry about CAML or SharePoint Object Model. The steps to work with Linq-to-SharePoint is easy. Let’s dig it deeper.

  1. Generate Linq-to-SharePoint DataContext class: To use Linq to SharePoint you need to use SPMetal to generate Linq-To-SharePoint class. You can find the SPMetal in the location “C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\14\BIN”. You can run the command from command prompt. For example the following command will generate Linq-to-SharePoint DataContext class for site ‘http://localhost’ and put the code in C:\MyClass.cs file with namespace MyNameSpace.

    spmetal /web:http://localhost /code:c:\myclass.cs /namespace:mynamespace

    One thing to point here is that there are Visual Studio extension availa to enable developers to generate DataContext from Visual Studio. One such tool is Linq to SharePoint DSL Extension.
  2. Add DataContext class to your Visual Studio Project: The file you have generated at step 1 need to add in your Visual Studio Project. To do so you need to add reference to Microsoft.SharePoint.Linq.dll from Visual Studio’s Add Reference windows’ ‘.NET’ tab.
  3. Code Using DataContext Class: Now you can use the DataContext class for manipulating SharePoint lists. For example in the following code I have used the DataContext class generated at step 1 to add a new product in the product list.
    using (var context = new MyclassDataContext(http://mysite))
    {
        var item = new ProductItem();
        item.AvaialableQuantity = 100;
        item.LaunchDate = DateTime.Now;
        item.ProductDescription = "this is computer monitor";
        item.ProductName = "Monitor";
        context.Product.InsertOnSubmit(item);
        context.SubmitChanges();  
    }
  4. Suggestion: If you use SPMetal to generate DataContext class then you’ll find that all classes are placed in a single file (in my case MyClass.cs file). This is very difficult to manage and modify. My suggestion will be to modify the file to move classes in individual pages. You can use some Refactoring tools like Resharper.

CAML and Linq side-by-side

You may think CAML is dead now as we can do all operations using Linq to SharePoint. Wait, here few point to notice. Firstly, when you use Linq to SharePoint, under the hood, CAML is used. the Linq to SharePoint convert you expression in CAML. However, you can still use CAML for retriving data from database, then you can use Linq to do operations on returned results. For example, you can use CAML to find products. Then you can run linq query against the result set to perform operations like orderby, group, join etc. As shown in the example below, I have used Linq to SharePoint to query Product list to find items whose name contains monitor and also ordered by available quantity.

using (var context = new MyclassDataContext("http://mysite"))
{
    var proudcts = from p in context.Product
                    where p.ProductName.Contains("monitor")
                    orderby p.AvaialableQuantity
                    select p;
}

In the following example, I have used CAML query to perform the same operation I have performed above. In the above example I have used Linq to SharePoint extension fully. But in the following example I have used CAML query first to filter data from database. Then I have run Linq query to order data. The following example doesn’t use Linq to SharePoint. Rather it uses the conventional CAML and C# Linq.

SPList productList = SPContext.Current.Web.Lists["Product"];
SPQuery camlQuery=new SPQuery();
camlQuery.Query = "your CAMl query";

var products = productList.GetItems(camlQuery);
var orderProducts = from p in products.Cast<SPListItem>()
                where p["ProductName"].ToString().Contains("monitor")
                orderby Convert.ToInt32(p["AvaialableQuantity"])
                select p;
 

An Exception you may get:

You may find the following exception when you try to run an application in SharePoint server. At first glance you may think the site is not accessible or you have misspelled the site name. But the real fact is that if you try to run your application in 32 bit mode then you may get the exception.

The Web application at http://localhost could not be found. Verify that you have typed the URL correctly. If the URL should be serving existing content, the system administrator may need to add a new request URL mapping to the intended application.

Handy tools for Linq to SharePoint

SharePoint 2010 is not out there for too long. But there are much activities to help developers to easy development/deployment. I have found few codeplex projects aimed at easing development,deployment and more. I have found few Visual Studio extensions for SharePoint in MSDN Visual Studio gallery. The major problem we face in SharePoint development is that we need to deploy our code to test in development environment. VS 2010 has added nice extension already for developer to ease and fast development/deployment. But few VS extensions developed by others may add extra value to SharePoint developer’s life. Here are few useful links SharePoint developers may find handy.

Linq to SharePoint DSL Extension

CKS For SharePoint Server

SharePoint Developer Tool

Linq to SharePoint limitations

With Linq to SharePoint you can’t run all kinds of queries. There some kind of queries which is inefficient. For example if you join two lists in such a way that for each item in first list, you need to go to database for finding matching items in second list then the query is inefficient and not supported in Linq to SharePoint. You can find more details on this on the following link:

http://msdn.microsoft.com/en-us/library/ee536585%28office.14%29.aspx

Tuesday, May 11, 2010

SharePoint 2010 Deployment: Powershell Script

Pre-SharePoint 2010 developers are familiar with Stsadm command. The general scenario of SharePoint 2007 deployment is to develop a batch file with stsamd commands. A generic deployment includes the following steps:
  • Deactivate Features
  • Uninstall Features
  • Retract Solution
  • Delete Solution
  • Add Solution
  • Deploy Solution
  • Install Features
  • Activate Features

SharePoint 2007 Deployment Script:

I’ll first describe how stsadm command file looks like implementing the above steps. You can put the following script in a batch file and then clicking on the batch file in SharePoint server, will deploy the solution. The solution and the batch file need  to be in the same folder. The first line of the script (cd /d %~dp0) will change the current directory to the script directory.
--Change script directory to current directory 
cd /d %~dp0 
@SET STSADM="c:\program files\common files\microsoft shared\web server extensions\12\bin\stsadm" 
@SET SITEURL="http://localhost" 

echo Deativating 'MyFeature' feature. 
%stsadm% -o deactivatefeature -name MyFeature -url %SITEURL% -force  
echo Uninstalling 'MyFeature' feature. 
%stsadm% -o uninstallfeature -name MyFeature -force  

echo Retracting solution 'MySolution.wsp' 
%stsadm% -o retractsolution -name MySolution.wsp -immediate -allcontenturls %stsadm% -o execadmsvcjobs  
echo deleting solution 'MySolution.wsp' 
%stsadm% -o deletesolution -name MySolution.wsp -override  

echo adding solution 'MySolution.wsp'
%stsadm% -o addsolution -filename MySolution.wsp  
echo deploying solution 'MySolution.wsp' 
%stsadm% -o deploysolution -name MySolution.wsp -url %SITEURL% -immediate -allowGacDeployment -force 
%stsadm% -o execadmsvcjobs 
 
echo Installing 'MyFeature' feature. 
%stsadm% -o installfeature -name MyFeature -force  
echo activating 'MyFeature' feature. 
%stsadm% -o activatefeature -name MyFeature -url %SITEURL% -force  
iisreset /restart /noforce /timeout:60 
File: SharePoint 2007 Script for Deployment

PowerShell Scripting Basic, every SharePoint Developer Should Know

In SharePoint 2010 stsadm is supported but powershell commands are recommended to use. To know how to run SharePoint powershell script, let’s get an overview of PowerShell. I’ll try to provide a gist on Powershell so that you can write your own Script for SharePoint. As as SharePoint developer we don’t need to be expert in PowerShell script but we need to know the basic syntax.
 PowerShell command format: Powershell command has two parts: verb and noun. For example, to get current date, you need to execute command get-date. Here get is verb then a hyphen(-) and finally date which is noun. Powershell is not case sensitive. But its good practice to use Caml case in command. The following command uses verb-noun format to get current date.
Get-Date
Get Help on PowerShell Command: To get help for a command you can use Get-Help command. The following command is used to get help on Get-Date:
Get-Help Get-Date
You can even type the verb part including hyphen and then press tab. You’ll then get the all commands starting with the verb.
PowerShell command execution Permission: Before you execute any command, you need to enable PowerShell to execute command. You can get the current execution policy by running the following command:
Get-ExecutionPolicy
The result of the command might be one of the followings:
  • Restricted
  • AllSigned
  • RemoteSigned
  • Unrestricted
  • Bypass
  • Undefined
To execute command or run scripts, you can set execution policy to ReomteSigned but based on your security consideration, you can use different options. To set execution policy, you can run the following command:
Set-ExecutionPolicy RemoteSigned
Run a PowerShell Script: To run a PowerShell script, you need put the file name in the PowerShell command prompt. But there are few conventions/restrictions that you need to follow.
  • To run a script file you need to type complete path of the script file. The complete path may be in the form ‘.\folder\subfolder\script.ps1’ or a full path like ‘c:\folder\subfolder\script.ps1’
  • To execute a script you need to use the format of & ScriptPath format. If the file path has space then use double quotation to enclose the path. So to execute a file you can use the command like below:
& “C:\My Scripts\Script.ps1”
  • If you want to run PowerShell script from Run window then you can do so by putting the following command in Run window:
Powershell –NoExit & ‘C:\My Scripts\Scripts.ps1’
One thing to remember in the above script is that single quote is used instead of double quote when you will run the above command from Run window. Single quote must be used for file path if the file path has space. Double quote will not work in this case.
  • Variables in PowerShell are identified by putting a  $ prefix. You’ll find how the variable is used in the section “A Sample PowerShell Script”
  • PowerShell script file is saved with extension .ps1
A Sample PowerShell Script:
Let’s say you have a PowerShell script (as shown below) in a file named script.ps1. Now You want to run the following powershell script (in a file Script.ps1) from Run window. The script will add two numbers and print the output.
echo 'setting a value for a'
$a=5
echo 'setting a value for a'
$b=3
echo 'adding a and b'
$c=$a+$b
echo "reslut is $c"


The variables in the above script are prefixed by $. Take a close look at the last echo. The echo has a $c in the double quotation. Remember, you can refer a variable name in double quotation string (as in the last echo in the above script). But the same is not true for single quote. If you would use the $c inside single quote then it would print back the $c. Single quote is considered as literal string in PowerShell.

SharePoint 2010 Deployment

In SharePoint 2010, you can use PowerShell script for deploying SharePoint solution/features. Let’s first take a look at how the deployment script will look like
PowerShell Deployment Script: Deployment in SharePoint 2010 still has the same eight steps (Deactivate Features, Uninstall Features…..) as described at the beginning of this post. The following script deploy a solution:
function WaitForJobToFinish([string]$SolutionFileName)
{ 
    $JobName = "*solution-deployment*$SolutionFileName*"
    $job = Get-SPTimerJob | ?{ $_.Name -like $JobName }
    if ($job -eq $null) 
    {
        Write-Host 'Timer job not found'
    }
    else
    {
        $JobFullName = $job.Name
        Write-Host -NoNewLine "Waiting to finish job $JobFullName"
        
        while ((Get-SPTimerJob $JobFullName) -ne $null) 
        {
            Write-Host -NoNewLine .
            Start-Sleep -Seconds 2
        }
        Write-Host  "Finished waiting for job.."
    }
}

Add-PsSnapin Microsoft.SharePoint.PowerShell
 
$CurrentDir=$args[0]
$solutionName="Limeco.UI.WebParts.wsp"
$SolutionPath=$CurrentDir + "\"+$solutionName 
 
Write-Host 'Going to disable feature'
disable-spfeature -identity Limeco.UI.WebParts_LimecoWebPartFeature -confirm:$false -url http://localhost
 
Write-Host 'Going to uninstall feature'
uninstall-spfeature -identity Limeco.UI.WebParts_LimecoWebPartFeature -confirm:$false -force
 
Write-Host 'Going to uninstall solution'
Uninstall-SPSolution -identity $solutionName  -allwebapplications -confirm:$false

Write-Host 'Waiting for job to finish'
WaitForJobToFinish 

Write-Host 'Going to remove solution'
Remove-SPSolution –identity $solutionName -confirm:$false
 
Write-Host 'Going to add solution'
Add-SPSolution $SolutionPath
 
Write-Host 'Going to install solution to all web applications'
Install-SPSolution –identity $solutionName –Allwebapplications –GACDeployment

Write-Host 'Waiting for job to finish' 
WaitForJobToFinish 

Write-Host 'Going to enable Feature' 
Enable-spfeature -identity Limeco.UI.WebParts_LimecoWebPartFeature -confirm:$false -url http://localhost 

Remove-PsSnapin Microsoft.SharePoint.PowerShell
File: Myscript.ps1

The first thing in the above script is a function WaitForJobToFinish which is used to make sure jobs are finished executing before moving on. This method is similar like the command ‘stsadm –o execadmsvcjobs’ in SharePoint 2007. In the above script, the line ‘Add-PSSnapin’load the SharePoint PowerShell script. If you already using SharePoint 2010 Management Shell (Which is a PowerShell extension already) then this line should be removed. In the above script Write-Host is just like print function that print a string in the console. FYI, when you pass arguments to an PowerShell script, the arguments are kept in a PowerShell variable $Args. You can access any arguments by assessing it $Args[index]. I think the command in the above script is self-explanatory. The –confirm:$false is for not to prompt user for confirmation. In the above script you need to pass the solution directory.
Automate the Deployment Script: To automate the powershell Script you need to put the above script in a PowerShell scipt file(having ps1 extension). Let’s say you have you script in a file named as myscript.ps1. Now you need to run the script you need a batch file which will execute the script file. The script file may be like one shown below:
cd /d %~dp0
powershell -noexit -file    ".\MyScript.ps1" "%CD%"

 File: MyCommand.bat
In the above command, the first line change the current directory to the location from where the batch file is run. Then I have run the PowerShell with the MyScript.ps1 file and passed the current directory as argument (%CD%)

Conclusion

I think stsadm command was simple and easy to use. PowerShell is too much powerful and extensible. You can do almost all kinds of SharePoint programming with PowerShell script. My personal view is that we, SharePoint developers, don’t need to be expert in PowerShell but we need to have basic knowledge of “How to use PowerShell Script for SharePoint Deployment/Maintenance?”. There are already much activities on web around PowerShell and SharePoint. Few useful links related to PowerShell and SharePoint are given below:
Some Useful CodePlex links:
Here is a Visual Studio 2010 extension for SharePoint PowerShell Scripting:
Here is a tool called PowerGui that is handy for editing PowerShell script:

The concept for waiting for job to finish, I have taken from the following link:
http://msdn.microsoft.com/en-us/library/ff459292.aspx

Friday, May 7, 2010

Content Migration from SharePoint 2010 Beta to RTM is not supported

If anyone out there has already developed some SharePoint sites with beta release and now want to move to RTM then there’s a bad news. The migration is not supported. If you try to move your content with Content Migration API then you’ll get an error message like below:

The Version of the package 14.0.4536.1000 differs from the current version 14.0.4762.1000 which is supported by this program.

 

Steve Chen has described in his blog on why the migration from beta to RTM is not supported. He mentioned that the lesson Sharepoint team learned from 2007 that there may be inconsistency data left from  pre-releases versions. These inconsistent data (from pre-release versions) may generate problems for later releases. However, customers having “Go-Live” license can get help from Microsoft to move data from beta to RTM. The “Go-Live” license is an agreement between customers and Microsoft to help customers to migrate from beta to RTM.

The final learning is “Play with beta releases but don’t dear to develop production code until final version is released”.

Related information can be found in the following links:

http://blogs.technet.com/steve_chen/archive/2010/01/20/sharepoint-2010-public-beta-to-rtm-upgrade.aspx

http://social.msdn.microsoft.com/Forums/en/sharepoint2010general/thread/b55bea00-c907-4468-9cb3-dac208f7ac4e