Belgian user groups: Community day event

Today the first Belgian community day organized by five user groups was held in Keerbergen. What a day to get to the destination! Keerbergen is a village located next to Werchter where the yearly Rock Werchter festival takes place.
And today was the first day of the festival so there were a lot of cars stuck in the small roads leading to the festival. But I was lucky because most of the traffic jams were in the opposite direction.
And then again not so lucky because I don't have tickets to the festival ;-)

So now back to the event, it was a good opportunity to network with peers and learn something new in one of the technical sessions.

First session: SharePoint Community tools (BIWUG)
Joris Poelmans presented a general overview of development tools that can be used to help on SharePoint and WSS development. A few of the tools I already use and are listed in my Resources page. The new ones I did not yet know were:

  • AppPool recycler for SharePoint Devs: a little tool that sits in the windows tray and lets you choose an IIS application pool to recycle without having to go via IIS or doing an IISRESET.
  • WSPBuilder: a Visual Studio project template that builds your manifest.xml, ddf and cabinet file ollowing a 12 hive directory structure.
  • U2U CAML Query Builder feature: a SharePoint feature that adds action to build a CAML query via the interface and then saves the query to a document library. The query is then available for use in your custom developments. This is a feature developed by CAML Girl who was present in the audience!

Second session: Visual Studio Team System software lifecycle (VISUG)
Pieter Gheysen presented Visual Studio Team system in the new Visual Studio 2008 (using the Orcas VPC). Nice overview of the functionalities.

After that there was a nice dinner and time to network and get in contact with new people.
Thanks to the organizers!

 


New WSS3 development article on MSDN by Patrick Tisseghem and updated MOSS resources list

While catching up with new items in my RSS reader I learned that Patrick Tisseghem has just released another fantastic article series about WSS3 on MSDN:

These two articles go over the development process for WSS3 and MOSS 2007: setting up the development environment, basic development tools (Visual Studio Extensions for WSS3), using features, custom field controls, packaging it all into solutions (.wsp) and even a small sample on setting Code Access Security for web parts. Wow!
A must read for everyone starting out or already doing WSS3 development.

At the same time I've also updated my own list of WSS3 and MOSS 2007 resources I'm trying to keep up to date. It's not yet an extensive list of tools available but I'm trying to keep the list updated with tools I've already tried out.

 

Technorati tags: , , , ,

 


Problems with ClientScriptManager.GetWebResourceUrl in MOSS 2007 webparts (anonymous sites)

I have been struggling with some errors when using embedded resources in MOSS web parts.

My web part uses the ClientScriptManager.GetWebResourceUrl method to access an embedded resource. In this case it’s a JavaScript file that is compiled into the assembly.

Code snippet:

protected override void RenderWebPart(HtmlTextWriter output)

{

EnsureChildControls();

ClientScriptManager manager = this.Page.ClientScript;

string jsLibraryUrl = manager.GetWebResourceUrl(this.GetType(), "myresouce...");

string jsLibrary = string.Format("<script type=\"text/javascript\" language=\"JavaScript\" src=\"{0}\"></script>", jsLibraryUrl);

output.Write(jsLibrary);

//rest of code...

}

  • The web part is deployed to the web application’s bin directory by using a SharePoint solution.
  • Code Access Security for the web part’s assembly is set in the solution manifest.
  • My application is accessible by two Security Zones: Default and Internet. The Internet zone has been configured for Anonymous access.

Note: if you don’t know what and how embedded resouces can be used in ASP.NET 2.0 this is a good article from ASPAlliance.com: Embedding Resources in ASP.NET 2.0 Assemblies.

After development testing and deploying the web part on the web application I access the URL by using the Default zone and log in as an administrator. My web part works fine.
Next I log in by using the web application URL that has been extended and configured for anonymous access. Here I run into an error, a blank page is displayed showing just a 403 error.

403 FORBIDDEN

I went into debug mode and put a breakpoint in the CreateChildControls method of the web part. There I found that an exception was being generated by the following line:

string jsLibraryUrl = manager.GetWebResourceUrl(this.GetType(), "myresouce...");

The exception was System.UnauthorizedAccessException.

To resolve this I tried adding Read permissions to the IUSR_computername and the ASPNET users to the /bin directory of my web application. This solved the problem but is not a solution I can use on a production environment. Every time a new SharePoint solution is deployed to the web application the file permissions on the bin directory are reset by SharePoint anyway.

