EWS Create Appointment in exchange with extra custom properties - c#

Im currently looking at a way to save a few extra properties to an exchange appointment using C#. Currently I can save using the following properties:
Appointment calendar = new Appointment(p_service);
calendar.Subject = calendarS5Subject;
calendar.Body = calendarS5Body;
calendar.Start = calendarS5StartDateTime;
calendar.End = calendarS5EndDateTime;
calendar.IsReminderSet = false;
calendar.Location = calendarS5Location;
calendar.Body.BodyType = BodyType.Text;
calendar.Save();
However I want to be able to store my own custom properties like calendar.EventID and calendar.Blah . Is it possible to save these properties against the appointment and then be able to access them later? It would be even better if it could all be stored as a user control form inside the appoint window. I know you can do this with an outlook addin that uses the type AppointmentItem. However I am yet to find a way to do it with exchange with the type of Appointment.
TIA.
I have now been able to save the extra property using:
Guid EventIDSetGUID = new Guid("{C11FF724-AA03-4555-9952-8FA248A11C3E}");
ExtendedPropertyDefinition extendedPropertyEventID = new ExtendedPropertyDefinition(EventIDSetGUID, "EventID", MapiPropertyType.String);
calendar.SetExtendedProperty(extendedPropertyEventID, calendarS5EventID);
However I am now struggling to read back that property later on. This work right after I have saved the extra property but if I restart the application and then try to read the extra property eventIDProp always returns null. My code for reading:
Guid EventIDReadGUID = new Guid("{C11FF724-AA03-4555-9952-8FA248A11C3E}");
ExtendedPropertyDefinition extendedPropertyEventIDRead = new ExtendedPropertyDefinition(EventIDReadGUID, "EventID", MapiPropertyType.String);
object eventIDProp;
if (calendar.TryGetProperty(extendedPropertyEventIDRead, out eventIDProp) && eventIDProp != calendarS5EventID)
{
}

You can do that with MAPI extended properties:
// Define MAPI extended properties
private readonly ExtendedPropertyDefinition _extendedPropEventId =
new ExtendedPropertyDefinition(
new Guid("{00020329-0000-0000-C000-000000000046}"),
"Event Identifier",
MapiPropertyType.String);
private readonly ExtendedPropertyDefinition _extendedPropBlah =
new ExtendedPropertyDefinition(
new Guid("{00020329-0000-0000-C000-000000000046}"),
"Blah",
MapiPropertyType.String);
...
// Set extended properties for appointment
calendar.SetExtendedProperty(_extendedPropEventId, "custom EventID value");
calendar.SetExtendedProperty(_extendedPropBlah, "custom Blah value");
...
// Bind to existing item for reading extended properties
var propertySet = new PropertySet(BasePropertySet.FirstClassProperties, _extendedPropEventId, _extendedPropBlah);
var calendar = Appointment.Bind(p_service, itemId, propertySet);
if (calendar.ExtendedProperties.Any(ep => ep.PropertyDefinition.PropertySetId == _extendedPropEventId.PropertySetId))
{
// Add your code here...
}

Related

EWS SetExtendedProperty issue

