Tuesday, September 29, 2009

The platform does not know how to deserialize an object of type Microsoft.SharePoint.SPWeb

Hi all,

I have very weird error when I was developing a timer job.
Let me show how I had successfully provision a timer job in WebApplication socpe and changed the different scope (Web) of timer job which totally screwed my SharePoint instance.

This is working code : (WebApplication Scope)
class AlertNotificationInstaller : SPFeatureReceiver
{

private const string JobNameDaily =
ChecklistsConstants.JobNameDaily;
private const string JobNameWeekly =
ChecklistsConstants.JobNameWeekly;


public override void FeatureActivated(SPFeatureReceiverProperties properties)
{
SPWebApplication webApp =
properties.Feature.Parent as SPWebApplication;
if (webApp == null)
throw new SPException("Error obtaining refrence to the Web application.");

#region Delete other Job Definition for System Checklists
foreach (var job in webApp.JobDefinitions)
{
if (job.Name == JobNameDaily)
{
job.Delete();
}

if (job.Name == JobNameWeekly)
{
job.Delete();
}

}
#endregion



#region Create instances for timer jobs
AlertNotificationJob dailyJob = new AlertNotificationJob(JobNameDaily, webApp);
dailyJob.Properties.Add("Daily Job", "Tools");

AlertNotificationJob weeklyJob = new AlertNotificationJob(JobNameWeekly, webApp);
weeklyJob.Properties.Add("Weekly", "Tools");

#endregion

#region Daily


SPDailySchedule daily = new SPDailySchedule();
daily.BeginHour = 10;
daily.BeginMinute = 28;
daily.BeginSecond = 00;

daily.EndHour = 10;
daily.EndMinute = 30;
daily.EndSecond = 00;
dailyJob.Schedule = daily;
dailyJob.Update();



#endregion

#region Weekly

//SAME CODE FOR weekly schedule SPWeeklySchedule


#endregion


}


}

But need to change the time job to the web scope and changed the code as follows:
class AlertNotificationInstaller : SPFeatureReceiver
{

private const string JobNameDaily = ChecklistsConstants.JobNameDaily;
private const string JobNameWeekly = ChecklistsConstants.JobNameWeekly;

private SPWeb web = null;
private SPSite site = null;
public override void FeatureActivated(SPFeatureReceiverProperties properties)
{

web = properties.Feature.Parent as SPWeb;
site = web.Site;
if (web == null)
throw new SPException("Error obtaining refrence to the Web .");

#region Delete other Job Definition for System Checklists
foreach (var job in site.WebApplication.JobDefinitions)
{
if (job.Name == JobNameDaily)
{
job.Delete();
}

if (job.Name == JobNameWeekly)
{
job.Delete();
}

}
#endregion

#region Create instances for timer jobs
AlertNotificationJob dailyJob = new AlertNotificationJob(JobNameDaily,site.WebApplication);
dailyJob.Properties.Add("Daily Job", "Tools");

AlertNotificationJob weeklyJob = new AlertNotificationJob(JobNameWeekly, site.WebApplication);
weeklyJob.Properties.Add("Weekly", "Tools");

#endregion

#region Daily

SPDailySchedule daily = new SPDailySchedule();
daily.BeginHour = 10;
daily.BeginMinute = 28;
daily.BeginSecond = 00;

daily.EndHour = 10;
daily.EndMinute = 30;
daily.EndSecond = 00;
dailyJob.Schedule = daily;
dailyJob.Update();

#endregion

#region Weekly

//Weekly Schedule 

#endregion

}
}
And I did some code chnages as follows:

>> In the feature.xml, I changed the scope from "WebApplication" to "Web".

Scope="WebApplication" to Scope="Web"

>> In Execute method, I changed the scope of "WebApplication" to just "Web"

// get a reference to the current web application
SPWebApplication webApplication = this.Parent as SPWebApplication; TO

// get a reference to the current web application
SPWeb web= this.Parent as SPWeb;


I just upgraded the solution and timer job was provisioned in the web scope.
But when I deactivate this feature I got this error:

The platform does not know how to deserialize an object of type Microsoft.SharePoint.SPWeb. The platform can deserialize primitive types such as strings, integers, and GUIDs; other SPPersistedObjects or SPAutoserializingObjects; or collections of any of the above. Consider redesigning your objects to store values in one of these supported formats, or contact your software vendor for support.


There few other observations:

1) I try the my deactivate the feature on the web scope (through UI) , it threw the same error.
2) Tried uninstall the solution through WSPBuider, it threw this error:

