I downloaded code for a reservation event receiver from here: http://blog.sharepointsydney.com.au/post/Setting-up-multiple-calendars-for-meeting-room-bookings-prevent-double-booking.aspx
However, on the ItemUpdating it throws an "Object Reference Not Set to an Instance of an Object" error. By commenting out parts of the code and re-deploying I have narrowed the issue down to the line that gets the item's GUID:
string
guid_internal = collItems.List.Fields[
"GUID"
].InternalName;
When I modify it to something like "UniqueId" I get the "Value does not fall within expected range" error. Is there a better way to obtain the GUID of the calendar list item - or am I missing something? Full code below:
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; } } } }