Friday, September 25, 2009

Title Column Rename Issue

This post is from PFE legend, Godwin Tenzing:

Problem
Customer created a Custom Content Type from SharePoint Site Actions user interface and renamed the default SharePoint column e.g. “Title” to “FIO” and he tried to change it back to “Title”, but he was unable to rename it back to “Title” he received an error message “The Column name that you entered is already in use or reserved”

The issue can be reproduced like this
Customer created a custom content type from the Site Settings of the portal site. When he created a custom content type customer would have chosen to inherit parent content type for e.g Document as parent content type.

Custom content type was created successfully with a default SharePoint “Title” column which was inherited from the parent content type.

Customer clicked the content type column name “Title” and renamed the default “Title” column name for e.g. “Title” to “FIO”



He realised the column name “Title” had been renamed all over the Site Collection, so he tried to rename the modified column name “FIO” back to “Title” but he received the below error message

“The Column name that you entered is already in use or reserved”

Since “Title” is a reserved word in SharePoint, customer was unable to rename the column name back to “Title”.
What customer actually wanted to do is to rename the custom content type column name, but since “Title is the inherited column and it is default SharePoint column name, renaming the column had much wider implications.

Now the entire Portal Site Collection shows the column name “Title” as FIO and it cannot be renamed to “Title” in the SharePoint front end.

Customer now wants to rename the column name back to “Title”, but this cannot be done in the user interface.

Solution
The above issue is seen as design time limitation or as a bug, this will be raised with the product group to review and to fix it, if it is confirmed as bug by the product group then a fix will be provided in the future hot fixes.
However to get the issues resolved, we have found an easy solution for the issue, please use the below code to fix the above issue, however it is recommended to test the below console application code on your Test Server before applying it on to your live portal. Also it is recommended to take a complete back up of you portal content database.

Customer will have to create a console application project, once the project is created copy the code to the new project, and then compile the project.

Note: To successfully compile the project you will have to add reference to the “Microsoft.SharePoint.dll”
Microsoft.SharePoint.dll can be found in the SharePoint Server where MOSS 2007 is installed.
Path for the Microsoft.SharePoint.dll is “C:\Program Files\Common Files\microsoft shared\Web Server Extensions\12\ISAPI”

using System;
using System.Collections.Generic;
using System.Text;
using Microsoft.SharePoint;

namespace RenameField
{
class Program
{
static void Main(string[] args)
{
if (args.Length < 3)
{
Console.WriteLine("Usage: RenameField ");
return;
}

SPSite site = new SPSite(args[0]);
SPField f = site.RootWeb.Fields[args[1]];
f.Title = args[2];
f.Update();
}
}
}

Disclaimer
/// this source code is freeware and is provided on an "as is" basis without warranties of any kind,
/// whether expresses or implied, including without limitation warranties that the code is free of defect,
/// fit for a particular purpose or non-infringing. The entire risk as to the quality and performance of
/// the code is with the end user.


As you will not be developing this console application in a live server, you will have to create a deployment project to run this console application on the server.

The proposed solution has certain limitations on a Multilingual site, so the code has to be modified to work on a multilingual site.

-------------------------------------------------------------------------------------
Any installation of WSS 3.0 or MOSS 2007 is no complete with PowerShell. Why? Because it makes situations like this so easy.

Save the following as SharePoint.ps1:
[System.Reflection.Assembly]::Load("Microsoft.SharePoint, Version=12.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c");
function Get-Site($absoluteUrl) {
return new-object Microsoft.SharePoint.SPSite $absoluteUrl;
}
function Rename-Field($site, $oldTitle, $newTitle) {
$field = $site.RootWeb.Fields[$oldTitle];
$field.Title = $newTitle;
$field.Update;
}
######## End of SharePoint.ps1 ########

Now the rename function is availble on request:
1> .\SharePoint.ps1
2> $site = Get-Site http://localhost/PlaySite
3> Rename-Field $site "FIO" "Title"

When it comes to SharePoint administration, PowerShell is your new best friend - no copmiled code, no deployment issues and you can sign all scripts for use on production servers.
-------------------------------------------------------------------------------------

This will not be fixed
I raised this as a bug in the beta program and the product team said it is not a bug and is by design and will not be fixed. They suggested exactly what you have designed. They said use the object model to correct the mistake.

Lets try again
I feel it is a bug, because by design it lets you change the title name to some other name. But it doesn't let you change it back to the old name 'Title', which is weird. If this is design limitation then we need at least a warning message to warn the actions. When the customer tried to rename the title column he thought he is changing the column name for his custom content type, he didn't realise it will update the column name for the entire site collection.

I have spoken to couple of escalation engineers. They have requested me to raise it as bug, so let’s wait and see what the product group feels about it this time.

I know this bug and can rename the column to the original 'Title' with SharePoint Manager tool.


