Questions from Clients

27. April 2009 11:04 by sashashev in Active Directory, User Profiles  //  Tags: ,   //   Comments (0)

Ever go into a meeting where clients have asked you questions that you didn't know the answer to? No, that's never happened to me either. But a friend of mine thought every time he went into a meeting where a client asked him a (sensible) question he didn't know the answer to, he would list it here so that others could ponder the answers.I'll list the answers if I find them - Whoops - I mean if he finds them.

  1. Can the mysites left hand side nav contain different items by default on creation?
  2. Can you prevent users from creating subsites under my sites?
    1. Apparently yes - http://www.sharepointblogs.com/tbaginski/archive/2006/11/14/how-to-prevent-creation-of-sub-sites-within-moss-2007-my-sites.aspx
  3. Can you change the users display name?
    1. Yes. - http://www.21apps.com/sharepoint/user-profiles-why-do-my-changes-not-show-in-other-sites/ Basically just need to change or remap the name field in user profile properties in Central Admin.
  4. Once users are imported from AD, can you clear them all out?

 

Updating Active Directory From SharePoint

SharePoint out of the box supports only one way replication of user from AD to SharePoint which ofcourse means that when users update their profiles in their Mysites it doesn;t get replicated back to AD.

Even worse, their properties can get overwritten during the next profile import from AD.

The 2 recommended methods for updating AD from SharePoint that I have heard of are..

  1. Microsoft Identity Lifecycle manager
  2. Bamboo Solutions User Sync

From my little research the Bamboo Solutions seems to be a lot better. - ee review here - http://www.sharepointreviews.com/component/content/article/50-user-management/102-User-Profile-Sync-Web-Part-by-Bamboo-Solutions.html

ILM requires creating an import file from SharePoint - Already sounds too complicated if you ask me.

If anyone has experience with this, I would love to hear some feedback.I will probably end up using the Bamboo Solution so will be able to provide some feedback soon.

   

Creating a staff Directory in SharePoint Part 2 - People Search

In part 1 we looked at creating a Staff Directory using the User Information List. This time we'll attempt it with the People Search.

To begin with obviously we need to be able to search find people using the search. I have already set up a site using the Search Center  site template. The only problem is I am getting no results when searching for people.



I followed these instructions. - http://groups.google.com/group/microsoft.public.sharepoint.portalserver.development/browse_thread/thread/6f01af3e9da9e0b2/3caa0e3d6d1237c1

and it now works.

 



The first thing we can explore is what happens when we click edit on the page. Remembr that the search results page is actually a publishing page which is why it sits in a /pages directory.

 


Looking at this page in edit mode can provide some insight into what all those search web parts in the web parts gallery do. The capabilities of this page are beyond the scope of this article but will definitely be revisited in another article.

One of the requirements of the staff directory is that users should be able to click on a letter like this..

 

This was easily achieved by modifying the script found here - http://www.ramonscott.com/wordpress/?p=8

to look like this.

 

peoplesearch.txt (1.85 kb)


Next we want to customise the layout of the search results themselves. As with most of the web parts you will need to edit the XSL. Before you do though note that there appears to be a bug that throws an error every time you edit the XSLT. You can ignore it but unfortunately you can't see any changes you make until you publish the page. More info here - http://www.sharepoint-tips.com/2007/04/error-item-with-same-key-has-already.html

Instructions on customisation can be found here - http://www.sharepointology.com/development/customize-the-people-search-results-part-1/ and here - http://www.sharepointology.com/development/customize-the-people-search-results-part-2/

I was going to provide some of these instructions myself but these articles explain them really well.

Just to add a few finishing touches we can adjust the search dropdown options by mofidying propeties of searchbox.

 



I added favourite Cake and it now looks like.

 

Creating a staff Directory in SharePoint Part 1 - User Information List

Staff directories are a very common request for Intranets. Oddly SharePoint doesn't have a feature called Staff Directories but it contains many bits and pieces that can help build one.

i.e People Search, Custom user properties, My sites, People and Groups page.

There are also out of the box solutions that you can purchase from http://www.bamboosolutions.com such as http://store.bamboosolutions.com/p-41-user-directory-web-part-release-14.aspx

Or you can write code such as http://blogs.syrinx.com/blogs/sharepoint/archive/2007/10/05/sharepoint-2007-face-book-web-part.aspx

This article is to demonstrate how far we can go with just out of the box configuration trying various methods.

Method 1 - Using the User Information List 

################### Read this First ################################