i) Error while killing the timer jobs
ii) Same error mentioned above.

3) Tried delete the solution from Central Admin . Same Error.
4) When I went to Central Admin >> Operations >> Timer Job Definitions and clicked on it, threw this error:


ERROR:

The platform does not know how to deserialize an object of type Microsoft.SharePoint.SPWeb. The platform can deserialize primitive types such as strings, integers, and GUIDs; other SPPersistedObjects or SPAutoserializingObjects; or collections of any of the above. Consider redesigning your objects to store values in one of these supported formats, or contact your software vendor for support.

Now, I have noticed that all the Times Job definitions are screwed up.

I also researched and found that one person had same issue and workaround:
Issue and workaround .


I referred to one the blog which discussed this issue.
http://jritmeijer.spaces.live.com/blog/cns!8A48A27460FB898A!1176.entry

Apparently, SharePoint UI cant help . I have to modify the Database (SharePoint Configuration database ).
After studying the schema of the Config Database, SharePoint uses Hierarchical Object Store (HOS).

There are 2 important tables
1) Classes
2) Objects


What I queried the tables (Classes and Objects) and identified the "corrupt" object. (its the name of the solution , in my case)

>> Deleted the corrupt object . (Objects table)
>> Delete the corresponding class. (Classes table)

Went to Central Admin >> Operations >> Timer Job Definitions .

VOILA!!!

It worked....

I got my lesson and bottom line is that:

>> Whenever you are changing the scope, you MUST DEACTIVATE the feature first and then upgrade the solution. Otherwise, it will screw the SharePoint instance.

Cheers
--Aroh

IISReset or AppPool Recycling won't refresh email code

Hi All,
I was developing a SharePoint solution which contains instances time job definition in my VM.
For testing purposes, I hard coded my email address which is associated with my timer jobs. It worked fine.

I deployed the SharePoint solution to test server subsequently. Apparently, I noticed that in test server I had hard coded my email address.

Therefore, I made it dynamic email address in my VM, upgraded the WSP solution in VM. It worked fine. I also copied and deployed to the test server.

I did IISReset and recycled the application pool in the test server but it was not refreshing my email code and sending to only my email address and in that list I had 3 email seperate addresses.

It seems, when we deploy the timer jobs and upgrade the WSP solution, we need to follow these steps:

1) IISReset
2) Recyle Application pool.
3) Restart the Windows SharePoint Timer Service.

If we test it again, it should work fine.
There is one more blog about one of the SharePoint MVP about this issue.

Cheers,
--Aroh

Sunday, September 27, 2009

How to: Using CAML query from SharePoint List with folders content types

Hi all,

While developing the custom document library which has folders as content types, I had to query the custom document library for a particular folder using the U2U query builder.

This is my business requirement. I have provisioned a custom document library called "IT System Checklists". This is full structure:

IT System Checklists (Main document library)
---------Desktop Support (sub-folder)
----------------------Daily (sub-sub-folders)
----------------------Weekly
----------------------Monthly
----------------------Yearly
---------VMS (sub-folder)
----------------------(Same structure Daily, Weekly, Monthly, Yearly)

What I have to search for each folder and do some kind of manipulations. If we use U2U builder,
>>Choose the Site URL: http://testserver/apac/Tools
>>Choose "Connect via Object Model"








>> Right click on the "IT System Checklist". We have just option "Query". If we query this list "ID" and order by, there will be just 2 rows i.e. "Desktop Support" and "VMS". There is no folders like daily, weekly folders etc.










But, we can choose second option: "Connect via SharePoint Web Services"








>> Right click on "IT System Checklists", select "GetListItems" and choose "Query Options" tab.
Here we can select any sub folder.












A very detailed and extremely useful article by Karine Bosch (from U2U).
Here is the sample code:

public override void Execute(Guid contentDbId)

