I'm using EWS Managed API 2.0. I'm using the Calendaring part where you can book appointments as follows :
Appointment appointment = new Appointment(service);
//Set properties on the appointment.
appointment.Subject = "Dentist Appointment";
appointment.Body = "The appointment is with Dr. Smith.";
appointment.Start = new DateTime(2009, 3, 1, 9, 0, 0);
appointment.End = appointment.Start.AddHours(2);
//Save the appointment.
appointment.Save(SendInvitationsMode.SendToNone);
How can I using the API check the status of the booking and whether it was booked or not due to a conflict in the date (Success/Error/Conflict)? right now I'm able to check this through the outlook, but I'd like to know this information from the API. I've looked into the API documentation but I couldn't find anything.
Appreciate your help/guidance.
You should first check the availability of all attendees before saving your appointment. AvailabilityData will return you Result (ServiceResult.Success, ServiceResult.Warning, or ServiceResult.Error) and further you can check ErrorMessage property to find proper return message for each conflicting availability. If availability is not conflicting for any of the attendees, you can save your Appointment object.
AvailabilityOptions availabilityOptions = new AvailabilityOptions();
availabilityOptions.MeetingDuration = 60;
availabilityOptions.MaximumNonWorkHoursSuggestionsPerDay = 4;
availabilityOptions.MinimumSuggestionQuality = SuggestionQuality.Good;
availabilityOptions.RequestedFreeBusyView = FreeBusyViewType.FreeBusy;
List<AttendeeInfo> attendees = new List<AttendeeInfo>();
attendees.Add(
new AttendeeInfo()
{
SmtpAddress = "org#acme.com",
AttendeeType = MeetingAttendeeType.Organizer
});
attendees.Add(
new AttendeeInfo()
{
SmtpAddress = "at1#acme.com",
AttendeeType = MeetingAttendeeType.Required
});
attendees.Add(
new AttendeeInfo()
{
SmtpAddress = "room1#acme.com",
AttendeeType = MeetingAttendeeType.Room
});
GetUserAvailabilityResults availabilityResults =
service.GetUserAvailability(
attendees,
new TimeWindow(DateTime.Now, DateTime.Now.AddDays(1)),
AvailabilityData.FreeBusyAndSuggestions,
availabilityOptions
);
// Here check the availability Result and ErrorMessage of each attendees
// availabilityResults.AttendeesAvailability[0].Result
// availabilityResults.AttendeesAvailability[0].ErrorMessage
// ServiceResult.Success
// ServiceResult.Warning
// ServiceResult.Error
Related
I use EWS to get data about user calendar events. I connect to MS Exchange on behalf of the user. If I connect as user B, how can I tell if I found the same calendar event which I found before in mailbox of user A?
Maybe something like the same message identifier or something like that?
There's a few way you can do that the best way (which is the way Outlook uses) is to use the Goid properties eg GlobalCleanObjectId https://learn.microsoft.com/en-us/office/client-developer/outlook/mapi/pidlidcleanglobalobjectid-canonical-property a quick example
Appointment newAppointment = new Appointment(service);
newAppointment.Subject = "Test Subject";
newAppointment.Start = new DateTime(2012, 03, 27, 17, 00, 0);
newAppointment.StartTimeZone = TimeZoneInfo.Local;
newAppointment.EndTimeZone = TimeZoneInfo.Local;
newAppointment.End = newAppointment.Start.AddMinutes(30);
newAppointment.Save();
newAppointment.Body = new MessageBody(Microsoft.Exchange.WebServices.Data.BodyType.Text, "test");
newAppointment.RequiredAttendees.Add("attendee#domain.com");
newAppointment.Update(ConflictResolutionMode.AlwaysOverwrite ,SendInvitationsOrCancellationsMode.SendOnlyToAll);
ExtendedPropertyDefinition CleanGlobalObjectId = new ExtendedPropertyDefinition(DefaultExtendedPropertySet.Meeting, 0x23, MapiPropertyType.Binary);
PropertySet psPropSet = new PropertySet(BasePropertySet.FirstClassProperties);
psPropSet.Add(CleanGlobalObjectId);
newAppointment.Load(psPropSet);
object CalIdVal = null;
newAppointment.TryGetProperty(CleanGlobalObjectId, out CalIdVal);
Folder AtndCalendar = Folder.Bind(service, new FolderId(WellKnownFolderName.Calendar,"attendee#domain.com"));
SearchFilter sfSearchFilter = new SearchFilter.IsEqualTo(CleanGlobalObjectId, Convert.ToBase64String((Byte[])CalIdVal));
ItemView ivItemView = new ItemView(1);
FindItemsResults<Item> fiResults = AtndCalendar.FindItems(sfSearchFilter, ivItemView);
if (fiResults.Items.Count > 0) {
//do whatever
}
I was trying to get the number of events that a specific user created in the past month using Google Calendar API.
The problem is that I got all the events where a user was invited. I don't see how to query only the events that user created.
calendarId: user's email adress
updatedMin : today - one month
I am using Google's api explorer to query Calendar API.
You can filter them by creator.email or organizer.email
Code:
function getCreatedEvents() {
var user = 'user#domain.com';
var today = new Date();
var date = new Date();
date.setMonth(date.getMonth() - 1);
var args = {
timeMin: new Date(date.getTime()).toISOString(),
timeMax: new Date(today.getTime()).toISOString()
}
var events = Calendar.Events.list(user, args).items;
events.forEach(function (event){
if(event.creator && event.creator.email == user){
// do something to events
Logger.log(event);
}
});
}
Output:
References:
DateTime
UpdatedMin Error1
UpdatedMin Error2
Calendar.Events.List
Include a query parameter in your request:
q: organizer==user#domain.com
This will filter to only events organized by user#domain.com.
Updated:
Unfortunately the query parameter does not accept key value pairs. This solution will not work.
How to get all data present in my Calendar using Xamarin. I am using below code and It is only returning already present holidays list. I want to get the manually added events and reminder list also.Below is the code am using
var calendarsUri = CalendarContract.Events.ContentUri;
var cursor = Forms.Context.ContentResolver.Query(calendarsUri, null, null, null, null);
if (cursor.MoveToFirst())
{
do
{
calendarEventList.Add(new Calendar()
{
Id = cursor.GetString(cursor.GetColumnIndex(ContactsContract.Contacts.InterfaceConsts.Id)),
CalendarDisplayName = cursor.GetString(cursor.GetColumnIndex(CalendarContract.Calendars.InterfaceConsts.CalendarDisplayName)),
AccountName = cursor.GetString(cursor.GetColumnIndex(CalendarContract.Calendars.InterfaceConsts.AccountType)),
Title = cursor.GetString(cursor.GetColumnIndex(CalendarContract.Events.InterfaceConsts.Title)),
Description = cursor.GetString(cursor.GetColumnIndex(CalendarContract.Events.InterfaceConsts.Description)),
Dtstart = cursor.GetString(cursor.GetColumnIndex(CalendarContract.Events.InterfaceConsts.Dtstart)),
Dtend = cursor.GetString(cursor.GetColumnIndex(CalendarContract.Events.InterfaceConsts.Dtend))
});
} while (cursor.MoveToNext());
}
So my 'calendarEventList' contains only the holidays event. Can anyone help me with getting all the events from my Calendar.
Thank in Advance.
I want to add a field to Accounts which shows the email domain for that account e.g. #BT.com. I then have a spreadsheet which lists all the Accounts and their email domains. What I want to do is when a new Contact is added to Dynamics that it checks the spreadsheet for the same email domain (obviously without the contacts name in the email) and then assigned the Contact to the Account linked to that domain. Any idea how I would do this. Thanks
Probably best chance would be to develop CRM plugin. Register your plugin to be invoked when on after contact is created or updated (so called post-event phase). And in your plugin update the parentaccountid property of the contact entity to point to account of your choice.
Code-wise it goes something like (disclaimer: not tested):
// IPluginExecutionContext context = null;
// IOrganizationService organizationService = null;
var contact = (Entity)context.InputParameters["Target"];
var email = organizationService.Retrieve("contact", contact.Id, new ColumnSet("emailaddress1")).GetAttributeValue<string>("emailaddress1");
string host;
try
{
var address = new MailAddress(email);
host = address.Host;
}
catch
{
return;
}
var query = new QueryExpression("account");
query.TopCount = 1;
// or whatever the name of email domain field on account is
query.Criteria.AddCondition("emailaddress1", ConditionOperator.Contains, "#" + host);
var entities = organizationService.RetrieveMultiple(query).Entities;
if (entities.Count != 0)
{
contact["parentaccountid"] = entities[0].ToEntityReference();
}
organizationService.Update(contact);
I took Ondrej's code and cleaned it up a bit, re-factored for pre-operation. I also updated the logic to only match active account records and moved the query inside the try/catch. I am unfamiliar with the MailAddress object, I personally would just use string mapping logic.
var target = (Entity)context.InputParameters["Target"];
try
{
string host = new MailAddress(target.emailaddress1).Host;
var query = new QueryExpression("account");
query.TopCount = 1;
// or whatever the name of email domain field on account is
query.Criteria.AddCondition("emailaddress1", ConditionOperator.Contains, "#" + host);
query.Criteria.AddCondition("statecode", ConditionOperator.Equals, 0); //Active records only
var entities = organizationService.RetrieveMultiple(query).Entities;
if (entities.Count != 0)
{
target["parentaccountid"] = entities[0].ToEntityReference();
}
}
catch
{
//Log error
}
Im new to SharePoint programming, or programming at all for that case. My problem is that I get a error-message when I try to go to my sharepoint site after I debugged this oode (it worked fine in visual studio). I don't know whats wrong? The error message i get is:
"Server Error in '/' Application.
0x80004005Updates are currently disallowed on GET requests. To allow updates on a GET, set the 'AllowUnsafeUpdates' property on SPWeb."
I've read that you got to allow safe updates? but is that the case? I think maybe it is my code that is not right... Please help :)
// choose your site
SPSite site = new SPSite("http://....");
SPWeb web = SPContext.Current.Web;
//Add a list to the choosen site
SPListCollection lists = web.Lists;
// create new Generic list called "OrdersList"
lists.Add("OrdersTest", "All of my testorders will be here", SPListTemplateType.GenericList);
//Add the new list to the website
SPList newList = web.Lists["OrdersTest"];
// create Number type new column called "OrderID"
newList.Fields.Add("OrderID", SPFieldType.Number, true);
// create Number type new column called "OrderNumber"
newList.Fields.Add("OrderNumber", SPFieldType.Number, true);
// create Text type new column called "OrderProducts"
newList.Fields.Add("OrderProducts", SPFieldType.Text, true);
newList.Update();
//Create a object to that list
SPListItem newOrder = newList.AddItem();
//Add a new item
newOrder["OrderID"] = 1;
newOrder["OrderNumber"] = 1;
newOrder["OrderProducts"] = "Icecream";
newOrder.Update();
// create new Generic list called "ProductTest"
lists.Add("ProductTest", "All of my testproducts will be here", SPListTemplateType.GenericList);
//Add the new list to the website
SPList newList2 = web.Lists["ProductTest"];
// create Number type new column called "ProductID"
newList2.Fields.Add("ProductID", SPFieldType.Number, true);
// create Text type new column called "ProductName"
newList2.Fields.Add("ProductName", SPFieldType.Text, true);
// create Number type new column called "OrderID"
newList2.Fields.Add("ProductPrice", SPFieldType.Number, true);
//Create a object to that list
SPListItem nyProduct = newList2.AddItem();
//Add a new item
nyProduct["ProductID"] = 1;
nyProduct["ProductName"] = "Icecream";
nyProduct["ProductPrice"] = 13;
nyProduct.Update();
You need to set AllowUnsafeUpdates to true for updating data in get requests.
using(SPSite site = new SPSite("http://...."))
using (SPWeb web = site.OpenWeb())
{
bool b = web.AllowUnsafeUpdates;
web.AllowUnsafeUpdates = true;
try
{
//your code
//create and update list
}
catch (Exception ex)
{
//handles errors
}
finally
{
web.AllowUnsafeUpdates = b;
}
}