Before you try this at home, please note that this solution is very limited. I am making notes as I attempt various methods and these articles are my findings not neccesarily the best solutions.

A better solution is found in part 2 of this article - http://blog.sharepointsydney.com.au/post/Creating-a-staff-Directory-in-SharePoint-Part-2-People-Search.aspx

Pros of this method

  • Very easy to set up
  • Does a good basic job 
  • Some decent styles and info available OOTB

Cons

  • Can't create own styles
  • Content doesn't synch with SharePoint Profiles (This may be fixable with Bamboo Solutions User Sync)
  • As users are removed from SharePoint they still remain in this list (This may be fixable with Bamboo Solutions User Sync)
  • Can't edit the page that results appear on. E.G Can't add web parts.
  • Can't search for users. Can only group by SharePoint groups.
  • When users update their details in MySites it takes a while for the UIL to reflect the changes. This is because syncing is done by a Timer Job called "Profile Synchronization" which runs by default once an hour.

 More info: http://sharepointsherpa.com/2008/01/31/employee-directory-using-user-information-list-in-sharepoint-2007/

As part of the experiment I will use the Personalization Site Template to create a dedicated Staff Directory site for no particular reason other than I want to see what this site template does.

So here is what the new site looks like. It is just a normal site but it contains a couple of filters preloaded on the  page. It also applies a link to this area directly to the creators mysites section.

Now let's go to the People and Groups page and see what our options are.

 






In this image you can see that I have actually jumped a few steps ahead.

Really all that I have done is created a few groups - Sales, Marketing etc. Under Settings -> 'Edit Group Quick Launch' you can define which groups to show in the Quick Launch on the left.
In our example the client would like to be able to browse by department so we can either create groups to represent each department or perhaps these departments already exist if you are using AD.

Next notice in the top right dropdown that we have created a new view called Staff Directory. You could create as many views as you like perhaps even filtering by location. Or alternatively instead of using the groups in quick launch you could use the views to filter by dept instead.

Note: For some reason list settings option only appears from the top level site which is where you go to create custom views.

 


Here is where we start the limitations of this approach. You can create a new view but the properties that are displayed in that view seem to be limited to these.

 



Not sure at this point if you can add more. This may not be a huge limitation as all we areally want this view fo ris to display some basic info about the users and if they want more they can really click through to the user MySite page.

The other bit of customisation for this view is that you can select different styles for displaying the info. 


I'm trying to find if you can create your own styles but can't find any info.

You can open any of the views of the UIL from SharePoint Designer by opening the root site but the only options available appear to be the same as you get from the browser view.

On thing I noticed is that a ListViewWebPart is used to display the info but can't find any info on editing styles for LVWP either.

At this point this solution is not looking flexible enough for me so I am abandoning it and moving onto trying the People Search instead in part 2 of this artilce.

 

Custom fields & Missing Fields in Content Query Web Part

11. April 2009 12:31 by sashashev in reskining, web parts  //  Tags: ,   //   Comments (0)

I was trying to format the layout of the Custom Query Webpart similar in fashion to instructions found at http://www.heathersolomon.com/blog/articles/CustomItemStyle.aspx.

The problem was that no matter what I did in CQWP based on the announcements list the title and image appeared but the body text was not showing up.

After reading a few articles including http://martijnmolegraaf.blogspot.com/2008/12/configuring-and-customizing-content_20.html I realised that body was a custom field and so I needed to export the webpart.
Edit the exported webpart file with all my custom fields.

The line to edit looked like

<property name="CommonViewFields" type="string">
PublishingRollupImage,Image;Created,DateTime;Body,Note;EncodedAbsUrl,Computed;FileDirRef,Lookup;
</property>

Note the name followed by datatype.

Then import the webpart back in and use it as you would any other CQWP.

Editing skins with SharePoint Designer

7. April 2009 08:56 by sashashev in reskining, SharePoint Designer  //  Tags: , ,   //   Comments (0)

Editing skins with designer can be frustrating due to the many quirks in the process.

For a good starting point read here - http://www.sharepointblogs.com/tigirry/archive/2007/07/27/easy-way-of-editing-customized-theme-in-moss-2007.aspx

Some additional tips.

After you edit CSS files don't swich themes until you copy all your changes back to the theme.css file in the 12 hive otherwise SharePoint will overwrite your changes.

Every time you change themes SharePoint puts a local copy of the theme folder copied from the 12 hive which overwrites the current themes folder.