I googled for answers from people having similar problems. On a very nice post by Ryan Rogers about embedded resources there is a comment from someone with the same issue. There is no answer to the comment. Bummer… the problem is exactly the same as mine but no solution :-(

I tried installing the assembly in the GAC and this also solved the problem. As this is not an option for production I continued searching for other solutions.
After some more trial an error with CAS configuration I decided to use the SPSecurity.RunWithElevatedPrivileges method around the code calling the web resource.

Using this in combination with the Impersonate="true" in the SharePointPermission in CAS does it! Not setting the impersonation will raise a security exception when calling RunWithElevatedPrivileges.

This is what I ended up doing:

try

{

  SPSecurity.RunWithElevatedPrivileges(delegate()

{

  ClientScriptManager manager = this.Page.ClientScript;

  jsLibraryUrl = manager.GetWebResourceUrl(this.GetType(), "myresouce...");

});

}

catch (System.Security.SecurityException exc)

{

  System.Diagnostics.Trace.Write(exc.ToString());

}

CAS element:

<IPermission class="Microsoft.SharePoint.Security.SharePointPermission, Microsoft.SharePoint.Security, Version=12.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c"

UnsafeSaveOnGet="True" AllowUnsafeUpdates="True" ObjectModel="True" version="1" Impersonate="true" />

I’m still wondering if this is the good approach but since no other solution is available for the moment I’m happy with it.
If someone has a better solution I would love to hear about it.


 


Event handlers in WSS3 and MOSS 2007: some general notes and preventing a user update

Last week I was working on an event handler to prevent users from changing a value of a custom list item one an external service is busy processing some data.

Reading some information on event handlers I learned some important aspects about event handlers.

Deploy to the GAC: the assembly containing the event handler must be deployed to the Global Assembly Cache.

-Ed en -Ing events (asynchronous and synchronous events)
Event names ending on –ed like ItemUpdated, ItemDeleted and so on are called asynchronous events as they will execute after the action has been completed. At this stage you can no longer prevent something from being save or deleted.
The events ending in “ing” like ItemUpdating, ItemInserting and so on fire before the action is completed and are therefore called synchronous. In this case you can still intervene before the action is final.
The full list of available methods that can be overridden for SPItemEventReceiver can be found in the following MSDN article: http://msdn2.microsoft.com/en-us/library/ms437502.aspx

DisableEventFiring()
If you need to do an update to an item from within your event receiver you might end up in a recurring event being fired for the updates. To prevent this you can call DisableEventFiring() and then EnableEventFiring(). A small example for this:

public override void ItemUpdated(SPItemEventProperties properties)

        {

            //some handling here

            ListItem item = properties.ListItem;

            item["someproperty"] = "some value";

 

            this.DisableEventFiring();

            //save changes

            addedItem.Update();

            this.EnableEventFiring();

 

        }

When calling the Update method you might also consider using SystemUpdate() method which will do a SharePoint database updating without updating the time modified or versions of the item.

So now back to my event handler: I was looking for a way to know from within the event handler if it had been fired by a user action or by a system update. A system update is in my case a windows service opening the list item by using the object model.
As I’m using a schema.xml file to create the custom list I added a boolean field with the ReadOnly attribute set to true. This makes the custom field hidden in the edit form for the list item. When updating the item through the object model I do have access to the custom readonly field and can set its properties.

schema.xml snippet:

    ... ...

<Fields>

  <Field ID="{1FFDF566-D220-45e0-814D-34DB0E1A253D}" Name="Myreadonlyfield" StaticName="Myreadonlyfield" SourceID="http://schemas.microsoft.com/sharepoint/v3" Group="Groupname" DisplayName="SystemUpdate" Description="Hidden system field" Type="Boolean" ReadOnly="TRUE" Sealed="TRUE"></Field>

    </Fields>

       ...

</Fields>

My custom application sets the read only field to true before calling Update:

  item["fieldx"] = “some update”;

  item["SystemUpdate"] = true;

  item.Update();

As I’m using a synchronous event handler I can change the AfterProperties before these are saved into the database. This prevents the field from having a “true” value next time the item is updated.

public override void ItemUpdating(SPItemEventProperties properties)

       {

            bool isServiceUpdate = false;

            string modifiedStatus = Convert.ToString(properties.AfterProperties["somestatusfield"]);

 

            isServiceUpdate = Convert.ToBoolean(properties.AfterProperties["Myreadonlyfield"]);

 

            // Myreadonlyfield is always set to false except when the update comes from my custom application

            if (isServiceUpdate == false)

            {

 

                if (modifiedStatus.ToLower() == "invalid")

                {

                    properties.ErrorMessage = "This is an invalid choice...";

                    properties.Cancel = cancel;

                }

 

            }

            else

            {

                properties.AfterProperties["Myreadonlyfield"] = false;

            }

 

       }

I’m thinking maybe there is a much more efficient way of doing this but as I did not find any this way my solution. And what counts is it does the work.


And then here is a fantastic article series I found recently with very good information about event handlers in SharePoint 2007:
Brian Wilson - Event Handlers - Part 1: Everything you need to know about Microsoft Office SharePoint Server (MOSS) Event Handlers.

 

Technorati tags: , ,

 


Going to the Belgian Community Day

Coming 28th of June 2007, five IT Belgian User Groups are organizing a community day: BIWUG, VISUG, SQLUG, IT-Talks and Pro-Exchange. It's the first time I'll be attending a community and apparently it's also the first time the five groups are organizing a day together.

I'm a member of two of them: BIWUG and VISUG but been to more meetings organized by BIWUG. It's a really nice way to get to know people in the same work field and exchange experiences about our projects.

Looking forward to the event for the learning and the socializing with peers :-) 
See you there.