Thanks!!!!!!! Not quite the same, ... this one worked for me: ----- [System.Reflection.Assembly]::Load("Microsoft.SharePoint, Version=12.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c"); function Get-Site($absoluteUrl) { return new-object Microsoft.SharePoint.SPSite $absoluteUrl; } function Rename-Field($site, $oldTitle, $newTitle) { $field = $site.RootWeb.Fields[$oldTitle]; $field.Title = $newTitle; $field.Update(1); } $site = Get-Site("https://myportal/"); Rename-Field $site Title1 Title; ---- after 1st run, it did not see my functions in the shell, so I added the calls to the scripts. $filed.Update(1) so as to apply the cange down the line in all ascendant field (and content) types. Title1 was my NOT-THAT-old name :-) after system rejected to rename it back to title...

Updating all lists affected by the initial Title column rename
The following code goes one step further and walks all the lists in the site collection to rename any list columns that were affected when the site column was first changed:

using System;
using System.Collections.Generic;
using System.Text;
using Microsoft.SharePoint;

namespace FieldRename
{
class Program
{
static void Main(string[] args)
{
if (args.Length < 3)
{
Console.WriteLine("Usage: RenameField ");
Console.WriteLine("/n Run under indentity of WebApplication app pool identity");
return;
}

SPSite site = new SPSite(args[0]);

try
{
SPField f = site.RootWeb.Fields[args[1]];
f.Title = args[2];
f.Update();
Console.WriteLine("Site Column: {0} renamed {1}", args[1], args[2]);
}
catch { }

UpdateSiteLists(site, args); // update lists in targeted site collection

}

static void UpdateSiteLists(SPSite site, string[] args)
{
foreach (SPWeb w in site.AllWebs)
{
Console.WriteLine("Scanning Site{0} ( Listcount: {1})",w.Title.ToString(), w.Lists.Count);

List lists = new List();

foreach(SPList l in w.Lists)
{
try
{
SPField lf = l.Fields[args[1]]; // exception if not found
lists.Add(l); // found
}
catch { }
}

foreach (SPList l in lists)
{
Console.WriteLine(" List {0} updated", l.Title);
SPField lf = l.Fields[args[1]];
lf.Title = args[2];
lf.Update();
}
}
}
}
}

at 4/26/2009 3:16 AM
Restore original title in a multilingual scenario
Hello, Thanks for the post. You said: "The proposed solution has certain limitations on a Multilingual site, so the code has to be modified to work on a multilingual site." Well, I've got that problem. I modified the column and now, it is not translated to other languages. What could I do?

at 5/14/2009 6:49 AM
Restore original title in a multilingual scenario
Hello, Thanks for the post. You said: "The proposed solution has certain limitations on a Multilingual site, so the code has to be modified to work on a multilingual site." Well, I've got that problem. I modified the column and now, it is not translated to other languages. What could I do?

at 5/14/2009 6:55 AM
This PowerShell Script worked for me
This worked like a dream, using PowerShell on the SharePoint server front-end:

[System.Reflection.Assembly]::LoadWithPartialName("Microsoft.SharePoint")

$site=[Microsoft.Sharepoint.SPSite]("http://")

$web=$site.openWeb()

$fld = $web.Fields.getFieldByInternalName("Title")

$fld.Title = "Title"

$fld.PushChangesToLists = $true

$fld.Update()
at 7/1/2009 4:19 PM
Reply: This is Fixed in WSS 3.0 SP2
http://download.microsoft.com/download/7/A/3/7A3E2E01-5454-4427-95CB-28CE84523B0A/Windows%20SharePoint%20Services%203.0%20Service%20Pack%202%20Changes.xlsx

Chris Whitehead
at 7/2/2009 7:13 AM
Do not modify SQL!!
We have had some people post comments that you can fix this by using an UPDATE SQL statement on the ContentTypes table.

We will not be posting these since whilst this may work, it is COMPLETELY UNSUPPORTED and WILL render your environment unsupported. You should never modify your SQL backend. There are many completely supported solutions posted above. Please use one of these.

If you have already modified your databases, you should restore them to the point before the modification and use a proper fix to resolve the issue.

Sorry for the stern response but it is critical that customers follow the correct guidance on this. Many thanks!

1 comment:

  1. There is a file called FldEdit.aspx in layouts folder which contains a
    javascript function as shown below

    function doesFieldNameConflict( strName )
    {
    if (g_FieldName[strName.toLowerCase()] &&
    strName.toLowerCase() != <
    %SPHttpUtility.AddQuote(SPHttpUtility.EcmaScriptStringLiteralEncode(spField.Title),Response.Output);
    %>.toLowerCase())
    return true;
    else
    return false;
    }

    g_FieldName : Its an array collection of all possible fields...
    Just modify the function to add your own logic and by passing the
    check for existence of "Title" field as shown below


    function doesFieldNameConflict( strName )
    {
    if( strName.toLowerCase() == "title")
    return false;
    if (g_FieldName[strName.toLowerCase()] &&
    strName.toLowerCase() != <
    %SPHttpUtility.AddQuote(SPHttpUtility.EcmaScriptStringLiteralEncode(spField.Title),Response.Output);
    %>.toLowerCase())
    return true;
    else
    return false;
    }


    I tried this method, and problem is resolved like this, dont forget to remove that 2 line once it get resolved.

    All The Best... :-)

    ReplyDelete