Only 1 theme folder per site collection appears in Designer.

Also as an extra note in the Masterpage section of sesttings, the system Masterpage option is used for the document center masterpage.

It appears the difference between the SIte Master Page and System Master page is primarily the quick launch. Which becomes the treeview in the System Page.

 

 

 

Developing for SharePoint on XP

3. April 2009 10:58 by sashashev in SharePoint Development  //  Tags: , , ,   //   Comments (0)

There are many articles on how to do SharePoint development on an XP pc. E.G http://fernandof.wordpress.com/2008/02/11/how-to-install-the-sharepoint-2007-vs-2005-extensions-on-a-workstation/

The question is does this give you the same experience as the recommended method of developing directly on a SharePoint server?

The bottom line is NO. The reason is that these methods still won't allow you to connect to a SharePoint web.

i.e Anything like this won't work

this._Web = SPContext.Current.Web; or

this._Web = new SPSite(http://<IP_ADDRESS>).OpenWeb();

In other words you can compile but to see the results you will have to deploy to a SharePoint server.

The only exception to this rule is with web parts where code doesn't actually interact with the SharePoint object model and is just a standalone web part. Then you can test your web part by creating a web project with web part zones and run your web part from there.

If that hasn't put you off here are a couple of extra steps you may need to get going with SharePoint dev on XP.

1)  Copy all the DLLs out of the GAC of SharePoint install.

From http://mossofall.blogspot.com/2007/05/how-to-get-microsoftsharepoint-dlls-out.html

So, to extract these DLLs (for example in the c:\temp folder), I use a classic XCOPY command in command line from the folder C:\windows\assembly\ :
XCOPY GAC_MSIL c:\temp /

Then use a normal windows search to find all dll in temp folderabd copy out the SharePoint related ones.



Copy the DLLS to your local GAC. i.e to C:\windows\assembly

Do an IISRESET.

 2) If you get a personalization web.config error when testing we parts in local web part zone enabled Site

Make sure you set personalization on your web part manager off for testing locally

 <asp:WebPartManager ID="uiWPManager" runat="server" Personalization-Enabled="false"></asp:WebPartManager>

 

 

Setting up multiple calendars for meeting room bookings & prevent double booking

31. March 2009 16:57 by Eric in calendar, Event Handlers  //  Tags: ,   //   Comments (3)

A common usage for Sharepoint is meeting room bookings.

This article will provide one way of elegantly handling this scenario with some simple configuration but then we'll take it a step further by getting under the hood of WSS and adding some validation so that a room can not be double booked.

 

Add a calendar

Firstly we need to add the calendar list we are going to use.

On the parent page of where the calendar will reside use the site actions menu to create a new Calendar.

 

Give the calendar a descriptive name such as Book Meeting Rooms.

 

Add a new column

From the calendar settings choose "Create column" under the Columns options.

Name this column "Meeting Room" of type "Choice" and add some entries for each meeting room name.

 

This column will be used as a filter so that users can select a specific meeting room view.

 

Create Views

From the settings menu on the calendar choose create view.

 

Click Calendar View.

Name your view after one of the meeting rooms and add filtering criteria as below.

 

Repeat these steps until you have created a view for all Meeting Rooms.

Now the user can select which room they would like to see the availability for by selecting from the view drop down list in the top right of the calendar page.

 

One last touch - Displaying the room name in Month View.

When you are in month view by default the Title of the entry is visible.

  

The calendar month view only displays the title column by default.

In week view and day view you can select a second column to be displayed but in month view for some strange reason this is not possible.

The trick is to create a new calculated column that is a combination of the fields you would like to see.

In this example the Meeting room name followed by the title in a column I have called Summary.

 Then go into the calendar view and select Summary as the Month View Title.

 Now the month view displays the meeting room as well as the title

  

 Stay tuned for part 2 where we get technical and look at event handlers in Sharepoint!!

 

How to Prevent Duplicate Bookings in a Sharepoint Calendar List

We recently had a customer request a feature addition to the Calendar List.  The feature they wanted to add would prevent the user from being able to book a meeting room for a time in which the meeting room was already used.  For more information on adding a Meeting Room column, see the previous article.  For example, we have made a booking for the Earth Room on 25/9/08 at 4:00pm:

 

 

Attempting to create a new item on 25/9/08 from 4:30pm to 5:00pm can be done:

 

 This 'How To' will show you how to prevent this from happening.