Register at: www.communityday.be

 

Technorati tags: , , , ,

Part III – MOSS 2007 Publishing page layout using a feature

This is the third and last post on creating site columns, publishing content types and page layouts using features:
Part I – Creating site columns, publishing content types and page layout using a feature
Part II – Creating publishing content types

This post describes how to create a publishing page layout and deploy it using a custom feature. This post goes further on what was already discussed in pat I and II. Now that we have a custom publishing site columns as well as custom publishing content types defined using a feature, the next step is to create the page layout.

Publishing page layouts map to the custom fields of a publishing content type. The files are placed in the Master page gallery (Site Actions > Site Settings > Modify All Settings > Galleries section > Master pages and page layouts).

1. Creating the page layout

The page layout can be created by using Visual Studio 2005. It’s really an .ASPX page and some basic Intellisense works for the SharePointWebControls and PublishingWebControls.
If you need information on how to create your custom page layout there is a very good article on MSDN: Customizing and Branding Web Content Management-Enabled SharePoint Sites (Part 1 of 3): Understanding Web Content Management and the Default Features.

Important to remember here is that you are dependant from the Master Page that will be used together with your page layout. In this article I’m using the default Blue Bland one; so all the default Content placeholders are available.

Snippet of the page layout (download all the files from the link at the bottom of the post):

Tip: to quickly create and test a page layout for my custom content types I sometimes use SharePoint Designer 2007 (SDP). Create the page layout by choosing “New > Page Layout” in the Master pages gallery. Be sure to choose your custom page layout:

Then open the page using SharePoint Designer. Add your HTML and design elements and drag your custom properties to the page. HTML page design is really not my thing so this is an easy way to add some tables and layout to the page. Once you have the page ready in SPD, save the file, check in and test it by creating a new page.
You can now use the HTML and controls from this page when creating your custom page layout using Visual Studio.
Note that SPD saves the page directly into the SharePoint database and not on the hard drive. So this is just a fast way to start up the creation of your page layout but it does not allow you to deploy the page easily to other servers.

2. Creating the provisioning xml schema

To provision the page layout and any used CSS, images or other files we create a XML file that will be picked up by the feature and install the files in the corresponding libraries in your publishing site.

In my example I have one custom page layout with just one image. I could as well have several images and CSS files installed using the same feature. I guess you get the idea with this image sample.

<Elements xmlns="http://schemas.microsoft.com/sharepoint/">

 

    <Module Name="ProductPageLayouts" Url="_catalogs/masterpage" Path="PageLayouts" RootWebOnly="TRUE">

 

                                <File Url="ProductDetail.aspx" Type="GhostableInLibrary">

                                                <Property Name="Title" Value="$Resources:pagelayout_product_name;" />

                                                <Property Name="MasterPageDescription" Value="$Resources:pagelayout_product_description;" />

                                                <Property Name="ContentType" Value="$Resources:cmscore,contenttype_pagelayout_name;" />

                                                <Property Name="PublishingPreviewImage" Value="~SiteCollection/_catalogs/masterpage/$Resources:core,Culture;/Preview Images/DefaultPageLayout.png, ~SiteCollection/_catalogs/masterpage/$Resources:core,Culture;/Preview Images/DefaultPageLayout.png" />

                                                <Property Name="PublishingAssociatedContentType" Value=";#$Resources:contenttype_productbase_name;;