I'm trying to update an existing email with a new property but I can't get it working.. i'm testing it by adding a custom property with a time stamp string in it..
When i fetch the item in after this has run I can't see any extended properties on it at all...
Here's how i'm trying to save it:
message.Load();
Guid MyPropertySetId = new Guid("{117c7745-5df5-4049-97be-8e2d2d92d566}");
ExtendedPropertyDefinition extendedPropertyDefinition = new ExtendedPropertyDefinition(MyPropertySetId, "JNB", MapiPropertyType.String);
message.SetExtendedProperty(extendedPropertyDefinition, DateTime.Now.AddDays(2).ToString());
message.Update(ConflictResolutionMode.AlwaysOverwrite);
And then when I pull it back in again i'm doing this:
if (item.ExtendedProperties.Count > 0)
{
// Display the name and value of the extended property.
foreach (ExtendedProperty extendedProperty in item.ExtendedProperties)
{
if (extendedProperty.PropertyDefinition.Name == "ccpUniqueID")
{
messageAlreadyLogged = AccountMessageManager.HasMessageAlreadyBeenSaved(extendedProperty.Value.ToString());
}
}
}
There just isn't any extended properties....
Exchange will only return the Extended properties you tell it to return so in your case you will need to add that property to a Property Set and then use Load to load it back (this won't happen by default) eg
Guid MyPropertySetId = new Guid("{117c7745-5df5-4049-97be-8e2d2d92d566}");
ExtendedPropertyDefinition extendedPropertyDefinition = new ExtendedPropertyDefinition(MyPropertySetId, "JNB", MapiPropertyType.String);
PropertySet psPropSet = new PropertySet(BasePropertySet.FirstClassProperties){extendedPropertyDefinition};
message.Load(psPropSet);

Create appointment with custom properties in EWS

I try to add a custom property to created appointments like this:
var newEvent = new Appointment(service)
{
Start = start,
End = end,
Subject = subject,
ReminderMinutesBeforeStart = 15
};
var extendendProperty = new ExtendedPropertyDefinition(DefaultExtendedPropertySet.Address, "organizer",
MapiPropertyType.String);
newEvent.SetExtendedProperty(extendendProperty, organizer);
but problem is that when I try get this appointment from server, property ExtendedProperty is empty.
In addition I create new appointment and add 'room' as a required attendee, and when I try get this appointment, I don't get it from my calendar but from room calendar.
So, I want to add extend property to my appointment and invite 'room'. Next get all appointments of the room and here I want read this property. It is even possible?
I read this topic: EWS Create Appointment in exchange with extra custom properties and as I understand I'll must have access to ExtendendPropertyDefinition when I want read this property, and must known id of this appointment before. Now I download all appointments from outlook by this code:
var folderId = new FolderId(WellKnownFolderName.Calendar, new Mailbox(userName));
var calendar = CalendarFolder.Bind(service, folderId, new PropertySet());
return calendar.FindAppointments(new CalendarView(start, stop)).ToList();
EDIT
Thanks Glen Scales!
It almost works as I want, but one thing. I can read this additional property if I download my own appointments, but in that code I download appointments from room calendar.
As I suppose when creating new appointment and add room as required attendant, it create his own appointment and this additional property isn't copied.
So is any way to get this additional property from room appointment, when I add this property to my?
You need to first Create a property set, add the extended property you want to load to that property set. Then tell EWS you want that property returned when you execute the FindAppointment method see https://msdn.microsoft.com/en-us/library/office/dd633697(v=exchg.80).aspx eg in your example
PropertySet YourProperyset = new PropertySet(BasePropertySet.FirstClassProperties);
var extendendProperty = new ExtendedPropertyDefinition(DefaultExtendedPropertySet.Address, "organizer",MapiPropertyType.String);
YourProperyset.Add(extendendProperty);
var folderId = new FolderId(WellKnownFolderName.Calendar, new Mailbox(userName));
var calendar = CalendarFolder.Bind(service, folderId);
var calendarView = new CalendarView(start, stop);
calendarView.PropertySet = YourProperyset;
return calendar.FindAppointments(calendarView).ToList();

How to retrieve multiple Extended Properties use EWS and Java

I have created two "User-Defined" fields in the contacts folder in Outlook 2010. I'm using the Java port of the C# EWS API. My goal is to read the value of the fields for each contact for a specific user. The problem to this point has been retrieving more than one field. In my code below you'll find that I define multiple (2) fields that are extended properties that I want to access. However, in the output, I only retrieve, at most, 1 field. For Example, a contact has both fields, it will only return the first one it finds. If it only has 1 of the two fields, it will return which ever one is populated. Any ideas?
private static void printContacts(ExchangeService service, int numOfContacts) throws Exception{
// Defined the properties you want to retreive
ExtendedPropertyDefinition propertyOne = new ExtendedPropertyDefinition(DefaultExtendedPropertySet.PublicStrings, "property1", MapiPropertyType.String);
ExtendedPropertyDefinition propertyTwo= new ExtendedPropertyDefinition(DefaultExtendedPropertySet.PublicStrings, "property2", MapiPropertyType.String);
// Push the customer properties into an arary
ExtendedPropertyDefinition[] list = {propertyOne , propertyTwo};
// Create a property set to hold the properties
PropertySet propertySet = new PropertySet(BasePropertySet.FirstClassProperties, list);
// Get items from mail box
ItemView view = new ItemView(numOfContacts);
try {
FindItemsResults<Item> contactResults = service.findItems(WellKnownFolderName.Contacts, view);
for(Item item : contactResults.getItems()){
item.load();
Contact contact = Contact.bind(service, item.getId(), propertySet);
System.out.println("count: " + contact.getExtendedProperties().getCount());
for(ExtendedProperty prop : contact.getExtendedProperties()){
String propertyName = prop.getPropertyDefinition().getName().toString();
String propertyValue = prop.getValue().toString();
System.out.println(propertyName +" : "+ propertyValue);
}
}
}catch(Exception e){
e.printStackTrace();
}
}
When I print out the count of extended properties, its always one, even if both extended properties are set. Any help would be appreciated.

RemoveExtendedProperty throws error when used on an occurrence of a recurring appointment

I am developing an application that syncs an exchange calendar to another calendar. I put extended properties on the exchange appointments in order to preserve the mapping between appointments in the two calendars. Everything is working fine until I try to remove an extended property from an occurrence of a recurring appointment. When I try doing this, I get the error:
The delete action is not supported for this property.
Here is a code snippet that demonstrates the error:
public void ExchangeTest()
{
ExchangeService service = new ExchangeService(ExchangeVersion.Exchange2007_SP1)
{
Credentials = new NetworkCredential("username", "password", "domain")
};
service.AutodiscoverUrl("username#domain.com");
Appointment appt = new Appointment(service)
{
Recurrence = new Recurrence.DailyPattern(DateTime.Now, 2) { NumberOfOccurrences = 3},
Start = DateTime.Now,
End = DateTime.Now.AddHours(2),
Subject = "Test Appointment"
};
NameResolutionCollection resolutionCollection = service.ResolveName("username", ResolveNameSearchLocation.DirectoryOnly, false);
string mailboxAddress = resolutionCollection.First().Mailbox.Address;
FolderId folderId = new FolderId(WellKnownFolderName.Calendar, mailboxAddress);
appt.Save(folderId);
PropertySet properties = new PropertySet(AppointmentSchema.ICalUid);
appt.Load(properties);
CalendarView view = new CalendarView(DateTime.Today, DateTime.Today.AddDays(8)){PropertySet = properties};
IEnumerable<Appointment> occurrences = service.FindAppointments(folderId, view)
.Where(a => a.ICalUid == appt.ICalUid);
ExtendedPropertyDefinition definition = new ExtendedPropertyDefinition(DefaultExtendedPropertySet.PublicStrings, "TestProperty", MapiPropertyType.String);
Appointment firstOccurrence = occurrences.First();
firstOccurrence.SetExtendedProperty(definition, "test");
firstOccurrence.Update(ConflictResolutionMode.AutoResolve);
//The error occurs on the next line.
firstOccurrence.RemoveExtendedProperty(definition);
firstOccurrence.Update(ConflictResolutionMode.AutoResolve);
//clean up
appt.Delete(DeleteMode.HardDelete);
}
It appears that the error is only thrown for an Exchange 2007 server (It works on 2010). Am I doing something wrong, or is this a problem with Exchange? Is there a way to work around this issue? Any help will be appreciated.
I ended up not using the RemoveExtendedProperty function. Instead, I worked around it by just setting the property again, but setting it to an empty space. I then handled the empty space in code. This appears to be a problem with Exchange or the managed API.
Did you try;
appointment.Delete(DeleteMode.SoftDelete,SendCancellationsMode.SendToAllAndSaveCopy);

How can I get / set an extended property from a contact using Microsoft's EWS API?

I think I'm creating it properly, like as follows. c is a Contact, and I'm just trying to store a unique identifier considering that ItemId which is provided by EWS isnt static...
propertySetId = System.Guid.NewGuid();
// Create a definition for the extended property.
ExtendedPropertyDefinition extendedPropertyDefinition = new ExtendedPropertyDefinition(DefaultExtendedPropertySet.Common, "itemGUID", MapiPropertyType.String);
c.SetExtendedProperty(extendedPropertyDefinition, propertySetId.ToString());
c.Update(ConflictResolutionMode.AlwaysOverwrite);
When I try to pull this back out when searching for the contact based on something else, like first name, I'm getting a null returned. I'm trying to get the value by:
foreach (Item c in findResults.Items)
{
foreach(ExtendedProperty extendedProperty in c.ExtendedProperties)
{
if(extendedProperty.PropertyDefinition.Name == "itemGUID")
{
results[i] = extendedProperty.Value.ToString();
}
}
}
EDIT: code for findResults
List<SearchFilter> searchFilters = new List<SearchFilter>();
searchFilters.Add(new SearchFilter.IsEqualTo(itemGUID, value));
//can be more filters here depending on situation
SearchFilter filter = new SearchFilter.SearchFilterCollection(LogicalOperator.And, searchFilters.ToArray());
findResults = service.FindItems(WellKnownFolderName.Contacts, filter, view);
You need to assign the PropertySet in the ItemView to tell EWS what properties to include when you search using FindItems. If you don't include it in your ItemView it won't be available for reading.The alternative approach is to use the Contact.Bind and request the property for each Contact in question (more service requests, but sometimes necessary).
See Viewing Extended Properties using EWS for a full example on working with Extended Properties in EWS.
Approach #1: Retrieve Extended Property for all Contacts
ExtendedPropertyDefinition propDef = new ExtendedPropertyDefinition(DefaultExtendedPropertySet.Common, "itemGUID", MapiPropertyType.String);
ItemView view = new ItemView(50) { PropertySet = new PropertySet(propDef) };
Approach #2: Bind one contact at a time if you have a Contact ID
ExtendedPropertyDefinition propDef = new ExtendedPropertyDefinition(DefaultExtendedPropertySet.Common, "itemGUID", MapiPropertyType.String);
Contact contact = Contact.Bind(service, contactID, new PropertySet(propDef));

Categories