EWS-managed: Fetch required and optional attendees of appointments - exchange-server

As far as I am now, I know how to fetch appointments from exchange server, BUT as soon as I want to see the required and optional attendees, these fields are empty ... I checked the appointment trice and there is an attendee, except me. Do I have to config Outlook differently or do I miss something?
List<Appointment> listOfAppointments = new List<Appointment>();
CalendarFolder cfolder = CalendarFolder.Bind(MyService, WellKnownFolderName.Calendar);
CalendarView cview = new CalendarView(from.ToUniversalTime(), to.ToUniversalTime());
cview.PropertySet = new PropertySet(ItemSchema.Subject);
cview.PropertySet.Add(AppointmentSchema.Start);
cview.PropertySet.Add(AppointmentSchema.End);
cview.PropertySet.Add(AppointmentSchema.Location);
cview.PropertySet.Add(AppointmentSchema.ICalUid);
cview.PropertySet.Add(AppointmentSchema.Organizer);
cview.PropertySet.Add(AppointmentSchema.IsAllDayEvent);
cview.PropertySet.Add(AppointmentSchema.DateTimeCreated);
FindItemsResults<Appointment> result = cfolder.FindAppointments(cview);
thats how I fetch the appointments, as I figured from exceptions and trail and error, I don't need to ask exchange for attendees... but maybe I am missing something.

The FindAppointments operation do not return the attendees of meetings. Instead, specify a propertyset of PropertySet.IdOnly to get only the ids of the items. Then, use the ExchangeService.LoadPropertiesForItems to perform a batch load of the properties you need.

Related

How do I add a member (name and email address) to an existing Outlook Distribution List using C#

I am trying to programmatically add a member (name and email address) to an existing Outlook Distribution List, but I can figure out how to grab it. I have found many postings describing how to create a new Outlook Distribution List, but none on how to add a member to an existing one. I have been able to retrieve the items collection of the Contacts folder, but I cannot access the Outlook Distribution List I want. Keep in mind that the Contacts folder contains at least two different object types, Contact Items and Distribution List items. Is there a way to just retrieve the Distribution List items from the Contacts folder? Any help would be greatly appreciated. I have no code worth posting.
I have made some progress. I now have the below code:
Outlook.MAPIFolder outlookContactsFolder = outlookNamespace.GetDefaultFolder(Outlook.OlDefaultFolders.olFolderContacts); // Get Contacts folder.
Outlook.Items outlookContactsItems = outlookContactsFolder.Items; // Get the Items collection.
for (int i = 1; i <= outlookContactsItems.Count; i++)
{
if (i == 62)
{
Outlook.DistListItem outlookDistListItem = outlookContactsItems.GetNext();
Outlook.Recipient outlookRecipient = **(Need help creating a Recipient object with a name and email address)**
outlookDistListItem.AddMember(outlookRecipient);
outlookDistListItem.Save();
break;
}
else
{
Outlook.ContactItem outlookContactsItem = outlookContactsItems.GetNext();
}
}
I know this is not the best way, but it works. I can now access the Distribution List without the code blowing up. Now I need to add a new member to it. I know I can do that with the AddMember method, but it takes an Outlook.Recipient object. I can't find anywhere how to create it with a name and email address.

Cannot specify child attributes in the columnset for Retrieve

In attempting to merge contacts in Microsoft CRM, I am using the following code -
//c1ID and c2ID are GUIDs of duplicated contacts.
EntityReference target = new EntityReference();
target.LogicalName = Contact.EntityLogicalName;
target.Id = c2ID;
MergeRequest merge = new MergeRequest();
// SubordinateId is the GUID of the account merging.
merge.SubordinateId = c1ID;
merge.Target = target;
merge.PerformParentingChecks = true;
Contact updater = new Contact();
Contact updater2 = new Contact();
updater = (Contact)xrmSvc.ContactSet.Where(c => c.ContactId.Equals(c1ID)).First();
updater2 = (Contact)xrmSvc.ContactSet.Where(c => c.ContactId.Equals(c2ID)).First();
MergeResponse mergedR = (MergeResponse)xrmSvc.Execute(merge);
When I try my Execute call here,I get this error -
Cannot specify child attributes in the columnset for Retrieve. Attribute: owneridname.
Am I not setting something correctly?
Having updatecontent does not change the issue. In fact, I get the error on lookups entered into the updatecontent. I find you have to build new entityreferences:
if (match.Contains("new_mostrecentcampaign"))
master["new_mostrecentcampaign"] =
new EntityReference(match.GetAttributeValue<EntityReference>("new_mostrecentcampaign").LogicalName
, match.GetAttributeValue<EntityReference>("new_mostrecentcampaign").Id);
...
Merge.UpdateContent = master
...
I realize this is a pretty old question, but for those of you who have run into the same issue in 2021 and beyond, here's the reason this error happens.
TL;DR: Ensure the EntityReference values for the attributes does not specify the Name property.
Explanation:
Everything that gets added to the Entity set to UpdateContent will be applied to the Target contact. When programmatically executing a MergeRequest within a plugin/workflow, the attributes of the UpdateContent get applied (as desired).
Where this breaks down is for EntityReference value types (lookups). The internal Microsoft code that performs this operation tries to interpret all properties of the EntityReference object, including Name.
So when the existing values from the SubordinateId contact are pulled using IOrganizationService.Retrieve (to dynamically get the latest version), the Name property is automatically set for those lookup attributes (the child record). This operation is not valid, even though it's not the user code that's directly executing it.
This brings us full circle to explain the original error:
Cannot specify child attributes in the columnset for Retrieve
I wish I had some documentation for this, but although the official documentation notes that the UpdateContent is optional, experience proves that it is in fact necessary. In the MergeRequests I've tested, I always include that property in the request, and there's a post in the MSDN forums for Dynamics 3.0 that suggests the same.
In fact, when I try to merge two contacts in my org without UpdateContent assigned, I actually get a FaultException saying the following:
Required field 'UpdateContent' is missing
Even though the documentation says it's optional!
So I'd suggest populating the UpdateContent property with something as in the below and see if that works:
var merge = new MergeRequest
{
// SubordinateId is the GUID of the account merging.
SubordinateId = c1ID,
Target = target,
PerformParentingChecks = true,
UpdateContent = new Contact()
};