Create an Event Listener
1.     Open Visual Studio and create a new class library project.
2.     Add a reference to Microsoft.Sharepoint.dll (the dll can be found in %Program Files%\Common Files\Microsoft Shared\web server extensions\12\ISAPI on the the server running WSS).
3.     Add a new code file and name it PreventDoubleBooking.cs.

 

 4.     In PreventDoubleBooking.cs, add the following code:

using System;
using Microsoft.SharePoint;


namespace Webcoda.WSS.Calendar.Events
{
    class PreventDoubleBooking: SPItemEventReceiver
    {
        /// <summary>
        /// This event is triggered when the user adds a new item
        /// </summary>
        /// <param name="properties"></param>
        public override void ItemAdding(SPItemEventProperties properties)
        {
            //Our query string variable
            string strQuery = null;

            try
            {
                //Get the Sharepoint site instance
                using (SPWeb oWebsite = new SPSite(properties.SiteId).OpenWeb(properties.RelativeWebUrl))
                {
                    
                    //Get the collection of properties for the Booking item
                    SPListItemCollection collItems = oWebsite.Lists[properties.ListTitle].Items;

                    //Get the Calendar List that we will be querying against
                    SPList calendar = oWebsite.Lists[properties.ListId];

                    //Get the internal name of the fields we are querying. 
                    //These are required for the CAML query
                    string start_internal = collItems.List.Fields["Start Time"].InternalName;
                    string end_internal = collItems.List.Fields["End Time"].InternalName;
                    string MeetingRoom_Internal = collItems.List.Fields["Meeting Room"].InternalName;

                    //Get the query string parameters
                    string start_str = properties.AfterProperties[start_internal].ToString();
                    string end_str = properties.AfterProperties[end_internal].ToString();
                    string MeetingRoom_str = properties.AfterProperties[MeetingRoom_Internal].ToString();

                    //Construct a CAML query
                    SPQuery query = new SPQuery();

                    //Create the CAML query string that checks to see if the booking we are attemping
                    //to add will overlap any existing bookings
                    strQuery = string.Format(@"

    <Where>
    
        <And>
            <Or>
            
                <Or>
                    <And>
                       <Leq>
                          <FieldRef Name='EventDate' />
                          <Value Type='DateTime' IncludeTimeValue='TRUE'>{0}</Value>
                       </Leq>

                       <Gt>
                          <FieldRef Name='EndDate' />
                          <Value Type='DateTime' IncludeTimeValue='TRUE'>{0}</Value>
                       </Gt>
                    </And>

                    <And>
                       <Lt>
                          <FieldRef Name='EventDate' />
                          <Value Type='DateTime' IncludeTimeValue='TRUE'>{1}</Value>
                       </Lt>

                       <Geq>
                          <FieldRef Name='EndDate' />
                          <Value Type='DateTime' IncludeTimeValue='TRUE'>{1}</Value>
                       </Geq>
                    </And>
                </Or>
                
                <Or>
                    <And>
                       <Leq>
                          <FieldRef Name='EventDate' />
                          <Value Type='DateTime' IncludeTimeValue='TRUE'>{0}</Value>
                       </Leq>

                       <Geq>
                          <FieldRef Name='EndDate' />
                          <Value Type='DateTime' IncludeTimeValue='TRUE'>{1}</Value>
                       </Geq>
                    </And>

                    <And>
                       <Geq>
                          <FieldRef Name='EventDate' />
                          <Value Type='DateTime' IncludeTimeValue='TRUE'>{0}</Value>
                       </Geq>

                       <Leq>
                          <FieldRef Name='EndDate' />
                          <Value Type='DateTime' IncludeTimeValue='TRUE'>{1}</Value>
                       </Leq>
                    </And>
                </Or>
                
            </Or>
        
            <Eq>
                <FieldRef Name='Meeting_x0020_Room' />
                <Value Type='Choice'>{2}</Value>
            </Eq>
            
        </And>
        
    </Where>
    <OrderBy>
        <FieldRef Name='EventDate' />
    </OrderBy>
", start_str, end_str, MeetingRoom_str);

                    //Set the query string for the SPQuery object
                    query.Query = strQuery;

                    //Execute the query against the Calendar List
                    SPListItemCollection existing_events = calendar.GetItems(query);
                    
                    //Check to see if the query returned any overlapping bookings
                    if (existing_events.Count > 0)
                    {
                        //Cancels the ItemAdd action and redirects to error page
                        properties.Cancel = true;

                        //Edit the error message that will display on the error page
                        properties.ErrorMessage += "This booking cannot be made because of one or more bookings in conflict. <BR><BR>";

                        //Here you can loop through the results of the query
                        //foreach (SPListItem oListItem in existing_events)
                        //{
                        //   ....
                        //}

                        properties.ErrorMessage += "Please go back and schedule a new time.";
                    }
                    
                }
            }
            catch (Exception ex)
            {
                //Cancels the ItemAdd action and redirects to error page
                properties.Cancel = true;

                //Edit the error message that will display on the error page
                properties.ErrorMessage = "Error looking for booking conflicts: " + ex.Message;
            }
          
        }

        /// <summary>
        /// This event is triggered when the user edits an calendar item
        /// </summary>
        /// <param name="properties"></param>
        public override void ItemUpdating(SPItemEventProperties properties) {

            string strQuery = null;

            try {

                //Get the Sharepoint site instance
                using (SPWeb oWebsite = new SPSite(properties.SiteId).OpenWeb(properties.RelativeWebUrl)) {

                    //Get the collection of properties for the Booking item
                    SPListItemCollection collItems = oWebsite.Lists[properties.ListTitle].Items;

                    //Get the Calendar List that we will be querying against
                    SPList calendar = oWebsite.Lists[properties.ListId];

                    //Get the internal name of the fields we are querying. 
                    //These are required for the CAML query
                    string start_internal = collItems.List.Fields["Start Time"].InternalName;
                    string end_internal = collItems.List.Fields["End Time"].InternalName;
                    string MeetingRoom_Internal = collItems.List.Fields["Meeting Room"].InternalName;
                    string guid_internal = collItems.List.Fields["GUID"].InternalName;

                    //Get the query string parameters
                    string start_str = properties.AfterProperties[start_internal].ToString();
                    string end_str = properties.AfterProperties[end_internal].ToString();
                    string MeetingRoom_str = properties.AfterProperties[MeetingRoom_Internal].ToString();
                    string guid_str = properties.AfterProperties[guid_internal].ToString();

                    //Construct a CAML query
                    SPQuery query = new SPQuery();

                    //Create the CAML query string that checks to see if the booking we are attemping
                    //to change will overlap any existing bookings, OTHER THAN ITSELF
                    strQuery = string.Format(@"

    <Where>
        <And>
        
            <And>
                <Or>
                
                    <Or>
                        <And>
                           <Leq>
                              <FieldRef Name='EventDate' />
                              <Value Type='DateTime' IncludeTimeValue='TRUE'>{0}</Value>
                           </Leq>

                           <Gt>
                              <FieldRef Name='EndDate' />
                              <Value Type='DateTime' IncludeTimeValue='TRUE'>{0}</Value>
                           </Gt>
                        </And>

                        <And>
                           <Lt>
                              <FieldRef Name='EventDate' />
                              <Value Type='DateTime' IncludeTimeValue='TRUE'>{1}</Value>
                           </Lt>

                           <Geq>
                              <FieldRef Name='EndDate' />
                              <Value Type='DateTime' IncludeTimeValue='TRUE'>{1}</Value>
                           </Geq>
                        </And>
                    </Or>
                    
                    <Or>
                        <And>
                           <Leq>
                              <FieldRef Name='EventDate' />
                              <Value Type='DateTime' IncludeTimeValue='TRUE'>{0}</Value>
                           </Leq>

                           <Geq>
                              <FieldRef Name='EndDate' />
                              <Value Type='DateTime' IncludeTimeValue='TRUE'>{1}</Value>
                           </Geq>
                        </And>

                        <And>
                           <Geq>
                              <FieldRef Name='EventDate' />
                              <Value Type='DateTime' IncludeTimeValue='TRUE'>{0}</Value>
                           </Geq>

                           <Leq>
                              <FieldRef Name='EndDate' />
                              <Value Type='DateTime' IncludeTimeValue='TRUE'>{1}</Value>
                           </Leq>
                        </And>
                    </Or>
                    
                </Or>
            
                <Eq>
                    <FieldRef Name='Meeting_x0020_Room' />
                    <Value Type='Choice'>{2}</Value>
                </Eq>
                
            </And>
        
            <Neq>
                <FieldRef Name='GUID' />
                <Value Type='GUID'>{3}</Value>
            </Neq>
        
        </And>
        
    </Where>
    
    <OrderBy>
        <FieldRef Name='EventDate' />
    </OrderBy>
", start_str, end_str, MeetingRoom_str, guid_str);

                    //Set the query string for the SPQuery object
                    query.Query = strQuery;

                    //Execute the query against the Calendar List
                    SPListItemCollection existing_events = calendar.GetItems(query);

                    //Check to see if the query returned any overlapping bookings
                    if (existing_events.Count > 0) {

                        //Cancels the ItemAdd action and redirects to error page
                        properties.Cancel = true;

                        //Edit the error message that will display on the error page
                        properties.ErrorMessage += "This booking cannot be made because of one or more bookings in conflict. <BR><BR>";

                        //Here you can loop through the results of the query
                        //foreach (SPListItem oListItem in existing_events)
                        //{
                        //   ....
                        //}

                        properties.ErrorMessage += "Please go back and schedule a new time.";
                    }

                }
            } catch (Exception ex) {

                //Cancels the ItemAdd action and redirects to error page
                properties.Cancel = true;

                //Edit the error message that will display on the error page
                properties.ErrorMessage = "Error looking for booking conflicts: " + ex.Message;
            }

        }

        
    }
}

Register Assembly into GAC

We want the WSS server to call our event code instead of the built-in code that allows us to make a double booking.  In order for our new events to be available to the WSS server, we need to register our assembly into the GAC.  For this to happen, the assembly being registered must be strongly typed and signed. 

1.    To do this, follow the instructions here:  http://www.dotnetspider.com/resources/1620-Strong-Naming-And-Installing-Assembly-into-GAC.aspx.  Once you have added the Key File into the project, your solution should look similar to this:

 

