Sunday, December 13, 2009

SPWeb.Users and SPWeb.SiteUsers are the same ?

Well no.

Sounds very close, but there is a difference.


SPWeb.Users - Property returns collection of user objects that are explicitly assigned permissions.


SPWeb.SiteUsers - Property returns collection of user objects that belong to site collection.

Thursday, November 12, 2009

CAML Vs Linq ? What's better ?

A few days ago I had a small project over one of my clients, one of the issues I had to deal with was to iterate via his enormous lists sizes, and to change specific MetaData according to other metadata that he already has.

Then I had to choose how I want to work with those lists

Why Linq ?

1. Easy for the .net developer, no new skills required.
2. intellisense. It's a great deal sometimes.
3. Easy to read your code, no loops, no "weird" syntax.
4. Can combine multiple sources ( XML files, SharePoint lists and databases and more ... )

Why NOT Linq ?

1.Performance issues in some cases. All items are being retrieved from the database.
The filtering phase is being done only by iterating via all all items and comparing them to the where clause. So in large collections we have a major performance problem with Linq.

An example, which we will use later again :

 
//checking if the column address is not empty and the column name equals tothe filter.
//and order it by PostedOn

var resourceListItems = fromSPListItemitemin resourceList.Items
whereitem[“Name”] .ToString().ToLower().Contains(_filter)
&& item[“Adress”].ToString().Length> 0
orderbyitem[“PostedOn”] ascending


Why CAMAL ?

1. Only items that match the filter criteria will be retrieved from the database.
2. There are some wizards to make it easier for writing those queries ( such as : LinqToSharepoint, Linq4SP and some more - just google those names ).

Why NOT CAMAL ?

1. Syntax. No intellisense. Not easy to read.
2. Problematic filtering, not as wide as you can get in Linq. If you want to compare two columns it's not feasible ( I might wrong on that ).

Same example as before in CAML :

 
//checking if the column address is not empty and the column name equals tothe filter.
//and order it by PostedOn, and at last calling getting the collection.

SPQueryquery = newSPQuery();
query.Query= String.Format(“

{0}




”, _filter);

SPListItemCollectionlistItemsColl= resourceList.GetItems(query);


And yes, you can use them both combined , for example :

 

SPQuerycamlQuery= newSPQuery();
camlQuery.Query= String.Format(“

{0}


”, _filter);
var resourceItemsCollection=fromSPListItemiteminresourceList.GetItems(camlQuery)
orderbyitem[“PostedOn”] ascending


Bottom line, it depends on what you need to do :

If you work on a very large collection, you better use CAMAL ( also recommended in the MSDN ).

If you work on a small collection , and the cost of iterating all collection is ok for you, Or when you need to make a certain filtering that requires iteration ( such as column comparison ) then choose Linq.

Enjoy.

Wednesday, November 11, 2009

How to change the regional settings of your site collection

Very simple -

Go to : Site Settings => Modify All Site Settings

Click on "Regional Settings" under "Site Administration" column.
Now just change the time zone...

Good Luck.

Saturday, October 31, 2009

Moss on Windows server 2008 R2

In the last few weeks I have started to sense over my clients the desire of upgrading windows servers from 2003 to 2008.

So if you are about to this move for your Moss WFE server, you better check this link -
http://blogs.msdn.com/sharepoint/archive/2009/10/02/install-sharepoint-server-2007-on-windows-server-2008-r2.aspx

Good luck.

Friday, October 9, 2009

How to check if list is a document library ? Let's Linq it !

Sometimes you need to iterate via the Doclibs of a site for a dedicated reason, and there is no need to iterate via the "regular" lists of the site.

Of course it's very easy so you usually just run something like that -

 
SPWeb web = site.Openweb();
SPListCollection listCol = web.lists;
foreach(SPList list in listCol )
{
//Do your thing
}


So in order to be more efficient, run only in doclibs, and not on all lists that you have in your website ( including hidden ones ).

How you do that ? very simple.

 
SPWeb web = site.Openweb();
SPListCollection listCol = web.lists;
foreach(SPList list in listCol )
{
if(list.BaseType == SPBaseType.DocumentLibrary)
{
//Do your thing
}
}


And to make it even nicer, lets just LINQ it -
 
var docLibs = from SPList list in web.Lists where (list.BaseType == SPBaseType.DocumentLibrary) select list;
foreach (SPList doclib in docLibs)
{
//do your thing
}


Hope it helps.

Tuesday, September 8, 2009

few days ago I came across this nice short video.

Im ashamed to say how much time I spent on doing the same via web services...

Actually, Im just being harsh on myself, because this "idea" is a bit more limited, but still very cute.

Display a SharePoint list on Another Site in 3 minutes from Dux Raymond Sy on Vimeo.

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.

Thursday, July 23, 2009

How to change SQL server name ?

A very common issue, when you make a p2v ( convert in vmare language ) to a physical Server and change the name of the server.