{

// get a reference to the current web application
SPWebApplication webApplication = this.Parent as SPWebApplication;
// get a reference to the current site collection's content database
SPContentDatabase contentDb = webApplication.ContentDatabases[contentDbId];
weekend = isWeekend(DateTime.Today);
foreach(SPSite site in contentDb.Sites)
{
Console.WriteLine(site);
if(site.ToString().Contains("apac"))
{
siteName = site.ServerRelativeUrl;
break;
}

}
// get a reference to the Site Collection in the content database
using (SPSite spSite = contentDb.Sites[siteName])
{
// get a reference to the Web
using (SPWeb spWebRoot = spSite.OpenWeb("Tools"))
{
// get a reference to the "System Checklists" list
SPList sysCheckList = spWebRoot.Lists["System Checklists"];
// this will give us a list of all objects (docs/files and folders) for a particular subfolder level
SPListItemCollection sysCheckColl = sysCheckList.Items;
// loop for iterating all folders, subfolders and documents.
foreach (SPFolder subFolder in sysCheckList.RootFolder.SubFolders)
{
// get the query object
SPQuery queryFolder = new SPQuery();
queryFolder.Query = "<OrderBy><FieldRef Name='Title'/></OrderBy>";
queryFolder.Folder = subFolder;
queryFolder.ViewAttributes = "Scope=\"RecursiveAll\"";
// get sub-folders such as Daily, Weekly
foreach (SPListItem folder in sysCheckList.GetItems(queryFolder))
{
Console.WriteLine(queryFolder.Folder);
#region Daily
if (folder.Name == "Daily")
{
string str = queryFolder.Folder.ToString();
// get the SharePoint group names for each category (Daily)
if (str.Contains("VMS"))
{
GroupName = "VMS - Daily";
GroupName = SharePointGroups.DesktopSupportDaily;
}
if (str.Contains("Desktop Support"))
{
GroupName = "Desktop Support - Daily";
}
// get the group name for "Daily" checklists

SPGroup dailyGrp = spWebRoot.Groups[GroupName];
SPUserCollection userCollection = dailyGrp.Users;

foreach (SPUser user in userCollection)
{
FolderVar = queryFolder.Folder;
FolderVarSub = FolderVar.SubFolders["Daily"];

// get the query object for user alert
SPQuery queryUserAlert = new SPQuery();
queryUserAlert.Query = "<Where>" +
"<And>" +
"<Eq>" +
"<FieldRef Name='Author' />" +
"<Value Type='User'>" + user + "</Value>" +
"</Eq>" +
"<Eq>" +
"<FieldRef Name='Modified' IncludeTimeValue='FALSE'/>" +
"<Value Type='DateTime'>" + SPUtility.CreateISO8601DateTimeFromSystemDateTime(DateTime.Today) + "</Value>" +"</Eq>" +
"</And>" +
"</Where>";
queryUserAlert.Folder = FolderVarSub;
SPListItemCollection noOfItems = sysCheckList.GetItems(queryUserAlert);
// No Daily Checklists for today then send email
if (noOfItems.Count == 0)
{
string daily = "Daily Checklists: " + str;
SendEmailReminder(spWebRoot, user.Email, user.Name, daily);
}
}
}
#endregion

#region Weekly
if (folder.Name == "Weekly")
{
string str = queryFolder.Folder.ToString();

// get the SharePoint group names for each category (Daily)
if (str.Contains("VMS"))
{
GroupName = "VMS - Weekly";
}
if (str.Contains("Desktop Support"))
{
GroupName = "Desktop Support - Weekly";
}
// get the group name for "Daily" checklists
SPGroup dailyGrp = spWebRoot.Groups[GroupName];
SPUserCollection userCollection = dailyGrp.Users;
foreach (SPUser user in userCollection)
{
FolderVar = queryFolder.Folder;
FolderVarSub = FolderVar.SubFolders["Weekly"];
// get the query object for user alert
SPQuery queryUserAlert = new SPQuery();
queryUserAlert.Query = "<Where>" +
"<And>" +
"<Eq>" +
"<FieldRef Name='Author' />" +
"<Value Type='User'>" + user + "</Value>" +
"</Eq>" +
"<Eq>" +
"<FieldRef Name='Modified' IncludeTimeValue='FALSE'/>" +
"<Value Type='DateTime'>" + SPUtility.CreateISO8601DateTimeFromSystemDateTime(DateTime.Today) + "</Value>" +
"</Eq>" +
"</And>" +
"</Where>";
queryUserAlert.Folder = FolderVarSub;
SPListItemCollection noOfItems = sysCheckList.GetItems(queryUserAlert);
if (noOfItems.Count == 0)
{
string weekly = "Weekly Checklists: " + str;
SendEmailReminder(spWebRoot, user.Email, user.Name, weekly);
}
}
}
#endregion

}
}
}
}
}

Friday, September 25, 2009

Preparing for SharePoint 2010 today (in Singapore)

There was a Microsoft event on 16 September 2009 where Joel Oleson (MVP) and Jean (MVP) give some information about SharePoint 2010 and discussed what's new in this version. Here are my following my notes:

There were two presentations.

1) SharePoint Workspace 2010 (by: Jean, MVP )

