Sharing the experience search

Search sharing-the-experience.blogspot.com

Tuesday, September 28, 2010

This object will now be disposed

Recently we had to process around 2000 items on the list. Basically we needed to fire the update event on every item.
The code looks very simple:
 using (SPSite oSiteCollection = GetSPSite(properties, "http://test/t1/t2/t3"))
            {
                using (SPWeb oWebsite = GetSPWeb(properties, oSiteCollection))
                {
                    bool oldAllowUnsafeUpdates = oWebsite.AllowUnsafeUpdates;
                    oWebsite.AllowUnsafeUpdates = true;
                    try
                    {
                        SPList destSPList = GetListByUrlPattern(oWebsite, "Lists/mylist");
                        if (destSPList != null)
                        {
                            List<SPListItem> tmpList = new List<SPListItem>(destSPList.ItemCount);
                            foreach (SPListItem tmpSpListItem in destSPList.Items)
                                tmpList.Add(tmpSpListItem);
                            tmpList.Sort(delegate(SPListItem op1, SPListItem op2) { return op1.ID.CompareTo(op2.ID); });

                            RTWEventLog.WriteInfo("RTWSMSIncidentPermissionPatch is starting processing!");
                            int incCount = tmpList.Count;
                            for (int i = 0; i < incCount; i++)
                            {
                                SPListItem spListItem = tmpList[i];
                                try
                                {
                                    if (!spListItem.HasUniqueRoleAssignments)
                                    {
                                       
                                        System.Threading.Thread.Sleep(5000);
                                        spListItem.Update();
                                        System.Threading.Thread.Sleep(10000);

                                        RTWEventLog.WriteInfo(string.Format("The Item {0} (ID:{1}) is processed!", spListItem.DisplayName, spListItem.ID));
                                    }
                                }
                                catch (Exception ex)
                                {
                                    RTWEventLog.WriteError(ex);
                                }
                            }
                            RTWEventLog.WriteInfo("RTWSMSIncidentPermissionPatch is completed!");
                        }
                        else
                            throw new ApplicationException("Couldn't find list with url Lists/mylist");
                    }
                    catch (Exception ex)
                    {
                        RTWEventLog.WriteError(ex);
                    }

                    oWebsite.AllowUnsafeUpdates = oldAllowUnsafeUpdates;
                }
            }
        }
We had to put the code in sleep - to be sure that otimer.exe can fetch the event and fires the  handled on the item.
After a while ULS Log shows the error:
An SPRequest object was not disposed before the end of this thread.
 To avoid wasting system resources, dispose of this object or its parent (such as an SPSite or SPWeb) as
soon as you are done using it.  This object will now be disposed.  
So the only resume we have  is : don't use a disposable object for too long! Try to dispose and re-create inside your long routine.

Wednesday, September 22, 2010

"No item exists" - Modifying a default permission level leads to a problem

As you can guess from the title - I have tried to modify a permission level on a sharepoint site and at some point it broke my securable objects.

Issue: The user can't see the item that he just created . The error- "No item exists..". The list item can have inherited permissions and it can have unique permissions with setup permissions level for a creator - it doesn't change behavior. "Manage permissions" shows user should have a permission on the item, Effective permission report (Microsoft SharePoint Administration Toolkit v4.0 x86 ) shows "No effective permission for the user".

If you ever seen this - you are lucky to have my answer, or unlucky - if it still drives you crazy and my solution doesn't work for you.

Solution: After a week of researching with a team of 3 people - we finally came to the point to blame the modified default permission level on the site.  Seems that at some point the modification of permission level on the web site mixed up the security on some lists (it didn't affect all objects! which I consider really strange!) . To fix the issue - I had to re-inherit the permission levels from the site collection.

!Attention  - Once you re-inherit the permission level, all unique permissions on the site will be destroyed!
Here is a note from Microsoft:
 Important   Inheriting permissions from the parent site permanently discards all custom permissions that you might have created on any securable object for this site. This means that all lists, libraries, folders within those lists and libraries, list items, and documents lose all their unique permission settings.
 Anyway, even I have a lots object to take care of ( I made a code to return the unique permission set back), I have reset the permission level - inherit and edit - It gave a nice non-modified permission levels, and I copied the permission level instead modifying the predefined one, and set permissions set that I like to see on my own permission level. Finally assigned this permission level to a particular group\users.
And now it works!!!

Be happy, breathe freely!

By the way, I spoke with a Microsoft support team - they don't recommend modifying the out-of-box permission levels.... even though they left such nice way to do it)


Wednesday, September 15, 2010

How to restore a sharepoint web app from a SQL backup

You may want to restore data for 2 general reasons:
1. Something terrible happened on Prod and you need to bring the system up from the backup.
(the principle to backup sql databases stays the same as for ASP.net app - the full backup once a week, and differential - once a day)
2. You need to have Staging to testing purposes (which is highly recommended!)

Whatever reason you have the process of restoring will look like this:
1. On env where you want to restore - restore the sql backup into new sql database.
2. On sharepoint env where you want to have the restored web app - go to the Central Administration - Create web application - !Choose the sql database which you have got after the first step. 
3. Create a new site collection on the top level ( it's a kind of magic for me (I took it from Restore a SharePoint Site from a Database Backup).

   It will help you to identify permission problem on SQL side. At this step you may see the error in ULS log:
 Cannot open database "[Database Name]" requested by the login. The login failed.  Login failed for user '[user_name]'. That's simply means that you have to add your application pool account to the SQL db.

4. Go to the restore site collection administrators - and check if those administrator still valid in new env, or change them as you wish to have it
5. BINGO!) You are done)
If for some reason you don't want to restore the way I describe , you are welcome to leave your suggestion and read the following related articles:

http://www.sharepointassist.com/2009/05/30/restoring-a-sharepoint-site-collection-to-a-new-domai/

http://social.technet.microsoft.com/Forums/en-US/sharepointadmin/thread/a60af1a0-caa7-4576-80a1-519ef42109db#7e5a4469-a8b8-462d-a5da-1ac0daf40adf

http://www.ungertech.com/dbrestore.html

http://www.iotap.com/Blogs/tabid/277/EntryId/136/Move-sharepoint-site-from-one-domain-to-another-domain.aspx

P.S. Experiencing the error "has been upgraded to a newer version of SharePoint. Please upgrade this SharePoint application server before attempting" - refer to the post Where to look for SharePoint version?

P.S.S. If you do such restore on the regular basis, this simple truth makes you life easier:
1. Use the same port for restored web application as you use in source (assuming, prod) web application;
2. Use the same name of db on the restored env as you use in the source environment.

Friday, September 3, 2010

Simple Concept:How to enable fusion log



[Question]:
Why I need fusion log? And how to enable fusion log? 


[Answer]:


Ever experienced the error with loading dll?


Recently did something wrong and found a lots errors in the system event log similar to this:
SafeControl load exception:Microsoft.SharePoint.Portal, Version=12.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c Exception:


Fusion log comes in very handy when you want to understand or debug binding behaviors. 


In order to enable it:
1. Easy going method:
Download SDK;
Install it;
Run the sdk command prompt;
Input Fuslogvw.exe




2. Manually:



regedit.exe - HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Fusion
set the registry key to enable fusion logging. HKLM/Software/Microsoft/Fusion/EnableLog DWORD 1




 By default the log files go into the Temporary Internet Files folder of the current user’s profile. 


Optionally you can set you custom path for log:  HKLM/Software/Microsoft/Fusion/LogPath String [your disk: you location]


Be careful! If you setup your own custom location - you are responsible to clear it out 


After the setting the keys - IISreset and load any pages, it will trigger the logging.
To analyze you can search in the fusion log folder by name of dll with which you are experiencing the issue. Or you can find the folder of your process  that triggered the loading of this dll. Every ddl has own file with history of loading.


To make reading more convenient you can use the Assembly Binding Log Viewer (Fuslogvw.exe) 
It's included in .NET Framework 2.0 Software Development Kit (SDK)


Additional information on register keys for Fusions log : Fusion Log Viewer

Best Practices: Sharepoint Application Development Life Cycle

As you might know SharePoint Application development life cycle is different if you compare with  asp.net application development.
I bumped on the the question after the first production release : "What next? How we can perform our development,testing and deployment any further?"

There is no easy answer. Recently I happened to be at the Sharepoint Best Practices 2010 in Washington DC and got a chance to ask the experts the same question which was nagging me since the the first release on my production.

 Here is some recommendation that I have - every an update should be packed in the new wsp file and must deliver all changes that I want to make over the Prod. Why it so? because it's safe to keep the original feature  set which was used to create a Prod site. It's safe for list feature and also for Workflow features.

So the first rule: Never retract the original a wsp file on the Prod. Here is the wonderful recommendation from my SharePoint star - Professional Sharepoint Development. Every release is a new wsp file.

In case you need to change the structure of the list which has been already created from you list template feature-  do it through Object Model, don't modify a schema.  An update schema file after very first list has been created is unsupportable and may break the list instance. So to soothe the pain - use the feature for content types and custom feature receiver to propagate the changes to the list level. In you custom list template feature reference to those content types.

 the first rule in the real world: Even I know that is bad to redeploy the original wsp I am still doing it!
 to make the upgrade of the existing site I have adopted the concept of the release feature


The second rule: Never change the schema for the list template feature if the list instance has been already created. Do all your changes through Object Model.

In case you are unfortunate enough and you have a code-based Workflow on your site. If workflow needs modification, you have to be aware that serialized workflow instance might not be able to wake up using your new workflow dll.

The third rule: Don't change the original dll for Worklfow. You always should keep the original dll in GAC. Every workflow modification should be packed in new dll and new association should be made to use it.


A few days ago I have been delighted to discover this practical guidance - this is free and made initially for internal use but then converted as general public hands-on best practices "how to develop a sharepoint project". Some of the chapters I don't really agree on, but it's just my personal opinion.

Found a  useful  scenarion in MSDN: Upgrading the Training Management Application