 2.    When you get to the “Installing Assembly into the GAC” section, instead of running the gacutil.exe command line utility, you can simply drag your compiled project assembly into the GAC:

 

Register Events

Now that the assembly is registered into the GAC, we still need to register the events in the WSS Server.  To do this, we can use a tool called EventHandlerExplorer.  Download, source code, and demo instructions can be found here:  http://www.u2u.info/Blogs/Patrick/Lists/Posts/Post.aspx?ID=1547.  

1.    Once you’ve downloaded the tool, run the EventHandlerExplorer.exe on the WSS server.  In the “Enter URL for the site collection you want to explore” field, type the URL of your Sharepoint site, then click “Explore”.  If you get an “Access is denied. (Exception from HRESULT: 0x80070005 (E_ACCESSDENIED))” error, then you are probably not running the EventHandlerExplorer app in the context of a Site Collection Administrator account. On the WSS Server, go to Central Administration -> Application Management -> Site Collection Administrators and add yourself as the Secondary site collection administrator. Be sure that you add yourself to the correct site collection.  Alternatively, run the EventHandlerExplorer as the person who is listed as a Site Collection Administrator (right-click on EventHandlerExplorer.exe -> Run as...).

 

 

If you get through without an “Access is dened…” error, you should be able to expand your site, then subsite until you get to the List that contains your Calendar.  In our case, we have a subsite called “Sandbox” and the List containing the Calendar is called “Book Meeting Room”.  So, we would expand the Sandbox tree, then expand the Lists tree node to expose the “Items” node and “Event Handlers” node.

 

To see which events are registered for that list, you must double-click the “Event Handlers” node.  At this point, however, you probably won’t have any events registered and therefore double-clicking will do nothing.

With the Book Meeting Room node highlighted, click the Load Assembly button, and then select the .dll we’ve created.  Then, in the Class drop down, select PreventDoubleBooking.  For sequence, type “0”.  I think this only comes into play if you want to have multiple delegates for the same event, but I’m not 100% sure.  And finally, for Event Type, select ItemAdding.  The values you selected should look like this:

 

Then click the “Add Handler” button.  Once that event has been registered, change the Event Type to ItemUpdating, then click the “Add Handler” button again.  Even though you just registered two events, the Event Handlers node doesn’t show a “plus” sign next to it, indicating it has child nodes.  This is because you must first double-click the Event Handlers node which will then show the “plus” sign.  Expand this node to see the two Events you just registered.

 

Testing Our Code

That’s it!  You’re finished!  Now let’s test our changes.  To test our code, we’re going to book a meeting room for an hour at 4pm on 26/9 and then try to book the same meeting room at 4:30pm.

 