>> Microsoft is renaming "Groove 2007" to SharePoint Workspace 2010.
>> SharePoint Workspace 2010 provides a very easy access to the SharePoint content and giving a seamless online/offline kind of experience.
>> SharePoint Workspace 2010 is extremely easy to manage and deploy the content. Thereby, making SharePoint users more productive.
>> Users can go to SharePoint Workspace 2010, make a local copy of the content, make changes and sync content to SharePoint Workspace.
>> No need of VPN.

There few videos for the demo, but there in French.

2) Preparing for SharePoint 2010 today (by: Joel Oleson, MVP)

i) System Requirements
The following are the system requirements for SharePoint Server 2010.

SharePoint Server
64-bit Windows Server 2008 or 64-bit Windows Server 2008 R2

SQL Server
64-bit SQL Server 2005 or SQL Server 2008

Client Desktop Requirements
Internet Explorer (IE) 7 or higher, or Firefox 3.x for Editing and Design
Safari - better browsing experience
No support for IE 6

Surprisingly, Visual Studio .net 2010 is 32-bit but Microsoft provides 64 bin components for SharePoint.

Office 2010 provides the greatest innovations for editing Office clients since 2007, as well as the richest SharePoint integration ever.
For improved user experience, we (audience) should also seriously consider SharePoint Workspace.

ii) Developer Desktop Considerations

The ultimate SharePoint developer desktop is 64-bit with 8 GB of RAM running Visual Studio 2010 with SSD disks. While it may take some serious planning to get your (audience) developers running with the latest and greatest technologies, SharePoint 2010's 64-bit requirements can help you justify this expenditure when planning your development budget. In addition, if corporate remote development includes virtual environments, then be sure to look at Windows Server 2008 and Hyper V. Make sure that the host will support 64 bit.

iii) Running the STSADM command PREUPGRADECHECK

Its provided on SharePoint Server SP2. Its an awesome tool and also a health check for our farms. These are 5 main reasons to run this command:

>> 1. PreUpgradeCheck is has a better engine, it's based on a best practices analyze.
>> 2. PreUpgradeCheck is read-only
>> 3. PreUpgradeCheck Reporting Rocks!
Gives you not just a log and screen output, but an XML report and HTM report, and verbose log of all of the rules with a again verbose database and site collection detail that goes way beyond. Excellent was of comparing the Local vs. Farm reports and comparing server to server reports.
>> 4. PreUpgradeCheck tells you about the state of your farm
>> 5. PreUpgradeCheck is a native STSADM command


Joel, showed a demo on this farm and ran that command.

iv) Identifying Customizations

The PreUpgradeCheck tool can give you (audience) a lot of insight into your environment, but you shouldn't stop there in your efforts to identify development assets, customizations, and configurations in your SharePoint farm. This could be lot of customizations:

>>Binaries and Dev Assets, which are often found in _layouts, features, and 12 hive
>>Installation directories
>>GAC or Bin
>>IIS Home directory or virtual directories
>>Features
>>Solutions
>>Timer jobs
>>Event receivers

v) Tools to find the customizations

There are lot of tools to the customizations such as:

>> SPDiag
>> Windiff - comparing folders/files (Joel prefers this tool) etc.

vi) INFORMATION ARCHITECTURE AND DATA CLEANUP

The more optimized the environment, the smoother and faster the upgrade will be. Creating an initiative to encourage users to delete unused sites and identify ones that are no longer in use can trim a lot of content that is simply taking up space; this clutter can slow down the upgrade process. You can do all of the following today:

>>Remove unused sites and site collections
>>Remove orphaned sites, lists, and objects identified in the PreUpgradeCheck
>>Remove locks and increase the quotas of sites that are at or near max capacity
>>Remove or add missing features and web part assemblies (check dependencies) identified in PreUpgradeCheck
>>Cleanup can also involve working through and resetting pages and sites back to site definition or finalizing previous upgrades:
>>Finalize any 2003 or WSS 2.0 gradual upgrades that have not been finalized
>>Return pages to the layout in site definition, reset all pages using the reset to site definition found in site settings on the site collection

Saturday, September 19, 2009

SharePoint 2010 Sneak Peek Presentation

While Tom, Richard and Paul did the Overview, IT Pro & Developer SharePoint 2010 sneak peek videos respectively on the web, I did the SharePoint 2010 Sneak Peek session at WPC last month. The video was recently posted that you can check out here.


Building Solutions on SharePoint

How to: Use cascading drop-down lists in PowerApps

Hi all, Using cascading dropdown, users can easily fill the forms by selecting drop-down values dependent on values from another dro...