Sunday, August 23, 2009

How to edit / update / change "Read Only" list columns

We had to retrieve data from our archive storage, back to the sharepoint sites. The problem was that when we retrieved the data back to the sharepoint doclib\lists we changed the Meta Data of our items ( such as Modified, Modified By ) which most of them appear as "read only" columns.

The solution - We had to interfere in our lists, and touch those "read only" columns \ Fields. Remembering we had to avoid changing those lists\Doclibs columns and keep the "old" metadata ( before the retrieval process ).

Code Snippet for how changing the data in the "read only" column such as "Modified" -

 

SPFieldCollection colFields = list.Fields;
for (int i = 0; i < colFields.Count; i++)
{
SPField field = colFields[i];
try
{

if (list.Fields[i].Title == "Modified")
{
if (field.ReadOnlyField)
{
list.Fields[i].ReadOnlyField = false;
for (int j = 0; j < list.Items.Count; j++)
{
SPListItem oListItem = list.Items[j];
DateTime date = (DateTime)oListItem[list.Fields[i].Title];

// updating the relvant stuff on that item.

oListItem[list.Fields[i].Title] = date;
oListItem.Update();

}
}
}
}
catch(Exception e)
{
Console.WriteLine(e.ToString());
}
}


You can play with it more, and adjust it. Hope you got the idea.

Good luck.

Friday, August 21, 2009

Watch out when deleting user with "limited access" permission

Ok, So you see all the time in your root SiteCollection web site users with the weird permission of "limited access". Sometimes you don't even remember why they have this permission and you just want to delete them... So BIG NO. You are about to create a major mistake.

Before I start to explain why, you need to understand what is it.

Limited Access is a permission level that is automatically assigned to a user or a group when you assign them a role at a lower level ( website/list ) but in order to access that lower level they require to access an object at a level higher than they have permissions to ( like the top rootsite of the SiteCollection ).

When you delete that user who has limited access permission from the permission list, you also delete the user from the list/site/item that he does has permission to ! Yes, by doing this small step, you delete the user actual permission from the subweb/list.

Be aware when you want to delete this permission.

Monday, August 17, 2009

How to change Site theme programatically

Very simple -

 

using (SPSite oSite = new SPSite("http://Sharepoint_Site"))
{

// Open website
using (SPWeb oWeb = oSite.OpenWeb())
{
oWeb.ApplyTheme("Theme_name");
oWeb.Update();
}
}

Saturday, August 8, 2009

A memory problem using the SPListItemCollection - How to avoid it ?

In the last few weeks my main core is tracking down memory leaks in client Sharepoint applications. This issue might not be happening to all of you who using this Object/Class. but it does might have something to do with you if you work on large lists or "future to be" large lists.

Ok, SPListItemCollection is a very strong class. Why ? Only with him you can get in flat way all the files you have in the doclib/list, regardless how deep they are located in the doclib ( in whatsoever folder in it ). I saw people that in order to get all the files which located in the sub folders in their doblibs, they were doing some serious digging ( including inefficient recursive iteration to get all those files ). But I'm sure you say - but if I need to to know in which subfolder this file was in ? Easy, you can track it down with the URL property.

So where the problem begins ? When you need just to do something very simple and very common - Automatically/pragmatically adding files\data into a list.
Let's say I want to add an item for my list, in order to do so I need to get the collection , right ? But what if my collection is huge ? above 2000 items in the list ( Above the recommendation in the whitepapers ) ?
Yes, now you start getting the problem. By calling this huge collection repeatedly Im using a lot of memory, till I might even get "Out of memory" exception.

Some code snippet to make sure you got the scenario -
 

SPWeb web = site.OpenWeb();
SPList list = web.Lists["Shared Documents"];
//Getting all Items in the collection ,even though we dont really need it
SPListItemCollection itemCol = list.Items;
SPListItem listItem = itemCol.Add();
//Working on the listItem we just added
listItem["Field1"] = //adding metadata and so on
listItem.Update();



So what we do just to workaround this scenario ? we get the collection from a certain view, which will be "thinner" version or in other words not as big as the default set of the collection. In fact, we made a special view only for that.

Short example to make sure you got the idea again -

 

SPWeb web = site.OpenWeb();
SPList list = web.Lists["Shared Documents"];
//Getting only the view items - could be empty
SPListItemCollection itemCol = list.GetItems(FakeView);
SPListItem listItem = itemCol.Add();
//Working on the listItem we just added
listItem["Field1"] = //adding metadata again or whatsoever
listItem.Update();



Apparently , This issue is very well known, it's much greater than I thought when I first saw this issue over one of my clients. Even in the MSDN they made a clearafaction about it.

Another disclaimer, one of my colleagues asked me right away, does it mean we added those items to that certain view ? Well, No. Since we still added the data to the list, the view might present those items if they fall in his view criteria. I personally made a "dummy/fake" view so it will always present nothing.

Enjoy.

Tuesday, August 4, 2009

Sharepoint Designer - what did you do ? ACCESS DENIED !

Hey all,
A few weeks ago we created with the SPD ( Sharepoint Designer ) a workflow.
After deploying it in one of our Moss websites, we saw that every time when end users created a list - there was a problem to edit an item.

The weird thing was , that every attempt to edit an item, even with the system account or with our strong privileges users, we got an access denied page.

After doing some research, we narrowed down the issue to occur only in a certain version of Moss. Googling for a while led me to the February hotfix rollup kb961756 & kb961755 - that solve this issue.
But what can I do regarding the lists that already "damaged" ? I got to this code snippet that was published by Microsoft support -







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

namespace CA_TestingHotfix
{
class Program
{
static void Main(string[] args)
{
FixField(args);
}

static void FixField(string[] args)
{
string RenderXMLPattenAttribute = "RenderXMLUsingPattern";

//Console.WriteLine("Please enter the URL of the site: (Press enter after typing):");
string weburl = args[0];

//Console.WriteLine("Please enter the Document Library Name: (Press enter after typing):");
string listName = args[1];
SPSite site = new SPSite(weburl);
SPWeb web = site.OpenWeb();
SPList list = web.Lists[listName];
SPField f = list.Fields.GetFieldByInternalName("PermMask");
string s = f.SchemaXml;
Console.WriteLine("schemaXml before: " + s);
XmlDocument xd = new XmlDocument();
xd.LoadXml(s);
XmlElement xe = xd.DocumentElement;
if (xe.Attributes[RenderXMLPattenAttribute] == null)
{
XmlAttribute attr = xd.CreateAttribute(RenderXMLPattenAttribute);
attr.Value = "TRUE";
xe.Attributes.Append(attr);
}
string strXml = xe.OuterXml;
Console.WriteLine("schemaXml after: " + strXml);
f.SchemaXml = strXml;
}

}
}



This console application just adds to your schema the attribute that is missing. We did some more research in order to understand what really happened. The thing is that somehow we made the list schema be unghosted on that Site Collection, which means that instead of taking the schema.xml for list from the WFE itself, it made a "new" copy of the schema.xml in the DB - literally a simple case of Unghosting.

We wanted to see if we can fix it without deploying SP2 or that hotfix, So in our virtual machine we decided to track that record down.

 

SELECT SiteId, Class,Scope,ContentTypeID,Version,NextChildByte,Definition, Size, ResourceDir,IsFromFeature
FROM ContentTypes
WHERE (ContentTypeId = XXXXXXXXXXXXXXXX)




To sum things up, You can deploy service pack 2 or just run the query above ( NOT SUPPORTED ), and in order to fix the lists that already affected, run the console application.

Hope it helps.