The whole idea is that the database still thinks it's on the pervious database and it damages his functionalty.

Those are the steps to check if you have this issue, and how to fix that.

 
//check the hosting server of the SQL service
sp_helpserver
select @@servername

//if the server name that appears is of the pervious server
// Make sure to run it from the server itself, NO remote execution
sp_dropserver 'old_name'
go
sp_addserver 'new_name','local'
go
// Now restart the SQL service and check the first step again to make sure.


Good luck

Thursday, July 2, 2009

Archive for Sharepoint ? Symantec Enterprise Vault... Round# 2

Well, a while ago I talked about the Enterprise vault product for archiving Sharepoint platform.
Since then, The Moss 2007 is common in every single customre I have. So , now they have new version. I checked. And now I declare.

What did they fix that makes it better than their last version ?

1. It supports Kerberos authentication.

What still makes it not ready ?

1. Doesn't support fedrated shearch AKA you still cant crawl it with your Moss search engine.
2. When you want to edit an item, it's being retrieved back from the repository, but it opens the document in your temporray internet files and NOT in your web site AKA your changes wont be saved/updated ( Cause you didn't save them on your website ).
3. Permission issue. When you copy an item ( the stub ) to anoter new list with diffrent ACL - you wont be able to reach the file if you dont have an access to the source list ( read at least ).

There are more issues, but those are the most critical and I count only till three.

Sorry, But it still not ready. I better submit my customer an email.

Sunday, June 21, 2009

How to Delete specific user from your sharepoint sites

Hey.

Small task I had today, to delete a certain user who left the company. They have a list in which they document all the workers who left, so I had to just check the list every day, see if there is anything new and if so, just delete that user from all SiteCollection - be aware, when you delete a user from the siteCollection it's enough, there is no need to drill down to each and each web site.

 


foreach (SPWebApplication webApp in service.WebApplications)
{
SPSiteCollection colSites = webApp.Sites;
for (int i = 0; i < colSites.Count; i++)
{
using (SPWeb web = colSites[i].OpenWeb())
{
SPUser user = web.SiteUsers[UserName_ToDelete];

try
{
if (!user.IsDomainGroup && !user.IsSiteAdmin)
{
web.SiteUsers.Remove(user.LoginName);
web.Update();
}
}
catch (Exception ex)
{
// user not found
}
}
colSites[i].Dispose();
}

}

Wednesday, May 27, 2009

SP2 is out - But with some "minor" problems...

Be aware for the bug when installing the SP. There is a simple workaround, an hotfix soon to be released.

http://blogs.msdn.com/sharepoint/archive/2009/04/28/announcing-service-pack-2-for-office-sharepoint-server-2007-and-windows-sharepoint-services-3-0.aspx

Sunday, May 17, 2009

SPUserCollection is not including groups ? Or just a Bug in Wss 2.0 Object Model ?

Hey.

I wrote today a small application that need to track down all the administrators of all the websites in my client sharepoint farm ( and write the data into a list with the website url and etc ).

Anyway , just to remind you I was dealing with wss 2.0 ( 2003 ), I was doing very simple stuff as iterating via all web applications->SiteCollections->WebSites.
and then just wanted to get all the users ( including Active directory groups )

 
SPUserCollection colUser = web.AllUsers;
foreach(SPUser user in colUser)
{
// check if admin, update list and blah blah
}


Unfortunately, it gives you back only the regular users, and not the AD groups too. I know you have under the SPWeb object the groups/sitegroups property but both of them are for Sharepoint groups and not for AD group.
Moreover, Under the SPUser object you have the property IsDomainGroup ( like I cant ask for more ) - BUT sorry, it just gives you back regular users all the time, and just "ignore" the AD gorups.