 But look what happens when we try to add the booking at 4:30pm for the same meeting room on the same day.

 

An error is generated and the booking is not made!

 

Download 

You can download the entire project here:  Webcoda_PreventDuplicateBookings.zip (5.41 mb)

 

More Information

Any changes to the code you make will require you to recompile the assembly, reinstall your assembly into the GAC, and finally reregister your events.  If you would like to change the query used in the sample code, a tool that may help is U2U Caml Query Builder which can be found here:  http://www.u2u.info/Blogs/karine/Lists/Posts/Post.aspx?ID=12.  To get familiar with the Microsoft.SharePoint namespace, here is a link to the documentation you will need:  http://msdn.microsoft.com/en-us/library/microsoft.sharepoint.aspx.

Also, here is a link to “Getting Started with Programmatically Customizing a SharePoint Web Site in Visual Studio”:  http://msdn.microsoft.com/en-us/library/ms479423.aspx.

How to customize a Sharepoint theme

31. March 2009 16:29 by sashashev in reskining  //  Tags: , ,   //   Comments (0)
In this article, we are going to explore how to modify an existing Sharepoint theme.  This process is pretty straight forward and this article provides a few tips and tricks along the way.  Please note this process requires some previous CSS experience.

Copy the theme directory you want to customize

 

1.    Navigate to THEMES folder:  %Program Files%\Common Files\Microsoft Shared\web server extensions\12\TEMPLATE\THEMES.  Copy theme folder you want to modify and rename the copied folder.  Here, we copied the BREEZE2 folder and renamed it to DERWENT.

 

Update the copied files with the new theme information

2.     Navigate into the new theme folder and rename the .INF to the name of the new theme.  Here we renamed BREEZE2.INF to DERWENT.INF.

 

