/// <summary> /// Returns <paramref name="propertyDefinition"/> property value from Exchange storage <paramref name="item"/>. /// If property value not reachable, returns default <paramref name="propertyDefinition"/> value. /// </summary> /// <typeparam name="T">Return value type.</typeparam> /// <param name="item"><see cref="Exchange.Item"/> instance.</param> /// <param name="propertyDefinition"><see cref="Exchange.PropertyDefinition"/> instance.</param> /// <returns><paramref name="propertyDefinition"/> value from <paramref name="item"/> if value reachable, /// dafault <paramref name="propertyDefinition"/> value otherwise.</returns> public static T SafeGetValue <T>(this Exchange.Item item, Exchange.PropertyDefinition propertyDefinition) { T value; item.TryGetProperty(propertyDefinition, out value); return(value); }
static bool SetProperty(EmailMessage message, PropertyDefinition propertyDefinition, object value) { if (message == null) return false; // get value of PropertyBag property — that is wrapper // over dictionary of inner message’s properties var members = message.GetType().FindMembers(MemberTypes.Property, BindingFlags.NonPublic | BindingFlags.Instance,PartialName,"PropertyBag"); if (members.Length < 1) return false; var propertyInfo = members[0] as PropertyInfo; if (propertyInfo == null) return false; var bag = propertyInfo.GetValue(message, null); members = bag.GetType().FindMembers(MemberTypes.Property,BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance,PartialName,"Properties"); if (members.Length < 1) return false; // get dictionary of properties values var properties = ((PropertyInfo)members[0]).GetMethod.Invoke(bag, null); var dictionary = properties as Dictionary<PropertyDefinition, object>; if (dictionary == null) return false; dictionary[propertyDefinition] = value; return true; }
/// <summary> /// Validates this property set instance for request to ensure that: /// 1. Properties are valid for the request server version. /// 2. If only summary properties are legal for this request (e.g. FindItem) then only summary properties were specified. /// </summary> /// <param name="request">The request.</param> /// <param name="summaryPropertiesOnly">if set to <c>true</c> then only summary properties are allowed.</param> internal void ValidateForRequest(ServiceRequestBase request, bool summaryPropertiesOnly) { foreach (PropertyDefinitionBase propDefBase in this.additionalProperties) { PropertyDefinition propertyDefinition = propDefBase as PropertyDefinition; if (propertyDefinition != null) { if (propertyDefinition.Version > request.Service.RequestedServerVersion) { throw new ServiceVersionException( string.Format( Strings.PropertyIncompatibleWithRequestVersion, propertyDefinition.Name, propertyDefinition.Version)); } if (summaryPropertiesOnly && !propertyDefinition.HasFlag(PropertyDefinitionFlags.CanFind, request.Service.RequestedServerVersion)) { throw new ServiceValidationException( string.Format( Strings.NonSummaryPropertyCannotBeUsed, propertyDefinition.Name, request.GetXmlElementName())); } } } if (this.FilterHtmlContent.HasValue) { if (request.Service.RequestedServerVersion < ExchangeVersion.Exchange2010) { throw new ServiceVersionException( string.Format( Strings.PropertyIncompatibleWithRequestVersion, "FilterHtmlContent", ExchangeVersion.Exchange2010)); } } if (this.ConvertHtmlCodePageToUTF8.HasValue) { if (request.Service.RequestedServerVersion < ExchangeVersion.Exchange2010_SP1) { throw new ServiceVersionException( string.Format( Strings.PropertyIncompatibleWithRequestVersion, "ConvertHtmlCodePageToUTF8", ExchangeVersion.Exchange2010_SP1)); } } if (!string.IsNullOrEmpty(this.InlineImageUrlTemplate)) { if (request.Service.RequestedServerVersion < ExchangeVersion.Exchange2013) { throw new ServiceVersionException( string.Format( Strings.PropertyIncompatibleWithRequestVersion, "InlineImageUrlTemplate", ExchangeVersion.Exchange2013)); } } if (this.BlockExternalImages.HasValue) { if (request.Service.RequestedServerVersion < ExchangeVersion.Exchange2013) { throw new ServiceVersionException( string.Format( Strings.PropertyIncompatibleWithRequestVersion, "BlockExternalImages", ExchangeVersion.Exchange2013)); } } if (this.AddBlankTargetToLinks.HasValue) { if (request.Service.RequestedServerVersion < ExchangeVersion.Exchange2013) { throw new ServiceVersionException( string.Format( Strings.PropertyIncompatibleWithRequestVersion, "AddTargetToLinks", ExchangeVersion.Exchange2013)); } } if (this.MaximumBodySize.HasValue) { if (request.Service.RequestedServerVersion < ExchangeVersion.Exchange2013) { throw new ServiceVersionException( string.Format( Strings.PropertyIncompatibleWithRequestVersion, "MaximumBodySize", ExchangeVersion.Exchange2013)); } } }
/// <summary> /// Scopes the date time property to the appropriate time zone, if necessary. /// </summary> /// <param name="service">The service emitting the request.</param> /// <param name="dateTime">The date time.</param> /// <param name="propertyBag">The property bag.</param> /// <param name="isUpdateOperation">Indicates whether the scoping is to be performed in the context of an update operation.</param> /// <returns>The converted DateTime.</returns> internal override DateTime ScopeToTimeZone( ExchangeServiceBase service, DateTime dateTime, PropertyBag propertyBag, bool isUpdateOperation) { if (!propertyBag.Owner.GetIsCustomDateTimeScopingRequired()) { // Most item types do not require a custom scoping mechanism. For those item types, // use the default scoping mechanism. return(base.ScopeToTimeZone( service, dateTime, propertyBag, isUpdateOperation)); } else { // Appointment, however, requires a custom scoping mechanism which is based on an // associated time zone property. PropertyDefinition timeZoneProperty = this.GetTimeZoneProperty(service.RequestedServerVersion); object timeZonePropertyValue = null; bool timeZonePropertyIsSet = propertyBag.TryGetProperty(timeZoneProperty, out timeZonePropertyValue); if (timeZonePropertyValue != null && propertyBag.IsPropertyUpdated(timeZoneProperty)) { // If we have the associated time zone property handy and if it has been updated locally, // then we scope the date time to that time zone. try { DateTime convertedDateTime = EwsUtilities.ConvertTime( dateTime, (TimeZoneInfo)timeZonePropertyValue, TimeZoneInfo.Utc); // This is necessary to stamp the date/time with the Local kind. return(new DateTime(convertedDateTime.Ticks, DateTimeKind.Utc)); } catch (TimeZoneConversionException e) { throw new PropertyException( string.Format(Strings.InvalidDateTime, dateTime), this.Name, e); } } else { if (isUpdateOperation) { // In an update operation, what we do depends on what version of EWS // we are targeting. if (service.RequestedServerVersion == ExchangeVersion.Exchange2007_SP1) { // For Exchange 2007 SP1, we still need to scope to the service's time zone. return(base.ScopeToTimeZone( service, dateTime, propertyBag, isUpdateOperation)); } else { // Otherwise, we let the server scope to the appropriate time zone. return(dateTime); } } else { // In a Create operation, always scope to the service's time zone. return(base.ScopeToTimeZone( service, dateTime, propertyBag, isUpdateOperation)); } } } }
/// <summary> /// Writes the update to Json. /// </summary> /// <param name="service">The service.</param> /// <param name="ewsObject">The ews object.</param> /// <param name="propertyDefinition">Property definition.</param> /// <param name="updates">The updates.</param> /// <returns> /// True if property generated serialization. /// </returns> bool ICustomUpdateSerializer.WriteSetUpdateToJson(ExchangeService service, ServiceObject ewsObject, PropertyDefinition propertyDefinition, List <JsonObject> updates) { // If the collection is empty, delete the property. if (this.Count == 0) { JsonObject jsonUpdate = new JsonObject(); jsonUpdate.AddTypeParameter(ewsObject.GetDeleteFieldXmlElementName()); jsonUpdate.Add(JsonNames.Path, (propertyDefinition as IJsonSerializable).ToJson(service)); return(true); } // Otherwise, use the default Json serializer. else { return(false); } }
/// <summary> /// Writes the set update to json. /// </summary> /// <param name="service">The service.</param> /// <param name="ewsObject">The ews object.</param> /// <param name="propertyDefinition">The property definition.</param> /// <param name="updates">The updates.</param> /// <returns></returns> bool ICustomUpdateSerializer.WriteSetUpdateToJson( ExchangeService service, ServiceObject ewsObject, PropertyDefinition propertyDefinition, List <JsonObject> updates) { List <TEntry> tempEntries = new List <TEntry>(); foreach (TKey key in this.addedEntries) { tempEntries.Add(this.entries[key]); } foreach (TKey key in this.modifiedEntries) { tempEntries.Add(this.entries[key]); } foreach (TEntry entry in tempEntries) { if (!entry.WriteSetUpdateToJson( service, ewsObject, propertyDefinition, updates)) { JsonObject jsonUpdate = new JsonObject(); jsonUpdate.AddTypeParameter(ewsObject.GetSetFieldXmlElementName()); JsonObject jsonUri = new JsonObject(); jsonUri.AddTypeParameter(JsonNames.PathToIndexedFieldType); jsonUri.Add(XmlAttributeNames.FieldURI, this.GetFieldURI()); jsonUri.Add(XmlAttributeNames.FieldIndex, entry.Key.ToString()); jsonUpdate.Add(JsonNames.Path, jsonUri); object jsonProperty = entry.InternalToJson(service); JsonObject jsonServiceObject = new JsonObject(); jsonServiceObject.AddTypeParameter(ewsObject.GetXmlElementName()); jsonServiceObject.Add(propertyDefinition.XmlElementName, new object[] { jsonProperty }); jsonUpdate.Add(PropertyBag.GetPropertyUpdateItemName(ewsObject), jsonServiceObject); updates.Add(jsonUpdate); } } foreach (TEntry entry in this.removedEntries.Values) { if (!entry.WriteDeleteUpdateToJson(service, ewsObject, updates)) { JsonObject jsonUpdate = new JsonObject(); jsonUpdate.AddTypeParameter(ewsObject.GetDeleteFieldXmlElementName()); JsonObject jsonUri = new JsonObject(); jsonUri.AddTypeParameter(JsonNames.PathToIndexedFieldType); jsonUri.Add(XmlAttributeNames.FieldURI, this.GetFieldURI()); jsonUri.Add(XmlAttributeNames.FieldIndex, entry.Key.ToString()); jsonUpdate.Add(JsonNames.Path, jsonUri); updates.Add(jsonUpdate); } } return(true); }
/// <summary> /// Tries to retrieve the value of the specified property. /// </summary> /// <param name="propertyDefinition">The property for which to retrieve a value.</param> /// <param name="propertyValue">If the method succeeds, contains the value of the property.</param> /// <returns>True if the value could be retrieved, false otherwise.</returns> internal bool TryGetValue(PropertyDefinition propertyDefinition, out object propertyValue) { return(this.properties.TryGetValue(propertyDefinition, out propertyValue)); }
/// <summary> /// Determines whether the property bag contains a specific property. /// </summary> /// <param name="propertyDefinition">The property to check against.</param> /// <returns>True if the specified property is in the bag, false otherwise.</returns> internal bool Contains(PropertyDefinition propertyDefinition) { return(this.properties.ContainsKey(propertyDefinition)); }
/// <summary> /// Gets or sets the value of a property. /// </summary> /// <param name="propertyDefinition">The property to get or set.</param> /// <returns>An object representing the value of the property.</returns> /// <exception cref="ServiceVersionException">Raised if this property requires a later version of Exchange.</exception> /// <exception cref="ServiceObjectPropertyException">Raised for get if property hasn't been assigned or loaded. Raised for set if property cannot be updated or deleted.</exception> internal object this[PropertyDefinition propertyDefinition] { get { ServiceLocalException serviceException; object propertyValue = this.GetPropertyValueOrException(propertyDefinition, out serviceException); if (serviceException == null) { return(propertyValue); } else { throw serviceException; } } set { if (propertyDefinition.Version > this.Owner.Service.RequestedServerVersion) { throw new ServiceVersionException( string.Format( Strings.PropertyIncompatibleWithRequestVersion, propertyDefinition.Name, propertyDefinition.Version)); } // If the property bag is not in the loading state, we need to verify whether // the property can actually be set or updated. if (!this.loading) { // If the owner is new and if the property cannot be set, throw. if (this.Owner.IsNew && !propertyDefinition.HasFlag(PropertyDefinitionFlags.CanSet, this.Owner.Service.RequestedServerVersion)) { throw new ServiceObjectPropertyException(Strings.PropertyIsReadOnly, propertyDefinition); } if (!this.Owner.IsNew) { // If owner is an item attachment, properties cannot be updated (EWS doesn't support updating item attachments) Item ownerItem = this.Owner as Item; if ((ownerItem != null) && ownerItem.IsAttachment) { throw new ServiceObjectPropertyException(Strings.ItemAttachmentCannotBeUpdated, propertyDefinition); } // If the property cannot be deleted, throw. if (value == null && !propertyDefinition.HasFlag(PropertyDefinitionFlags.CanDelete)) { throw new ServiceObjectPropertyException(Strings.PropertyCannotBeDeleted, propertyDefinition); } // If the property cannot be updated, throw. if (!propertyDefinition.HasFlag(PropertyDefinitionFlags.CanUpdate)) { throw new ServiceObjectPropertyException(Strings.PropertyCannotBeUpdated, propertyDefinition); } } } // If the value is set to null, delete the property. if (value == null) { this.DeleteProperty(propertyDefinition); } else { ComplexProperty complexProperty; object currentValue; if (this.properties.TryGetValue(propertyDefinition, out currentValue)) { complexProperty = currentValue as ComplexProperty; if (complexProperty != null) { complexProperty.OnChange -= this.PropertyChanged; } } // If the property was to be deleted, the deletion becomes an update. if (this.deletedProperties.Remove(propertyDefinition)) { AddToChangeList(propertyDefinition, this.modifiedProperties); } else { // If the property value was not set, we have a newly set property. if (!this.properties.ContainsKey(propertyDefinition)) { AddToChangeList(propertyDefinition, this.addedProperties); } else { // The last case is that we have a modified property. if (!this.modifiedProperties.Contains(propertyDefinition)) { AddToChangeList(propertyDefinition, this.modifiedProperties); } } } this.InitComplexProperty(value as ComplexProperty); this.properties[propertyDefinition] = value; this.Changed(); } } }
/// <summary> /// Gets the property value. /// </summary> /// <param name="propertyDefinition">The property definition.</param> /// <param name="exception">Exception that would be raised if there's an error retrieving the property.</param> /// <returns>Propert value. May be null.</returns> private object GetPropertyValueOrException(PropertyDefinition propertyDefinition, out ServiceLocalException exception) { object propertyValue = null; exception = null; if (propertyDefinition.Version > this.Owner.Service.RequestedServerVersion) { exception = new ServiceVersionException( string.Format( Strings.PropertyIncompatibleWithRequestVersion, propertyDefinition.Name, propertyDefinition.Version)); return(null); } if (this.TryGetValue(propertyDefinition, out propertyValue)) { // If the requested property is in the bag, return it. return(propertyValue); } else { if (propertyDefinition.HasFlag(PropertyDefinitionFlags.AutoInstantiateOnRead)) { // The requested property is an auto-instantiate-on-read property ComplexPropertyDefinitionBase complexPropertyDefinition = propertyDefinition as ComplexPropertyDefinitionBase; EwsUtilities.Assert( complexPropertyDefinition != null, "PropertyBag.get_this[]", "propertyDefinition is marked with AutoInstantiateOnRead but is not a descendant of ComplexPropertyDefinitionBase"); propertyValue = complexPropertyDefinition.CreatePropertyInstance(this.Owner); if (propertyValue != null) { this.InitComplexProperty(propertyValue as ComplexProperty); this.properties[propertyDefinition] = propertyValue; } } else { // If the property is not the Id (we need to let developers read the Id when it's null) and if has // not been loaded, we throw. if (propertyDefinition != this.Owner.GetIdPropertyDefinition()) { if (!this.IsPropertyLoaded(propertyDefinition)) { exception = new ServiceObjectPropertyException(Strings.MustLoadOrAssignPropertyBeforeAccess, propertyDefinition); return(null); } // Non-nullable properties (int, bool, etc.) must be assigned or loaded; cannot return null value. if (!propertyDefinition.IsNullable) { string errorMessage = this.IsRequestedProperty(propertyDefinition) ? Strings.ValuePropertyNotLoaded : Strings.ValuePropertyNotAssigned; exception = new ServiceObjectPropertyException(errorMessage, propertyDefinition); } } } return(propertyValue); } }
/// <summary> /// Determines whether the specified property has been updated. /// </summary> /// <param name="propertyDefinition">The property definition.</param> /// <returns> /// <c>true</c> if the specified property has been updated; otherwise, <c>false</c>. /// </returns> internal bool IsPropertyUpdated(PropertyDefinition propertyDefinition) { return(this.modifiedProperties.Contains(propertyDefinition) || this.addedProperties.Contains(propertyDefinition)); }