What I did at the end ? Just made a query to the SQL table ( Not so good, cause It's not supported ) - I will try now with WebService, let's hope it work via that.

If you think i'm wrong or you have another idea. Please comment.

Friday, April 3, 2009

SPQuery operators

I dont why in the Moss SDK there is no list of the operators in the SPQuery class.

It's kind of handy to have them by when you build your query.

Eq = equal to

Neq = not equal to

Lt = less than

Leq = less than or equal to

Gt = greater than

Geq = greater than or equal to

BeginsWith = begins with

Contains = contains

IsNull = is null

IsNotNull = is not null


Hopes it helps.

Sunday, March 15, 2009

Site Templates

I was asked to create several sites automatically, i had two options rather made it via stsadm or via the object model.

but first I had to look for the web sites templates identifiers -

GLOBAL#0 = Global template
STS#0 = Team Site
STS#1 = Blank Site
STS#2 = Document Workspace
MPS#0 = Basic Meeting Workspace
MPS#1 = Blank Meeting Workspace
MPS#2 = Decision Meeting Workspace
MPS#3 = Social Meeting Workspace
MPS#4 = Multipage Meeting Workspace
CENTRALADMIN#0 = Central Admin Site
WIKI#0 = Wiki Site
BLOG#0 = Blog
BDR#0 = Document Center
OFFILE#0 = Records Center
OFFILE#1 = Records Center
OSRV#0 = Shared Services Administration Site
SPS#0 = SharePoint Portal Server Site
SPSPERS#0 = SharePoint Portal Server Personal Space
SPSMSITE#0 = Personalization Site
SPSTOC#0 = Contents area Template
SPSTOPIC#0 = Topic area template
SPSNEWS#0 = News Site
CMSPUBLISHING#0 = Publishing Site
BLANKINTERNET#0 = Publishing Site
BLANKINTERNET#1 = Press Releases Site
BLANKINTERNET#2 = Publishing Site with Workflow
SPSNHOME#0 = News Site SPSSITES#0 = Site Directory
SPSCOMMU#0 = Community area template
SPSREPORTCENTER#0 = Report Center
SPSPORTAL#0 = Collaboration Portal
SRCHCEN#0 = Search Center with Tabs
PROFILES#0 = Profiles
BLANKINTERNETCONTAINER#0 = Publishing Portal
SPSMSITEHOST#0 = My Site Host
SRCHCENTERLITE#0 = Search Center
SRCHCENTERLITE#1 = Search Center
SPSBWEB#0 = SharePoint Portal Server BucketWeb Template

Tuesday, February 24, 2009

What is the diffrence between AllUsers, SiteUsers, Users ?

In the SPWeb object you have those three properties that sounds a like, but there is a slight diffrence between them -

AllUsers - Returns "almost" all users in the site collection ( including "guests" ).

SiteUsers - Returns all users that are really exist in the site collection, including groups such as "authenticated users" and system accounts and etc.

Users - Returns only the users that appear in that specific web site.

The explanation in the SDK wasn't clear enough ( as for now , before the service packs ).

If you want to check it yourself just run this short code and see the difference.

 

//Open a SPWeb object ( a site collection )

using (SPWeb web = colSites[i].OpenWeb())
{
SPUserCollection colUsers = web.Users;
foreach (SPUser user in colUsers)
{
Console.WriteLine(user.Name);
}
Console.WriteLine("=======================");
SPUserCollection colUsers1 = web.SiteUsers;

foreach (SPUser user in colUsers1)
{
Console.WriteLine(user.Name);
}
Console.WriteLine("=======================");
SPUserCollection colUsers2 = web.AllUsers;

foreach (SPUser user in colUsers2)
{
Console.WriteLine(user.Name);
}


}

Friday, February 13, 2009

How to block SPD from editing your sites ?

When I got into the SharePoint world a few years ago, I was told about the damages frontpage can make to Sharepoint websites ( though it can make some good stuff too ).

So one of the first things I did when I start learning about Moss, it's how to block the option of the end user to edit their website with Sharepoint Designer -

1. Go to the onet.xml file ( it's in the sharepoint hive of course ).
2. Look for the line that starts with - "3. Add the - DisableWebDesignFeatures="wdfopensite"
4. Do an iisreset.

Now, You can't edit your sites with SPD.
Good Luck.

Tuesday, February 10, 2009

Moss Css chart

Very useful link when you need to edit/brand/customize sharepoint sites or just working on the CSS files.

Moss css chart

Wednesday, January 7, 2009

IE 6 Cache problems with Moss

Oy. You have no idea how much I worked on that issue...

So let me explain what was wrong, and how we solved it :

The problem - all end users who use IE 6 sp2 gets after a few moments of browsing the Moss sites, javascript error which led to CSS error ( actually it's not being downloaded well ).

We didn't notice this problem in IE6 sp3, so we thought we are almost half way to solve this issue. But the problem was now only in computer who works on windows 2000 operating system ( in which you can't install IE sp3 there .... ).

After doing more searching, we realized that this issue happens only because of the static compression that made by the IIS that being enabled automatically by Moss installation. After disabling this option the problem was gone.

So to sums things up, the files that were compressed by the IIS weren't available to the end users who used the windows 2000 computers, in other words they couldn't work on moss websites.

Three last comments -

1. You can still avoid it by changing the expiration date of the page and then postpone this problem from occurring or go 10 years back and force the IE to work on the HTTP 1.0 protocol.

2. By disabling the static compression, Im sending to the users files that are almost five times bigger than the size I usually send ( we are talking about all the CSS / JS files such core.css / ie55up.js and etc ).

3. You should disable the dynamic compression, it's not recommended by MS ( its written in the MSDN ). Yeah , I do ask why the hell they put it there on the first place ?

Saturday, January 3, 2009

Problems editing SharePoint site with IE7

Saw it over several of the end users over my clients.

The cause for that issue is kind of simple -

Just open your browser On the the menu choose :
Tools -> Internet Options, switch to Advance Tab, and disable "Disable script debugging (Internet Explorer)".