 3.     Open the INF that was just renamed and update all the entries with the new name of your theme.  A global search and replace (Ctrl+H in most editors) will take care of this easily for you.  Here we changed all the Breeze2 entries to Derwent.

 

 4.    Next, we need to add the new theme into the XML file so that Sharepoint knows it exists.  To do this, we are going to edit the SPTHEMES.XML file located in C:\Program Files\Common Files\Microsoft Shared\web server extensions\12\TEMPLATE\LAYOUTS\1033.   Add the following <Templates> entry into the XML file:

For now, leave the <Thumbnail> and <Preview> tags as they are, we will get to these later.  They simply specify which images will show up when the user is previewing a theme.  Since we don’t have a screenshot of our new theme yet, we do not have anything to put here.  Your XML file should look similar to the one below:

Make CSS changes to the theme

5.    Next, we are going to edit the theme.css style sheet located in the new theme folder (for example, C:\Program Files\Common Files\Microsoft Shared\web server extensions\12\TEMPLATE\THEMES\DERWENT\theme.css).

This is where all of the hard work comes in.  In order to work more efficiently, it is a good idea to save a couple of the Sharepoint pages locally (File -> Save As… from IE, select Webpage, complete (*.htm;*.html) for Save as type).  

 

This will allow you see the CSS changes on a local page without have to perform an iisreset (See Step 6) on the server.

For the pages I saved locally, the .htm files seemed to link to “Derw1011-65001.css” style sheet instead of the expected theme.css file.  It turns out the “Derw1011-65001.css” is actually a copy of the theme.css style sheet.  (The “65001” in the filename comes from the codepage setting in the .INF file).  So when you save a page locally, it will also save the “Derw1011-65001.css” file since the .htm file links to this file.  Edit the “Derw1011-65001.css” file locally and once you’re happy with the changes, copy the contents of this CSS file into the theme.css file located on the server (after making a backup, of course).

Microsoft has provided some documentation (http://msdn.microsoft.com/en-us/library/ms438349.aspx) on the CSS classes used in core.css which shares some common CSS classes with theme.css, however I found it easier to examine the CSS information using IE Web Developer or Firebug.

Force Sharepoint to recognize changes

6.    Now that you finished with your CSS changes, you need to perform an iisreset from the command prompt in order for the Sharepoint server to recognize the changes.   

To do this, start the command prompt (Start -> Run… -> type cmd -> Enter).

   Type iisreset, then hit enter. 

Note: be careful performing this command on a server in a production environment as it will sever any active connections to all of the websites being hosted on the server.

Apply customized theme to site

7.    Next, we are going to apply the newly created theme.  Open a browser and navigate to the Sharepoint page that you want to apply the new theme to.  Click Site Actions -> Site Settings.

 Once in Site Settings, click “Site Theme” from the Look and Feel section:

This will bring up a list of all available themes that you can apply to the site.  You should see the theme we added in the previous steps.  Below, you can see the Derwent theme we added in the example:

Highlight the theme you added, and click apply. 

Update preview image

8.    Notice the Preview image shown to the left of the list of themes.  You will still see the preview image of the copied theme.

In order to update that image with a preview of our own theme, we need to grab a screenshot of our new theme and add it to the proper location.

Navigate to the home page of the site you changed the theme for.  In our example, we would navigate to the My Home page.

Take a screenshot of this page and resize it to about 350 x 230 pixels using your favorite image editor (i.e. SnagIt). 

Save the screenshot in a standard format (.gif, .jpg, or .png).


9.    Next, we need to add the image to the Sharepoint server so that the image will appear when a user is attempting to select a theme.

Copy the screenshot image you created in Step 8 into %Program Files%\Common Files\Microsoft Shared\web server extensions\12\TEMPLATE\IMAGES.  Here you can see I’ve named my screenshot Derwent_Preview.gif:

 10.     Repeat Step 4, updating the <Preview> and <Thumbnail> attributes in the SPTHEMES.XML file with the new name of your preview image, as shown below:

11.     Repeat Step 6 to complete the changes on the Sharepoint server.

12.    Next, we need to see our changes on the Sharepoint site.  Repeat Step 7 to navigate to the Site Themes Settings Page.

Notice that the image you just created isn’t showing up in the preview?  In order to see the changes you just made to the theme, you must first apply another theme (any theme listed - it doesn’t matter which one), and then reapply the new theme. This is required to see ANY changes you have made to theme, if you already have the theme applied.

Tips for Installing MOSS 2007 (3.0) on Windows Server 2008

31. March 2009 16:17 by sashashev in Server Configuration  //  Tags: ,   //   Comments (0)

Slipstream MOSS 3.0 Service Pack 1

At the time this article was written, Microsoft has only released a version of the MOSS 3.0 installer package without integrating the already available MOSS 3.0 SP1.  When you attempt to install MOSS 3.0 using the installer package on the Windows Server 2008, you will get an error from the Program Compatibility Assistant stating that a service pack is required in order to install WSS 3.0.  To circumvent this, we need to slipstream the SP1 bits into the MOSS 3.0 installer files.  Basically, this involves extracting the SP1 EXE files into the Upgrades folder of the MOSS 3.0 installer files.  Then, running the MOSS 3.0 installation should work.

How To

Matt Hester has compiled information on this issue and come out with a very helpful screencast which takes the user through a step-by-step process of slipstreaming SP1 into the installation.  Before beginning this video, make sure you have a local copy of the MOSS 3.0 installation files as we will need to add files to the Upgrades folder.  The screencast can be found here:

http://blogs.technet.com/matthewms/archive/2008/02/15/screencast-how-to-install-office-sharepoint-server-2007-on-windows-server-2008.aspx.

Error Using SharePoint Products and Technologies Configuration Wizard

After installing MOSS 3.0, you should be taken to the SharePoint Products and Technologies Configuration Wizard.  After specifying the Database Server, Database Name, Database Account, and Database Password, you may encounter an error stating “Internet Information Service is not installed. You must have Internet Information Service installed in order to use the Sharepoint Products and Technologies Configuration Wizard.”  If you receive this error, read the following two sections.

Error Source

If you used the Add Roles Wizard to install IIS 7.0 (as we did in Matt Hester’s How To),  we were given the default installation containing a minimum set of role services. We will need additional IIS 7.0 role services, such as IIS6 Metabase which provides a legacy interface to applications requiring IIS 6 backward compatibility.

Install Additional Features

We can use the following script to install available feature packages, namely IIS-Metabase.  Running the following script will give us the full IIS 7.0 installation, which installs all available feature packages.  If there are feature packages you do not need, you should change the script to install only the packages you require.

Code Snippet:

Excerpted from:

http://technet.microsoft.com/en-us/library/cc730716.aspx

Webcoda, SharePoint Consultants & Web Development

SharePoint Development Sydney is a crack team of SharePoint Consultants and SharePoint Developers.

We can't tell you their names or show their faces on TV but if you need a SharePoint job done right, call them on +61 2 9370 3602 or email us at info@sharepointsydney.com.au

Persecuted by the Government and shunned by society they developed their SharePoint skills in back streets and labor camps where other programmers wouldn't dare to tread. 

During a trek through the Himalayas they stumpled upon the fabled Mossy Yak who shared his SharePoint knowledge of how to attain Nirvana through a series of Workflows and Event Handlers. Their mission is to spread this knowledge through-out the world to bring peace, harmony and document version control to all .

 

Month List