Grab System Created Values CRM 2011

I'm facing a problem when I try to grab the Extended Amount Attribute inside the Opportunity Product Line Entity.
As follows my requirements are that upon creation of a an Opportunity Product Line I have a post-create plugin on it which applies a discount onto the extended amount and creates another line, with the new discounted extended amount. When I try to output the value on another field just to check what it gets, I keep getting 0 strangley. My code is as follows:
// Part where I grab the value
Entity entity = (Entity)context.InputParameters["Target"];
Money extenedAmount = (Money)entity["baseamount"];
//Create new line
Entity oppportunity_product = new Entity("opportunityproduct");
oppportunity_product["manualdiscountamount"] = extenedAmount;
service.Create(oppportunity_product);
Is it even possible to grab the amount? Would really much appreciate if someone could help me out here. Thanks in advanace.
After creation, you want to add a post image. Then reference the post image instead of the target.
if (context.PostEntityImages.Contains("PostImage") &&
context.PostEntityImages["PostImage"] is Entity)
{
postMessageImage = (Entity)context.PostEntityImages["PostImage"];
}
else
{
throw new Exception("No Post Image Entity in Plugin Context for Message");
}

How do I retrieve just recurring event masters using Exchange Web services?

I'm using a CalendarItemType view to retrieve calendar items. The only items I care about are those that I've created and I know that they are all weekly recurring items. I'm able to get each individual occurrence and, from any one of them the recurring master item, but I'd like to narrow the scope of my search to just those items that would match my pattern.
I've trying using the Restriction property on the FindItemType to specify a NotEqualTo restriction with a null constant for calenderRecurrenceId. This caused my request to time out. So far I've been unable to load the recurrences with the FindItemType at all and need to use a subsequent GetItemType call when I find an event that is an occurence in a recurring series.
Here's the code that I'm starting with. The code needs to work with both Exchange 2007 and Exchange 2010.
var findItemRequest = new FindItemType();
findItemRequest.ParentFolderIds = new DistinguishedFolderIdType[]
{
new DistinguishedFolderIdType()
};
((DistinguishedFolderIdType)findItemequest.ParentFolderIds[0]).Id = DistinguishedFolderIdNameType.calendar;
findItemRequest.Traversal = ItemQueryTraversalType.Shallow;
var itemShapeDefinition = new ItemResponseShapeType(
{
BaseShape = DefaultShapeNamesType.AllProperties;
}
findItemRequest.Item = calenderView;
findItemRequest.ItemShape = itemShapeDefinition;
var findItemResponse = this.esb.FindItem( findItemRequest );
Also, if you know of any good source of examples (beyond the ones in MSDN), I'd welcome them. I'm picking up someone else's code in an emergency and trying to learn Exchange Web Services on the fly.
Maybe I'm misunderstanding you, in which case I apologize.
You do NOT use the CalendarView - you use the normal IndexedPageItemView if all you want is Master Recurring Calendar items.
You use the CalendarView to expand the recurrences to individual items. However the compromise with CalendarView is NO restrictions are permitted besides Start and End Date. None.
You can search for a RecurrenceMaster by using the recurrence PidLid with an ExtendedPropertyDefinition. This works because, according to their documentation, "this property must not exist on single instance calendar items."
https://msdn.microsoft.com/en-us/library/cc842017.aspx
// https://msdn.microsoft.com/en-us/library/cc842017.aspx
ExtendedPropertyDefinition apptType = new ExtendedPropertyDefinition(
DefaultExtendedPropertySet.Appointment,
0x00008216, //PidLidAppointmentRecur
MapiPropertyType.Binary);
var restriction = new SearchFilter.Exists(apptType);
var iView = new ItemView(10);
var found = folder.FindItems(restriction, iView);
I just confirmed this works, today, when revisiting some old code that works with Office365 EWS in the cloud.
Found only property you need is RecurrenceStart property. Because EWS has limitations it is not possible to use all properties in restriction. This one working as expected.
Reference: Find master recurring appointments
You can create custom searchfilters. If you search from specific startdate OR isRecurring property you have most easy way...(SearchItems returns recurring masters)
List<SearchFilter> searchFilterCollection = new List<SearchFilter>();
SearchFilter.IsGreaterThanOrEqualTo startDatumFilter = new SearchFilter.IsGreaterThanOrEqualTo(AppointmentSchema.Start, new DateTime(2012, 9, 16));
SearchFilter.IsEqualTo masterRecurringFilter = new SearchFilter.IsEqualTo(AppointmentSchema.IsRecurring, true);
searchFilterCollection.Add(startDatumFilter);
searchFilterCollection.Add(masterRecurringFilter);
SearchFilter finalFilter = new SearchFilter.SearchFilterCollection(LogicalOperator.Or, searchFilterCollection);
ItemView itemView = new ItemView(100000);
itemView.PropertySet = new PropertySet(BasePropertySet.FirstClassProperties, AppointmentSchema.AppointmentType);
FindItemsResults<Item> items = _service.FindItems(WellKnownFolderName.Calendar, finalFilter, itemView);

Error when I try to read/update the .Body of a Task via EWS Managed API - "You must load or assign this property before you can read its value."

I am using the Exchange Web Services Managed API to work with Tasks (Exchange 2007 SP1). I can create them fine. However, when I try to do updates, it works for all of the fields except for the .Body field. Whenever I try to access (read/update) that field, it gives the following error:
"You must load or assign this property before you can read its value."
The code I am using looks like this:
//impersonate the person whose tasks you want to read
Me.Impersonate(userName); //home-made function to handle impersonation
//build the search filter
Exchange.SearchFilter.SearchFilterCollection filter = New Exchange.SearchFilter.SearchFilterCollection();
filter.Add(New Exchange.SearchFilter.IsEqualTo(Exchange.TaskSchema.Categories, "Sales"));
//do the search
EWS.Task exTask = esb.FindItems(Exchange.WellKnownFolderName.Tasks, filter, New Exchange.ItemView(Integer.MaxValue));
exTask.Subject = txtSubject.Text; //this works fine
exTask.Body = txtBody.Text; //This one gives the error implying that the object isn't loaded
The strange thing is that, inspecting the property bag shows that the object contains 33 properties, but {Body} is not one of them. That property seems to be inherited from the base class .Item, or something.
So, do I need to re-load the object as type Item? Or reload it via .Bind or something? Keep in mind that I need to do this with thousands of items, so efficiency does matter to me.
Calling the Load method solved my problem :)
foreach (Item item in findResults.Items)
{
item.Load();
string subject = item.Subject;
string mailMessage = item.Body;
}
I had the same problem when using the EWS. My Code is requesting the events(Appointments) from the
Outlook calendar, at the end I couldn't reach to the body of the Event itself.
The missing point in my situation was the following "forgive me if there is any typo errors":
After gathering the Appointments, which are also derived from EWS Item Class, I did the following:
1- Create a List with the type Item:
List<Item> items = new List<Item>();
2- Added all appointments to items list:
if(oAppointmentList.Items.Count > 0) // Prevent the exception
{
foreach( Appointment app in oAppointmentList)
{
items.Add(app);
}
}
3- Used the exchanged service "I have already created and used":
oExchangeService.LoadPropertiesForItems(items, PropertySet.FirstClassProperties);
now if you try to use app.Body.Text, it will return it successfully.
Enjoy Coding and Best Luck
I forgot to mention the resource:
http://social.technet.microsoft.com/Forums/en-US/exchangesvrdevelopment/thread/ce1e0527-e2db-490d-817e-83f586fb1b44
He mentioned the use of Linq to save the intermediate step, it will help you avoid using the List items and save some memory!
RockmanX
You can load properties using a custom property set. Some properties are Extended properties instead of FirstClassProperties.
Little example:
_customPropertySet = new PropertySet(BasePropertySet.FirstClassProperties, AppointmentSchema.MyResponseType, AppointmentSchema.IsMeeting, AppointmentSchema.ICalUid);
_customPropertySet.RequestedBodyType = BodyType.Text;
appointment.Load(_customPropertySet);

Resources