Dienstag, 20. Oktober 2009

Microsoft Unveils SharePoint Server 2010

Today, at Microsoft Corp.’s SharePoint Conference in Las Vegas, Microsoft Chief Executive Officer Steve Ballmer announced that the public beta of Microsoft SharePoint Server 2010 and Microsoft Office 2010 will become available in November, and revealed some of the new SharePoint Server 2010 capabilities for the first time.

During his keynote address, Ballmer talked broadly about SharePoint Server as a business collaboration platform and highlighted three key areas. One was how organizations can respond quickly to business needs with an improved developer platform that makes it easier to build rich content and collaboration applications. Another topic was the enhanced Internet site capabilities that help businesses drive revenue and retain customers on a single platform. The third was the choice and flexibility between on-premises and cloud solutions. At the event, Microsoft showcased the breadth of SharePoint Server 2010 that ranges from wikis to workflows, while Ballmer’s keynote address highlighted features and capabilities such as these:

  • A new ribbon user interface that makes end users more productive and customization of SharePoint sites easy
  • Deep Office integration through social tagging, backstage integration and document life-cycle management
  • Built-in support for rich media such as video, audio and Silverlight, making it easy to build dynamic Web sites
  • New Web content management features with built-in accessibility through Web Content Accessibility Guidelines 2.0, multilingual support and one-click page layout, enabling anyone to access SharePoint Server sites
  • New SharePoint tools in Microsoft Visual Studio 2010, giving developers a premier experience with the tools they know and trust
  • Business Connectivity Services, which allow developers to connect capabilities to line-of-business data or Web services in SharePoint Server and the Office client
  • Rich APIs and support for Silverlight, representational state transfer (REST) and Language-Integrated Query (LINQ), to help developers rapidly build applications on the SharePoint platform
  • Enterprise features in SharePoint Online such as Excel Services and InfoPath Forms Services, which make it simple to use, share, secure and manage interactive forms across an organization
  • The addition of two new SharePoint SKUs for Internet-facing sites, including an on-premises and hosted offer

The public betas of Microsoft SharePoint Server 2010, Office 2010, Project 2010 and Visio 2010 will become available in November 2009; more information is available at http://go.microsoft.com/?linkid=9689707.
Microsoft SharePoint Server 2010 will be available in the first half of 2010. More information about Microsoft SharePoint Server 2010 can be found at
http://www.microsoft.com/sharepoint.

Mittwoch, 23. September 2009

Updating item in "ItemUpdating" event receiver

The usual case when implementing a synchronous event like "ItemUpdating" is validating the values. For example you can easily do:

public override void ItemUpdating(SPItemEventProperties properties)
{
if (properties.AfterProperties["column"] == "aValue"){
properties.Cancel = true;
properties.ErrorMessage = "This column cannot be 'aValue'";
}
}

But if you want to change a value of the item, you cannot do this by updating the item in the common way:

item["column"] = "aValue";
item.Update();

Due to the nature of the synchronous event which is not yet completed you will get an error stating a concurrency exception.
Also the following will not do the trick. It won't raise an exception but your value will be overridden when the event is completed.
So the solution will be to put the value in the 'AfterProperties' HashTable and let the event finish.

string internalName = properties.ListItem.Fields[FIELD_NAME].InternalName;
properties.AfterProperties[internalName] = "aValue";

Donnerstag, 18. Juni 2009

Writing custom timer jobs with multiple content databases

When creating your custom timer job you probably start using code snippets from msdn or other blogs. Most of them are using the SPJobLockType.ContentDatabase intantiating the job SPJobDefinition-Object. While having just one content database on your development machine, it will always be the correct content database. So you are developing your code that is aimed to do something in a particular SPSite and everything works fine.
For executing your code you might start the Execute method with:

public override void Execute(Guid contentDbId)
{
SPSite siteCollection = new SPSite(http://xyz/);
...



Deploying this job in your production environment you might experience multiple executions because there are more than one content databases in your Web Application and your code executes for every content database per run cycle.

There are three different types of locking, as described in the SDK:
  • SPJobLockType.ContentDatabase - Locks the content database associated with the job.
  • SPJobLockType.Job - Locks the job to prevent multiple instances of the job from running on a single server.
  • SPJobLockType.None - No locking.

That means the following:

  • None - In a multi server farm the job runs on every server in your farm. You can use this when you have an switch for the job to check, if it has to run or not so that you can assure their work will not interfere.
  • Job - This means the job is locked in your farm and does run only on one server.
  • ContentDatabase - This locks the job and the content databases so that your job runs on a single server and executes for every database per cycle.

So the semantics of the job lock and the Execute method should match. If not, you could experience this confusing behaviour. Starting your Execute method with a fixed url and using the SPJobLockType.ContentDatabase will cause the job to run for every content database but it is not doing something on that particular database. That results in multiple executions of your code. In this case you should use the SPJobLockType.Job or modify the Execute method to work only on that particular content database.

public override void Execute(Guid contentDBId)
{

SPWebApplication webApp = this.Parent as SPWebApplication;
SPSiteCollection siteColl = webApp.ContentDatabases[contentDBId].Sites;
foreach (SPSite site in siteColl)
{
...

You should consider what lock type your code needs. To have the correct SPJobLockType set you might set it to a fix value in the constructor.