/// <summary> /// Writes an EWS DeleteUpdate opeartion for the specified property. /// </summary> /// <param name="writer">The writer to write the update to.</param> /// <param name="propertyDefinition">The property fro which to write the update.</param> /// <param name="propertyValue">The current value of the property.</param> private void WriteDeleteUpdateToXml( EwsServiceXmlWriter writer, PropertyDefinition propertyDefinition, object propertyValue) { // The following test should not be necessary since the property bag prevents // properties to be deleted (set to null) if they don't have the CanDelete flag, // but it doesn't hurt... if (propertyDefinition.HasFlag(PropertyDefinitionFlags.CanDelete)) { bool handled = false; ICustomUpdateSerializer updateSerializer = propertyValue as ICustomUpdateSerializer; if (updateSerializer != null) { handled = updateSerializer.WriteDeleteUpdateToXml(writer, this.Owner); } if (!handled) { writer.WriteStartElement(XmlNamespace.Types, this.Owner.GetDeleteFieldXmlElementName()); propertyDefinition.WriteToXml(writer); writer.WriteEndElement(); } } }
/// <summary> /// Writes an EWS SetUpdate opeartion for the specified property. /// </summary> /// <param name="writer">The writer to write the update to.</param> /// <param name="propertyDefinition">The property fro which to write the update.</param> private void WriteSetUpdateToXml(EwsServiceXmlWriter writer, PropertyDefinition propertyDefinition) { // The following test should not be necessary since the property bag prevents // properties to be updated if they don't have the CanUpdate flag, but it // doesn't hurt... if (propertyDefinition.HasFlag(PropertyDefinitionFlags.CanUpdate)) { object propertyValue = this[propertyDefinition]; bool handled = false; ICustomUpdateSerializer updateSerializer = propertyValue as ICustomUpdateSerializer; if (updateSerializer != null) { handled = updateSerializer.WriteSetUpdateToXml( writer, this.Owner, propertyDefinition); } if (!handled) { writer.WriteStartElement(XmlNamespace.Types, this.Owner.GetSetFieldXmlElementName()); propertyDefinition.WriteToXml(writer); writer.WriteStartElement(XmlNamespace.Types, this.Owner.GetXmlElementName()); propertyDefinition.WritePropertyValueToXml(writer, this, true /* isUpdateOperation */); writer.WriteEndElement(); writer.WriteEndElement(); } } }
/// <summary> /// Writes the set update to json. /// </summary> /// <param name="jsonUpdates">The json updates.</param> /// <param name="propertyDefinition">The property definition.</param> /// <param name="service">The service.</param> private void WriteSetUpdateToJson(List <JsonObject> jsonUpdates, PropertyDefinition propertyDefinition, ExchangeService service) { // The following test should not be necessary since the property bag prevents // properties to be updated if they don't have the CanUpdate flag, but it // doesn't hurt... if (propertyDefinition.HasFlag(PropertyDefinitionFlags.CanUpdate)) { object propertyValue = this[propertyDefinition]; bool handled = false; ICustomUpdateSerializer updateSerializer = propertyValue as ICustomUpdateSerializer; if (updateSerializer != null) { handled = updateSerializer.WriteSetUpdateToJson( service, this.Owner, propertyDefinition, jsonUpdates); } if (!handled) { JsonObject jsonUpdate = CreateJsonSetUpdate(propertyDefinition, service, this.Owner, this); jsonUpdates.Add(jsonUpdate); } } }
/// <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> /// 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 { // FJC: Removing to avoid crashing when syncing with Exchange servers that send back "Mentions". //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); } }