#0x010100C568DB52D9D0A14D9B2FDCC96666E9F2007948130EC3DB0645
84E219954237AF3900ADB88465BE2C439798977662094183BC;#
"/>

                                </File>

 

                </Module>

                <Module Name="ProductLayoutImages" Url="Style Library" Path="Styles" RootWebOnly="TRUE">

                                <File Url="images/line.jpg" Name="product/images/line.jpg" Type="GhostableInLibrary" />

                </Module>

</Elements>

(Note: the value for PublishingAssociatedContentType above contains a break for HTML display reasons. You should put the value in one line)
I must say not much is available in the MSDN documentation about the schema for provisioning publishing pages. Like in other cases I looked at the PublishingLayouts feature delivered with the MOSS 2007 installation. This is a hidden feature that provisions the standard page layouts, master pages, etc for a MOSS Publishing site. You can find the feature here: C:\Program Files\Common Files\Microsoft Shared\web server extensions\12\TEMPLATE\FEATURES\PublishingLayouts.

Some clarifications to the schema elements:

<Module> element

<Module Name="[your module name]" Url="virtual path destination of the module elements " Path="path from within this feature">

PublishingAssociatedContentType property
This property specifies to which the page layout you are installing is mapped to. The syntax is
;#ContentTypeName;#ContentTypeID;#

GhostableInLibrary
Every <File> element has the property Type="GhostableInLibrary"
This property is important because it will install the file in the Master Page gallery, but the actual file content are still stored on the hard drive and not directly in the SharePoint database (as is the case if you create your page layout using SDP).

3. Wrapping it up: creating the feature

I’m using one single feature to create my custom publishing fields, custom publishing content type and custom page layout(s).

The feature now has the following structure:


Three XML files are referenced by the feature schema in the order in which they should be installed.

  1. myfields.xml: this file defines all my custom site columns
  2. ProductContentTypes.xml: this file defines my two custom publishing content types and uses the custom field defined in myfields.xml
  3. PageProvisionedFiles.xml: this file contains the provisioning for page layout and associated image

I think the order in which these files are referenced in the feature schema are important because the site columns must be created before the content types, and the content types must be created before the page layout can reference it.
So, I have no proof that this really executes in the order defined in the feature schema but I do assume it is the case. Maybe someone has found some documentation on this?

Feature schema:

<?xml version="1.0" encoding="utf-8"?>

<Feature  Id="787DCDC4-97F9-4f64-A771-D2A8B86DCADB"

          Title="My publishing content type"

          Description="$Resources:feature_description;"

          Version="1.0.0.0"

          Scope="Site"

          DefaultResourceFile="_Res"

                                  Hidden="FALSE"

          xmlns="http://schemas.microsoft.com/sharepoint/">

                <ActivationDependencies>

                                <!-- Add a dependency to the Publishing site-->

                                <ActivationDependency FeatureId="F6924D36-2FA8-4f0b-B16D-06B7250180FA" />

                </ActivationDependencies>

                <ElementManifests>

                                <ElementManifest Location="myfields.xml"/>

                                <ElementManifest Location="ProductContentTypes.xml"/>

                                <ElementManifest Location="PageProvisionedFiles.xml"/>

                </ElementManifests>

</Feature>

That’s it, the feature is complete.
All that needs to be done is copy the feature directory to “C:\Program Files\Common Files\Microsoft Shared\web server extensions\12\TEMPLATE\FEATURES\MyContentTypeFeature” and run the install command
 
stsadm -o installfeature -filename MyContentTypeFeature\feature.xml

This command can be used to install and test the feature. For a production environment I would recommend creating a SharePoint solution that installs the feature and all its files.

The feature can be downloaded here: publishingfeature.zip.
The zip file contains all the files discussed in the three posts as well as a batch file that installs and activates the feature. Just update the URL to your site name first.

 

Copyright © 2007 Katrien De Graeve.