internal ClientTypeAnnotation ResolveEdmTypeName(Type expectedType, string edmTypeName) { ClientTypeAnnotation clientTypeAnnotation; PrimitiveType type; string collectionItemWireTypeName = WebUtil.GetCollectionItemWireTypeName(edmTypeName); string str2 = collectionItemWireTypeName ?? edmTypeName; ClientEdmModel model = ClientEdmModel.GetModel(this.ResponseInfo.MaxProtocolVersion); if (PrimitiveType.TryGetPrimitiveType(str2, out type)) { clientTypeAnnotation = model.GetClientTypeAnnotation(type.ClrType); } else if (!this.edmTypeNameMap.TryGetValue(str2, out clientTypeAnnotation)) { clientTypeAnnotation = model.GetClientTypeAnnotation(str2); } if (collectionItemWireTypeName == null) { return(clientTypeAnnotation); } Type elementType = clientTypeAnnotation.ElementType; if (type != null) { elementType = ClientTypeUtil.GetImplementationType(expectedType, typeof(ICollection <>)).GetGenericArguments()[0]; } Type backingTypeForCollectionProperty = WebUtil.GetBackingTypeForCollectionProperty(expectedType, elementType); return(model.GetClientTypeAnnotation(backingTypeForCollectionProperty)); }
internal void WriteNavigationLink(EntityDescriptor entityDescriptor, IEnumerable <LinkDescriptor> relatedLinks, ODataWriter odataWriter) { ClientTypeAnnotation clientTypeAnnotation = null; foreach (LinkDescriptor descriptor in relatedLinks) { descriptor.ContentGeneratedForSave = true; if (clientTypeAnnotation == null) { ClientEdmModel model = ClientEdmModel.GetModel(this.requestInfo.MaxProtocolVersion); clientTypeAnnotation = model.GetClientTypeAnnotation(model.GetOrCreateEdmType(entityDescriptor.Entity.GetType())); } ODataNavigationLink navigationLink = new ODataNavigationLink { Url = this.requestInfo.EntityTracker.GetEntityDescriptor(descriptor.Target).GetLatestEditLink(), IsCollection = new bool?(clientTypeAnnotation.GetProperty(descriptor.SourceProperty, false).IsEntityCollection), Name = descriptor.SourceProperty }; odataWriter.WriteStart(navigationLink); ODataEntityReferenceLink entityReferenceLink = new ODataEntityReferenceLink { Url = navigationLink.Url }; odataWriter.WriteEntityReferenceLink(entityReferenceLink); odataWriter.WriteEnd(); } }
protected ODataRequestMessageWrapper CreateRequest(EntityDescriptor entityDescriptor) { EntityStates state = entityDescriptor.State; Uri resourceUri = entityDescriptor.GetResourceUri(this.RequestInfo.BaseUriResolver, false); ClientEdmModel model = ClientEdmModel.GetModel(this.RequestInfo.MaxProtocolVersion); Version requestVersion = DetermineRequestVersion(model.GetClientTypeAnnotation(model.GetOrCreateEdmType(entityDescriptor.Entity.GetType())), state); string httpMethod = this.GetHttpMethod(state, ref requestVersion); ODataRequestMessageWrapper requestMessage = this.CreateRequestMessage(resourceUri, httpMethod); if (this.IsBatch) { requestMessage.SetHeader("Content-ID", entityDescriptor.ChangeOrder.ToString(CultureInfo.InvariantCulture)); } if (EntityStates.Deleted != entityDescriptor.State) { requestMessage.SetHeader("Content-Type", "application/atom+xml"); } if ((EntityStates.Deleted == state) || (EntityStates.Modified == state)) { string latestETag = entityDescriptor.GetLatestETag(); if (latestETag != null) { requestMessage.SetHeader("If-Match", latestETag); if (!this.IsBatch) { requestMessage.AddHeadersToReset("If-Match"); } } } ApplyPreferences(requestMessage, httpMethod, this.RequestInfo.AddAndUpdateResponsePreference, ref requestVersion); WebUtil.SetOperationVersionHeaders(requestMessage, requestVersion, this.RequestInfo.MaxProtocolVersionAsVersion); return(requestMessage); }
/// <summary> /// Creates and returns an ODataComplexValue from the given value. /// </summary> /// <param name="complexType">The value type.</param> /// <param name="value">The complex value.</param> /// <param name="propertyName">If the value is a property, then it represents the name of the property. Can be null, for non-property.</param> /// <param name="isCollectionItem">True, if the value is an item in a collection, false otherwise.</param> /// <param name="visitedComplexTypeObjects">Set of instances of complex types encountered in the hierarchy. Used to detect cycles.</param> /// <returns>An ODataComplexValue representing the given value.</returns> internal ODataComplexValue CreateODataComplexValue(Type complexType, object value, string propertyName, bool isCollectionItem, HashSet <object> visitedComplexTypeObjects) { Debug.Assert(complexType != null, "complexType != null"); Debug.Assert(value != null || !isCollectionItem, "Collection items must not be null"); ClientEdmModel model = this.requestInfo.Model; ClientTypeAnnotation complexTypeAnnotation = model.GetClientTypeAnnotation(complexType); Debug.Assert(complexTypeAnnotation != null, "complexTypeAnnotation != null"); Debug.Assert(!complexTypeAnnotation.IsEntityType, "Unexpected entity"); // Handle null values for complex types by putting m:null="true" if (value == null) { Debug.Assert(!isCollectionItem, "Null collection items are not supported. Should have already been checked."); return(null); } if (visitedComplexTypeObjects == null) { visitedComplexTypeObjects = new HashSet <object>(ReferenceEqualityComparer <object> .Instance); } else if (visitedComplexTypeObjects.Contains(value)) { if (propertyName != null) { throw Error.InvalidOperation(Strings.Serializer_LoopsNotAllowedInComplexTypes(propertyName)); } else { Debug.Assert(complexTypeAnnotation.ElementTypeName != null, "complexTypeAnnotation.ElementTypeName != null"); throw Error.InvalidOperation(Strings.Serializer_LoopsNotAllowedInNonPropertyComplexTypes(complexTypeAnnotation.ElementTypeName)); } } visitedComplexTypeObjects.Add(value); ODataComplexValue odataComplexValue = new ODataComplexValue(); // When TypeName is set, it causes validation to occur when ODataLib writes out the collection. Part of the validation ensures that all items // in the collection are exactly the same type, no derived types are allowed. In the released WCF Data Services 5.0 implementation, we don't set // TypeName here, so that validation does not occur, therefore we will set this value only for JSON Light, so we don't break existing code. if (!this.requestInfo.Format.UsingAtom) { odataComplexValue.TypeName = complexTypeAnnotation.ElementTypeName; } // If this complex type is a collection item don't put type name on each item if (!isCollectionItem) { odataComplexValue.SetAnnotation(new SerializationTypeNameAnnotation { TypeName = this.requestInfo.GetServerTypeName(complexTypeAnnotation) }); } odataComplexValue.Properties = this.PopulateProperties(value, complexTypeAnnotation.PropertiesToSerialize(), visitedComplexTypeObjects); visitedComplexTypeObjects.Remove(value); return(odataComplexValue); }
internal IEdmType ResolveWireTypeName(IEdmType expectedEdmType, string wireName) { Type elementType; ClientEdmModel model = ClientEdmModel.GetModel(this.ResponseInfo.MaxProtocolVersion); if (expectedEdmType != null) { ClientTypeAnnotation annotation = model.GetClientTypeAnnotation(expectedEdmType); elementType = annotation.ElementType; if (annotation.EdmType.TypeKind == EdmTypeKind.Primitive) { return(expectedEdmType); } } else { elementType = typeof(object); } Type type2 = this.ResolveTypeFromName(wireName, elementType); ClientTypeAnnotation clientTypeAnnotation = model.GetClientTypeAnnotation(model.GetOrCreateEdmType(type2)); if (clientTypeAnnotation.IsEntityType) { clientTypeAnnotation.EnsureEPMLoaded(); } switch (clientTypeAnnotation.EdmType.TypeKind) { case EdmTypeKind.Entity: case EdmTypeKind.Complex: { string key = clientTypeAnnotation.EdmType.FullName(); if (!this.edmTypeNameMap.ContainsKey(key)) { this.edmTypeNameMap.Add(key, clientTypeAnnotation); } break; } } return(clientTypeAnnotation.EdmType); }
/// <summary> /// Creates the ResponseInfo object. /// </summary> /// <returns>ResponseInfo object.</returns> protected override ResponseInfo CreateResponseInfo() { DataServiceContext context = (DataServiceContext)this.Source; ClientEdmModel model = context.Model; ClientTypeAnnotation type = model.GetClientTypeAnnotation(model.GetOrCreateEdmType(this.entity.GetType())); Debug.Assert(type.IsEntityType, "Must be entity type to be contained."); return(this.RequestInfo.GetDeserializationInfoForLoadProperty( null, context.GetEntityDescriptor(this.entity), type.GetProperty(this.propertyName, false))); }
/// <summary> /// loading a property from a response /// </summary> /// <returns>QueryOperationResponse instance containing information about the response.</returns> internal QueryOperationResponse LoadProperty() { MaterializeAtom results = null; DataServiceContext context = (DataServiceContext)this.Source; ClientEdmModel model = context.Model; ClientTypeAnnotation type = model.GetClientTypeAnnotation(model.GetOrCreateEdmType(this.entity.GetType())); Debug.Assert(type.IsEntityType, "must be entity type to be contained"); EntityDescriptor box = context.GetEntityDescriptor(this.entity); if (EntityStates.Added == box.State) { throw Error.InvalidOperation(Strings.Context_NoLoadWithInsertEnd); } ClientPropertyAnnotation property = type.GetProperty(this.propertyName, false); Type elementType = property.EntityCollectionItemType ?? property.NullablePropertyType; try { if (type.MediaDataMember == property) { results = this.ReadPropertyFromRawData(property); } else { results = this.ReadPropertyFromAtom(property); } return(this.GetResponseWithType(results, elementType)); } catch (InvalidOperationException ex) { QueryOperationResponse response = this.GetResponseWithType(results, elementType); if (response != null) { response.Error = ex; throw new DataServiceQueryException(Strings.DataServiceException_GeneralError, ex, response); } throw; } }
internal QueryOperationResponse LoadProperty() { MaterializeAtom results = null; QueryOperationResponse responseWithType; DataServiceContext source = (DataServiceContext)base.Source; ClientEdmModel model = ClientEdmModel.GetModel(source.MaxProtocolVersion); ClientTypeAnnotation clientTypeAnnotation = model.GetClientTypeAnnotation(model.GetOrCreateEdmType(this.entity.GetType())); EntityDescriptor entityDescriptor = source.GetEntityDescriptor(this.entity); if (EntityStates.Added == entityDescriptor.State) { throw System.Data.Services.Client.Error.InvalidOperation(System.Data.Services.Client.Strings.Context_NoLoadWithInsertEnd); } ClientPropertyAnnotation property = clientTypeAnnotation.GetProperty(this.propertyName, false); Type elementType = property.EntityCollectionItemType ?? property.NullablePropertyType; try { if (clientTypeAnnotation.MediaDataMember == property) { results = this.ReadPropertyFromRawData(property); } else { results = this.ReadPropertyFromAtom(entityDescriptor, property); } responseWithType = base.GetResponseWithType(results, elementType); } catch (InvalidOperationException exception) { QueryOperationResponse response = base.GetResponseWithType(results, elementType); if (response != null) { response.Error = exception; throw new DataServiceQueryException(System.Data.Services.Client.Strings.DataServiceException_GeneralError, exception, response); } throw; } return(responseWithType); }
internal void WriteEntry(EntityDescriptor entityDescriptor, IEnumerable <LinkDescriptor> relatedLinks, ODataRequestMessageWrapper requestMessage) { ClientEdmModel model = ClientEdmModel.GetModel(this.requestInfo.MaxProtocolVersion); ClientTypeAnnotation clientTypeAnnotation = model.GetClientTypeAnnotation(model.GetOrCreateEdmType(entityDescriptor.Entity.GetType())); using (ODataMessageWriter writer = CreateMessageWriter(requestMessage, this.requestInfo)) { ODataWriter odataWriter = writer.CreateODataEntryWriter(); ODataEntry entry = new ODataEntry(); if (this.requestInfo.HasWritingEventHandlers) { entry.SetAnnotation <WritingEntityInfo>(new WritingEntityInfo(entityDescriptor.Entity, this.requestInfo)); } string serverTypeName = this.requestInfo.GetServerTypeName(entityDescriptor); if (clientTypeAnnotation.ElementTypeName != serverTypeName) { SerializationTypeNameAnnotation annotation = new SerializationTypeNameAnnotation { TypeName = serverTypeName }; entry.SetAnnotation <SerializationTypeNameAnnotation>(annotation); } entry.TypeName = clientTypeAnnotation.ElementTypeName; if (EntityStates.Modified == entityDescriptor.State) { entry.Id = entityDescriptor.GetLatestIdentity(); } if (entityDescriptor.IsMediaLinkEntry || clientTypeAnnotation.IsMediaLinkEntry) { entry.MediaResource = new ODataStreamReferenceValue(); } odataWriter.WriteStart(entry); if (EntityStates.Added == entityDescriptor.State) { this.WriteNavigationLink(entityDescriptor, relatedLinks, odataWriter); } entry.Properties = this.PopulateProperties(clientTypeAnnotation, entityDescriptor.Entity, null); odataWriter.WriteEnd(); } }
internal void AttachLink(object source, string sourceProperty, object target, MergeOption linkMerge) { LinkDescriptor linkDescriptor = new LinkDescriptor(source, sourceProperty, target, this.maxProtocolVersion); LinkDescriptor descriptor2 = this.TryGetLinkDescriptor(source, sourceProperty, target); if (descriptor2 != null) { switch (linkMerge) { case MergeOption.OverwriteChanges: linkDescriptor = descriptor2; break; case MergeOption.PreserveChanges: if (((EntityStates.Added == descriptor2.State) || (EntityStates.Unchanged == descriptor2.State)) || ((EntityStates.Modified == descriptor2.State) && (descriptor2.Target != null))) { linkDescriptor = descriptor2; } break; case MergeOption.NoTracking: throw System.Data.Services.Client.Error.InvalidOperation(System.Data.Services.Client.Strings.Context_RelationAlreadyContained); } } else { ClientEdmModel model = ClientEdmModel.GetModel(this.maxProtocolVersion); if (model.GetClientTypeAnnotation(model.GetOrCreateEdmType(source.GetType())).GetProperty(sourceProperty, false).IsEntityCollection || ((descriptor2 = this.DetachReferenceLink(source, sourceProperty, target, linkMerge)) == null)) { this.AddLink(linkDescriptor); this.IncrementChange(linkDescriptor); } else if ((linkMerge != MergeOption.AppendOnly) && ((MergeOption.PreserveChanges != linkMerge) || (EntityStates.Modified != descriptor2.State))) { linkDescriptor = descriptor2; } } linkDescriptor.State = EntityStates.Unchanged; }
/// <summary> /// Write the entry element. /// </summary> /// <param name="entityDescriptor">The entity.</param> /// <param name="relatedLinks">Collection of links related to the entity.</param> /// <param name="requestMessage">The OData request message.</param> internal void WriteEntry(EntityDescriptor entityDescriptor, IEnumerable <LinkDescriptor> relatedLinks, ODataRequestMessageWrapper requestMessage) { ClientEdmModel model = this.requestInfo.Model; ClientTypeAnnotation entityType = model.GetClientTypeAnnotation(model.GetOrCreateEdmType(entityDescriptor.Entity.GetType())); using (ODataMessageWriter messageWriter = Serializer.CreateMessageWriter(requestMessage, this.requestInfo, false /*isParameterPayload*/)) { ODataWriterWrapper entryWriter = ODataWriterWrapper.CreateForEntry(messageWriter, this.requestInfo.Configurations.RequestPipeline); // Get the server type name using the type resolver or from the entity descriptor string serverTypeName = this.requestInfo.GetServerTypeName(entityDescriptor); var entry = CreateODataEntry(entityDescriptor, serverTypeName, entityType, this.requestInfo.Format); // Add the annotation required for writing the payload into an XElement // for firing WritingEntity events if (this.requestInfo.HasWritingEventHandlers) { entry.SetAnnotation(new WritingEntityInfo(entityDescriptor.Entity, this.requestInfo)); } if (serverTypeName == null) { serverTypeName = this.requestInfo.InferServerTypeNameFromServerModel(entityDescriptor); } entry.Properties = this.propertyConverter.PopulateProperties(entityDescriptor.Entity, serverTypeName, entityType.PropertiesToSerialize()); entryWriter.WriteStart(entry, entityDescriptor.Entity); if (EntityStates.Added == entityDescriptor.State) { this.WriteNavigationLink(entityDescriptor, relatedLinks, entryWriter); } entryWriter.WriteEnd(entry, entityDescriptor.Entity); } }
private string ConvertToEscapedUriValue(string paramName, object value) { object obj2 = null; string str; bool flag = false; if (value == null) { flag = true; } else if (value.GetType() == typeof(ODataUriNullValue)) { obj2 = value; flag = true; } else { ClientTypeAnnotation annotation3; ClientEdmModel model = ClientEdmModel.GetModel(this.requestInfo.MaxProtocolVersion); IEdmType orCreateEdmType = model.GetOrCreateEdmType(value.GetType()); switch (orCreateEdmType.TypeKind) { case EdmTypeKind.Primitive: obj2 = value; flag = true; goto Label_0155; case EdmTypeKind.Complex: { ClientTypeAnnotation clientTypeAnnotation = model.GetClientTypeAnnotation(orCreateEdmType); obj2 = this.CreateODataComplexValue(clientTypeAnnotation.ElementType, value, null, false, null); SerializationTypeNameAnnotation annotation = ((ODataComplexValue)obj2).GetAnnotation <SerializationTypeNameAnnotation>(); if ((annotation == null) || string.IsNullOrEmpty(annotation.TypeName)) { throw System.Data.Services.Client.Error.InvalidOperation(System.Data.Services.Client.Strings.DataServiceException_GeneralError); } goto Label_0155; } case EdmTypeKind.Collection: { IEdmCollectionType type2 = orCreateEdmType as IEdmCollectionType; IEdmTypeReference elementType = type2.ElementType; annotation3 = model.GetClientTypeAnnotation(elementType.Definition); switch (annotation3.EdmType.TypeKind) { case EdmTypeKind.Primitive: case EdmTypeKind.Complex: obj2 = this.CreateODataCollection(annotation3.ElementType, null, value, null); goto Label_0155; } break; } default: throw new NotSupportedException(System.Data.Services.Client.Strings.Serializer_InvalidParameterType(paramName, orCreateEdmType.TypeKind)); } throw new NotSupportedException(System.Data.Services.Client.Strings.Serializer_InvalidCollectionParamterItemType(paramName, annotation3.EdmType.TypeKind)); } Label_0155: str = ODataUriUtils.ConvertToUriLiteral(obj2, CommonUtil.ConvertToODataVersion(this.requestInfo.MaxProtocolVersionAsVersion)); if (flag) { return(DataStringEscapeBuilder.EscapeDataString(str)); } return(Uri.EscapeDataString(str)); }
/// <summary>Obtain binding info corresponding to a given type</summary> /// <param name="entityType">Type for which to obtain information</param> /// <param name="model">The client model.</param> /// <returns>Info about the <paramref name="entityType"/></returns> private static BindingEntityInfoPerType GetBindingEntityInfoFor(Type entityType, ClientEdmModel model) { BindingEntityInfoPerType bindingEntityInfo; metadataCacheLock.EnterReadLock(); try { if (bindingEntityInfos.TryGetValue(entityType, out bindingEntityInfo)) { return(bindingEntityInfo); } } finally { metadataCacheLock.ExitReadLock(); } bindingEntityInfo = new BindingEntityInfoPerType(); // Try to get the entity set name from the EntitySetAttribute attributes. In order to make the // inheritance work, we need to look at the attributes declared in the base types also. // EntitySetAttribute does not allow multiples, so there can be at most 1 instance on the type. EntitySetAttribute entitySetAttribute = (EntitySetAttribute)entityType.GetCustomAttributes(typeof(EntitySetAttribute), true).SingleOrDefault(); // There must be exactly one (unambiguous) EntitySetAttribute attribute. bindingEntityInfo.EntitySet = entitySetAttribute != null ? entitySetAttribute.EntitySet : null; bindingEntityInfo.ClientType = model.GetClientTypeAnnotation(model.GetOrCreateEdmType(entityType)); foreach (ClientPropertyAnnotation p in bindingEntityInfo.ClientType.Properties()) { BindingPropertyInfo bpi = null; Type propertyType = p.PropertyType; if (p.IsStreamLinkProperty) { // DataServiceStreamLink is not mutable externally // It implements INPC to notify controls about our updates // We should ignore its events since we are the only one updating it. continue; } else if (p.IsPrimitiveOrComplexCollection) { Debug.Assert(!BindingEntityInfo.IsDataServiceCollection(propertyType, model), "DataServiceCollection cannot be the type that backs collections of primitives or complex types."); bpi = new BindingPropertyInfo { PropertyKind = BindingPropertyKind.BindingPropertyKindPrimitiveOrComplexCollection }; } else if (p.IsEntityCollection) { if (BindingEntityInfo.IsDataServiceCollection(propertyType, model)) { bpi = new BindingPropertyInfo { PropertyKind = BindingPropertyKind.BindingPropertyKindDataServiceCollection }; } } else if (BindingEntityInfo.IsEntityType(propertyType, model)) { bpi = new BindingPropertyInfo { PropertyKind = BindingPropertyKind.BindingPropertyKindEntity }; } else if (BindingEntityInfo.CanBeComplexType(propertyType)) { // Add complex types and nothing else. Debug.Assert(!p.IsKnownType, "Known types do not implement INotifyPropertyChanged."); bpi = new BindingPropertyInfo { PropertyKind = BindingPropertyKind.BindingPropertyKindComplex }; } if (bpi != null) { bpi.PropertyInfo = p; // For entity types, all of the above types of properties are interesting. // For complex types, only observe collections and complex type properties. if (bindingEntityInfo.ClientType.IsEntityType || bpi.PropertyKind == BindingPropertyKind.BindingPropertyKindComplex || bpi.PropertyKind == BindingPropertyKind.BindingPropertyKindPrimitiveOrComplexCollection) { bindingEntityInfo.ObservableProperties.Add(bpi); } } } metadataCacheLock.EnterWriteLock(); try { if (!bindingEntityInfos.ContainsKey(entityType)) { bindingEntityInfos[entityType] = bindingEntityInfo; } } finally { metadataCacheLock.ExitWriteLock(); } return(bindingEntityInfo); }
private ODataRequestMessageWrapper CheckAndProcessMediaEntryPost(EntityDescriptor entityDescriptor) { ClientEdmModel model = ClientEdmModel.GetModel(base.RequestInfo.MaxProtocolVersion); ClientTypeAnnotation clientTypeAnnotation = model.GetClientTypeAnnotation(model.GetOrCreateEdmType(entityDescriptor.Entity.GetType())); if (!clientTypeAnnotation.IsMediaLinkEntry && !entityDescriptor.IsMediaLinkEntry) { return(null); } if ((clientTypeAnnotation.MediaDataMember == null) && (entityDescriptor.SaveStream == null)) { throw System.Data.Services.Client.Error.InvalidOperation(System.Data.Services.Client.Strings.Context_MLEWithoutSaveStream(clientTypeAnnotation.ElementTypeName)); } ODataRequestMessageWrapper mediaResourceRequest = null; if (clientTypeAnnotation.MediaDataMember != null) { string contentType = null; int length = 0; if (clientTypeAnnotation.MediaDataMember.MimeTypeProperty == null) { contentType = "application/octet-stream"; } else { object obj2 = clientTypeAnnotation.MediaDataMember.MimeTypeProperty.GetValue(entityDescriptor.Entity); string str2 = (obj2 != null) ? obj2.ToString() : null; if (string.IsNullOrEmpty(str2)) { throw System.Data.Services.Client.Error.InvalidOperation(System.Data.Services.Client.Strings.Context_NoContentTypeForMediaLink(clientTypeAnnotation.ElementTypeName, clientTypeAnnotation.MediaDataMember.MimeTypeProperty.PropertyName)); } contentType = str2; } object propertyValue = clientTypeAnnotation.MediaDataMember.GetValue(entityDescriptor.Entity); if (propertyValue == null) { base.mediaResourceRequestStream = null; } else { byte[] bytes = propertyValue as byte[]; if (bytes == null) { string str3; Encoding encoding; HttpProcessUtility.ReadContentType(contentType, out str3, out encoding); if (encoding == null) { encoding = Encoding.UTF8; contentType = contentType + ";charset=UTF-8"; } bytes = encoding.GetBytes(ClientConvert.ToString(propertyValue)); } length = bytes.Length; base.mediaResourceRequestStream = new MemoryStream(bytes, 0, bytes.Length, false, true); } mediaResourceRequest = this.CreateMediaResourceRequest(entityDescriptor.GetResourceUri(base.RequestInfo.BaseUriResolver, false), "POST", Util.DataServiceVersion1, clientTypeAnnotation.MediaDataMember == null, true); mediaResourceRequest.SetHeader("Content-Length", length.ToString(CultureInfo.InvariantCulture)); mediaResourceRequest.SetHeader("Content-Type", contentType); mediaResourceRequest.AddHeadersToReset("Content-Length"); mediaResourceRequest.AddHeadersToReset("Content-Type"); } else { mediaResourceRequest = this.CreateMediaResourceRequest(entityDescriptor.GetResourceUri(base.RequestInfo.BaseUriResolver, false), "POST", Util.DataServiceVersion1, clientTypeAnnotation.MediaDataMember == null, true); this.SetupMediaResourceRequest(mediaResourceRequest, entityDescriptor.SaveStream, null); } entityDescriptor.State = EntityStates.Modified; return(mediaResourceRequest); }
private static BindingEntityInfoPerType GetBindingEntityInfoFor(Type entityType, DataServiceProtocolVersion maxProtocolVersion) { BindingEntityInfoPerType type; metadataCacheLock.EnterReadLock(); try { if (bindingEntityInfos.TryGetValue(entityType, out type)) { return(type); } } finally { metadataCacheLock.ExitReadLock(); } type = new BindingEntityInfoPerType(); EntitySetAttribute attribute = (EntitySetAttribute)entityType.GetCustomAttributes(typeof(EntitySetAttribute), true).SingleOrDefault <object>(); ClientEdmModel model = ClientEdmModel.GetModel(maxProtocolVersion); type.EntitySet = (attribute != null) ? attribute.EntitySet : null; type.ClientType = model.GetClientTypeAnnotation(model.GetOrCreateEdmType(entityType)); foreach (ClientPropertyAnnotation annotation in type.ClientType.Properties()) { BindingPropertyInfo item = null; Type propertyType = annotation.PropertyType; if (!annotation.IsStreamLinkProperty) { if (annotation.IsPrimitiveOrComplexCollection) { item = new BindingPropertyInfo { PropertyKind = BindingPropertyKind.BindingPropertyKindPrimitiveOrComplexCollection }; } else if (annotation.IsEntityCollection) { if (IsDataServiceCollection(propertyType, maxProtocolVersion)) { item = new BindingPropertyInfo { PropertyKind = BindingPropertyKind.BindingPropertyKindDataServiceCollection }; } } else if (IsEntityType(propertyType, maxProtocolVersion)) { item = new BindingPropertyInfo { PropertyKind = BindingPropertyKind.BindingPropertyKindEntity }; } else if (CanBeComplexType(propertyType)) { item = new BindingPropertyInfo { PropertyKind = BindingPropertyKind.BindingPropertyKindComplex }; } if (item != null) { item.PropertyInfo = annotation; if ((type.ClientType.IsEntityType || (item.PropertyKind == BindingPropertyKind.BindingPropertyKindComplex)) || (item.PropertyKind == BindingPropertyKind.BindingPropertyKindPrimitiveOrComplexCollection)) { type.ObservableProperties.Add(item); } } } } metadataCacheLock.EnterWriteLock(); try { if (!bindingEntityInfos.ContainsKey(entityType)) { bindingEntityInfos[entityType] = type; } } finally { metadataCacheLock.ExitWriteLock(); } return(type); }
/// <summary> /// Writes the body operation parameters associated with a ServiceAction. /// </summary> /// <param name="operationParameters">The list of operation parameters to write.</param> /// <param name="requestMessage">The OData request message used to write the operation parameters.</param> internal void WriteBodyOperationParameters(List <BodyOperationParameter> operationParameters, ODataRequestMessageWrapper requestMessage) { Debug.Assert(requestMessage != null, "requestMessage != null"); Debug.Assert(operationParameters != null, "operationParameters != null"); Debug.Assert(operationParameters.Any(), "operationParameters.Any()"); using (ODataMessageWriter messageWriter = Serializer.CreateMessageWriter(requestMessage, this.requestInfo, true /*isParameterPayload*/)) { ODataParameterWriter parameterWriter = messageWriter.CreateODataParameterWriter(null); parameterWriter.WriteStart(); foreach (OperationParameter operationParameter in operationParameters) { if (operationParameter.Value == null) { parameterWriter.WriteValue(operationParameter.Name, operationParameter.Value); } else { ClientEdmModel model = this.requestInfo.Model; IEdmType edmType = model.GetOrCreateEdmType(operationParameter.Value.GetType()); Debug.Assert(edmType != null, "edmType != null"); switch (edmType.TypeKind) { case EdmTypeKind.Collection: { Collections.IEnumerator enumerator = ((ICollection)operationParameter.Value).GetEnumerator(); ODataCollectionWriter collectionWriter = parameterWriter.CreateCollectionWriter(operationParameter.Name); ODataCollectionStart odataCollectionStart = new ODataCollectionStart(); collectionWriter.WriteStart(odataCollectionStart); while (enumerator.MoveNext()) { Object collectionItem = enumerator.Current; if (collectionItem == null) { throw new NotSupportedException(Strings.Serializer_NullCollectionParamterItemValue(operationParameter.Name)); } IEdmType edmItemType = model.GetOrCreateEdmType(collectionItem.GetType()); Debug.Assert(edmItemType != null, "edmItemType != null"); switch (edmItemType.TypeKind) { case EdmTypeKind.Complex: { Debug.Assert(model.GetClientTypeAnnotation(edmItemType).ElementType != null, "edmItemType.GetClientTypeAnnotation().ElementType != null"); ODataComplexValue complexValue = this.propertyConverter.CreateODataComplexValue( model.GetClientTypeAnnotation(edmItemType).ElementType, collectionItem, null /*propertyName*/, false /*isCollectionItem*/, null /*visitedComplexTypeObjects*/); Debug.Assert(complexValue != null, "complexValue != null"); collectionWriter.WriteItem(complexValue); break; } case EdmTypeKind.Primitive: { collectionWriter.WriteItem(collectionItem); break; } default: // EdmTypeKind.Entity // EdmTypeKind.Row // EdmTypeKind.EntityReference // EdmTypeKind.Enum. throw new NotSupportedException(Strings.Serializer_InvalidCollectionParamterItemType(operationParameter.Name, edmItemType.TypeKind)); } } collectionWriter.WriteEnd(); collectionWriter.Flush(); break; } case EdmTypeKind.Complex: { Debug.Assert(model.GetClientTypeAnnotation(edmType).ElementType != null, "model.GetClientTypeAnnotation(edmType).ElementType != null"); ODataComplexValue complexValue = this.propertyConverter.CreateODataComplexValue( model.GetClientTypeAnnotation(edmType).ElementType, operationParameter.Value, null /*propertyName*/, false /*isCollectionItemType*/, null /*visitedComplexTypeObjects*/); Debug.Assert(complexValue != null, "complexValue != null"); parameterWriter.WriteValue(operationParameter.Name, complexValue); break; } case EdmTypeKind.Primitive: parameterWriter.WriteValue(operationParameter.Name, operationParameter.Value); break; default: // EdmTypeKind.Entity // EdmTypeKind.Row // EdmTypeKind.EntityReference // EdmTypeKind.Enum. throw new NotSupportedException(Strings.Serializer_InvalidParameterType(operationParameter.Name, edmType.TypeKind)); } } // else } // foreach parameterWriter.WriteEnd(); parameterWriter.Flush(); } }
/// <summary> /// Writes a navigation link. /// </summary> /// <param name="entityDescriptor">The entity</param> /// <param name="relatedLinks">The links related to the entity</param> /// <param name="odataWriter">The ODataWriter used to write the navigation link.</param> internal void WriteNavigationLink(EntityDescriptor entityDescriptor, IEnumerable <LinkDescriptor> relatedLinks, ODataWriterWrapper odataWriter) { // TODO:: create instance of odatawriter. // TODO:: send clientType once, so that we dont need entity descriptor Debug.Assert(EntityStates.Added == entityDescriptor.State, "entity not added state"); Dictionary <string, List <LinkDescriptor> > groupRelatedLinks = new Dictionary <string, List <LinkDescriptor> >(EqualityComparer <string> .Default); foreach (LinkDescriptor end in relatedLinks) { List <LinkDescriptor> linkDescriptorsList = null; if (!groupRelatedLinks.TryGetValue(end.SourceProperty, out linkDescriptorsList)) { linkDescriptorsList = new List <LinkDescriptor>(); groupRelatedLinks.Add(end.SourceProperty, linkDescriptorsList); } linkDescriptorsList.Add(end); } ClientTypeAnnotation clientType = null; foreach (var grlinks in groupRelatedLinks) { if (null == clientType) { ClientEdmModel model = this.requestInfo.Model; clientType = model.GetClientTypeAnnotation(model.GetOrCreateEdmType(entityDescriptor.Entity.GetType())); } bool isCollection = clientType.GetProperty(grlinks.Key, false).IsEntityCollection; bool started = false; foreach (LinkDescriptor end in grlinks.Value) { Debug.Assert(!end.ContentGeneratedForSave, "already saved link"); end.ContentGeneratedForSave = true; Debug.Assert(null != end.Target, "null is DELETE"); ODataNavigationLink navigationLink = new ODataNavigationLink(); navigationLink.Url = this.requestInfo.EntityTracker.GetEntityDescriptor(end.Target).GetLatestEditLink(); Debug.Assert(Uri.IsWellFormedUriString(UriUtil.UriToString(navigationLink.Url), UriKind.Absolute), "Uri.IsWellFormedUriString(targetEditLink, UriKind.Absolute)"); navigationLink.IsCollection = isCollection; navigationLink.Name = grlinks.Key; if (!started) { odataWriter.WriteNavigationLinksStart(navigationLink); started = true; } odataWriter.WriteNavigationLinkStart(navigationLink, end.Source, end.Target); odataWriter.WriteEntityReferenceLink(new ODataEntityReferenceLink() { Url = navigationLink.Url }, end.Source, end.Target); odataWriter.WriteNavigationLinkEnd(navigationLink, end.Source, end.Target); } odataWriter.WriteNavigationLinksEnd(); } }
private string ConvertToEscapedUriValue(string paramName, object value) { Debug.Assert(!string.IsNullOrEmpty(paramName), "!string.IsNullOrEmpty(paramName)"); Object valueInODataFormat = null; // Literal values with single quotes need special escaping due to System.Uri changes in behavior between .NET 4.0 and 4.5. // We need to ensure that our escaped values do not change between those versions, so we need to escape values differently when they could contain single quotes. bool needsSpecialEscaping = false; if (value == null) { needsSpecialEscaping = true; } else { if (value.GetType() == typeof(ODataUriNullValue)) { valueInODataFormat = value; needsSpecialEscaping = true; } else { ClientEdmModel model = this.requestInfo.Model; IEdmType edmType = model.GetOrCreateEdmType(value.GetType()); Debug.Assert(edmType != null, "edmType != null"); switch (edmType.TypeKind) { case EdmTypeKind.Primitive: valueInODataFormat = value; needsSpecialEscaping = true; break; case EdmTypeKind.Complex: ClientTypeAnnotation typeAnnotation = model.GetClientTypeAnnotation(edmType); Debug.Assert(typeAnnotation != null, "typeAnnotation != null"); valueInODataFormat = this.propertyConverter.CreateODataComplexValue( typeAnnotation.ElementType, value, null /*propertyName*/, false /*isCollectionItemType*/, null /*visitedComplexTypeObjects*/); // When using JsonVerbose to format query string parameters for Actions, // we cannot write out Complex values in the URI without the type name of the complex type in the JSON payload. // If this value is null, the client has to set the ResolveName property on the DataServiceContext instance. ODataComplexValue complexValue = (ODataComplexValue)valueInODataFormat; SerializationTypeNameAnnotation serializedTypeNameAnnotation = complexValue.GetAnnotation <SerializationTypeNameAnnotation>(); if (serializedTypeNameAnnotation == null || string.IsNullOrEmpty(serializedTypeNameAnnotation.TypeName)) { throw Error.InvalidOperation(Strings.DataServiceException_GeneralError); } break; case EdmTypeKind.Collection: IEdmCollectionType edmCollectionType = edmType as IEdmCollectionType; Debug.Assert(edmCollectionType != null, "edmCollectionType != null"); IEdmTypeReference itemTypeReference = edmCollectionType.ElementType; Debug.Assert(itemTypeReference != null, "itemTypeReference != null"); ClientTypeAnnotation itemTypeAnnotation = model.GetClientTypeAnnotation(itemTypeReference.Definition); Debug.Assert(itemTypeAnnotation != null, "itemTypeAnnotation != null"); switch (itemTypeAnnotation.EdmType.TypeKind) { // We only support primitive or complex type as a collection item type. case EdmTypeKind.Primitive: case EdmTypeKind.Complex: break; default: throw new NotSupportedException(Strings.Serializer_InvalidCollectionParamterItemType(paramName, itemTypeAnnotation.EdmType.TypeKind)); } valueInODataFormat = this.propertyConverter.CreateODataCollection( itemTypeAnnotation.ElementType, null /*propertyName*/, value, null /*visitedComplexTypeObjects*/); break; default: // EdmTypeKind.Entity // EdmTypeKind.Row // EdmTypeKind.EntityReference // EdmTypeKind.Enum. throw new NotSupportedException(Strings.Serializer_InvalidParameterType(paramName, edmType.TypeKind)); } } Debug.Assert(valueInODataFormat != null, "valueInODataFormat != null"); } // In the released WCF Data Services 5.0, we didn't pass the model for JSON Verbose literals, so continuing that behavior for backward compatibility ODataFormat literalFormat = this.requestInfo.Format.UriLiteralFormat; IEdmModel edmModel = literalFormat == ODataFormat.VerboseJson ? null : this.requestInfo.Model; // ODL can handle null values so we can send null values here. string literal = ODataUriUtils.ConvertToUriLiteral(valueInODataFormat, CommonUtil.ConvertToODataVersion(this.requestInfo.MaxProtocolVersionAsVersion), edmModel, literalFormat); // The value from ConvertToUriValue will not be escaped, but will already contain literal delimiters like single quotes, so we // need to use our own escape method that will preserve those characters instead of directly calling Uri.EscapeDataString that may escape them. // This is only necessary for primitives and nulls because the other structures are serialized using the JSON format and it uses double quotes // which have always been escaped. if (needsSpecialEscaping) { return(DataStringEscapeBuilder.EscapeDataString(literal)); } return(Uri.EscapeDataString(literal)); }
internal void WriteBodyOperationParameters(List <BodyOperationParameter> operationParameters, ODataRequestMessageWrapper requestMessage) { using (ODataMessageWriter writer = CreateMessageWriter(requestMessage, this.requestInfo)) { ODataParameterWriter writer2 = writer.CreateODataParameterWriter(null); writer2.WriteStart(); foreach (OperationParameter parameter in operationParameters) { IEnumerator enumerator; ODataCollectionWriter writer3; object obj2; if (parameter.Value == null) { writer2.WriteValue(parameter.Name, parameter.Value); continue; } ClientEdmModel model = ClientEdmModel.GetModel(this.requestInfo.MaxProtocolVersion); IEdmType orCreateEdmType = model.GetOrCreateEdmType(parameter.Value.GetType()); switch (orCreateEdmType.TypeKind) { case EdmTypeKind.Primitive: { writer2.WriteValue(parameter.Name, parameter.Value); continue; } case EdmTypeKind.Complex: { ODataComplexValue parameterValue = this.CreateODataComplexValue(model.GetClientTypeAnnotation(orCreateEdmType).ElementType, parameter.Value, null, false, null); writer2.WriteValue(parameter.Name, parameterValue); continue; } case EdmTypeKind.Collection: { enumerator = ((ICollection)parameter.Value).GetEnumerator(); writer3 = writer2.CreateCollectionWriter(parameter.Name); ODataCollectionStart collectionStart = new ODataCollectionStart(); writer3.WriteStart(collectionStart); goto Label_016D; } default: throw new NotSupportedException(System.Data.Services.Client.Strings.Serializer_InvalidParameterType(parameter.Name, orCreateEdmType.TypeKind)); } Label_00D3: obj2 = enumerator.Current; if (obj2 == null) { throw new NotSupportedException(System.Data.Services.Client.Strings.Serializer_NullCollectionParamterItemValue(parameter.Name)); } IEdmType edmType = model.GetOrCreateEdmType(obj2.GetType()); switch (edmType.TypeKind) { case EdmTypeKind.Primitive: writer3.WriteItem(obj2); break; case EdmTypeKind.Complex: { ODataComplexValue item = this.CreateODataComplexValue(model.GetClientTypeAnnotation(edmType).ElementType, obj2, null, false, null); writer3.WriteItem(item); break; } default: throw new NotSupportedException(System.Data.Services.Client.Strings.Serializer_InvalidCollectionParamterItemType(parameter.Name, edmType.TypeKind)); } Label_016D: if (enumerator.MoveNext()) { goto Label_00D3; } writer3.WriteEnd(); writer3.Flush(); } writer2.WriteEnd(); writer2.Flush(); } }
private ODataRequestMessageWrapper GenerateBatchRequest() { if ((base.ChangedEntries.Count == 0) && (this.Queries == null)) { base.SetCompleted(); return(null); } ODataRequestMessageWrapper requestMessage = this.CreateBatchRequest(); using (ODataMessageWriter writer = Serializer.CreateMessageWriter(requestMessage, base.RequestInfo)) { ODataUtils.SetHeadersForPayload(writer, ODataPayloadKind.Batch); requestMessage.FireSendingRequest2(null); this.batchWriter = writer.CreateODataBatchWriter(); this.batchWriter.WriteStartBatch(); if (this.Queries != null) { for (int i = 0; i < this.Queries.Length; i++) { Uri requestUri = base.RequestInfo.BaseUriResolver.CreateAbsoluteUriIfNeeded(this.Queries[i].QueryComponents(base.RequestInfo.MaxProtocolVersion).Uri); ODataRequestMessageWrapper wrapper2 = this.CreateRequestMessage(requestUri, "GET"); Version requestVersion = this.Queries[i].QueryComponents(base.RequestInfo.MaxProtocolVersion).Version; WebUtil.SetOperationVersionHeaders(wrapper2, requestVersion, base.RequestInfo.MaxProtocolVersionAsVersion); wrapper2.FireSendingRequest2(null); } } else if (0 < base.ChangedEntries.Count) { this.batchWriter.WriteStartChangeset(); ClientEdmModel model = ClientEdmModel.GetModel(base.RequestInfo.MaxProtocolVersion); for (int j = 0; j < base.ChangedEntries.Count; j++) { Descriptor descriptor = base.ChangedEntries[j]; if (!descriptor.ContentGeneratedForSave) { ODataRequestMessageWrapper wrapper3; EntityDescriptor entityDescriptor = descriptor as EntityDescriptor; if (descriptor.DescriptorKind == DescriptorKind.Entity) { if (entityDescriptor.State != EntityStates.Added) { if (((entityDescriptor.State == EntityStates.Unchanged) || (entityDescriptor.State == EntityStates.Modified)) && (entityDescriptor.SaveStream != null)) { throw System.Data.Services.Client.Error.NotSupported(System.Data.Services.Client.Strings.Context_BatchNotSupportedForMediaLink); } } else if (model.GetClientTypeAnnotation(model.GetOrCreateEdmType(entityDescriptor.Entity.GetType())).IsMediaLinkEntry || entityDescriptor.IsMediaLinkEntry) { throw System.Data.Services.Client.Error.NotSupported(System.Data.Services.Client.Strings.Context_BatchNotSupportedForMediaLink); } } else if (descriptor.DescriptorKind == DescriptorKind.NamedStream) { throw System.Data.Services.Client.Error.NotSupported(System.Data.Services.Client.Strings.Context_BatchNotSupportedForNamedStreams); } if (descriptor.DescriptorKind == DescriptorKind.Entity) { wrapper3 = base.CreateRequest(entityDescriptor); } else { wrapper3 = base.CreateRequest((LinkDescriptor)descriptor); } wrapper3.FireSendingRequest2(descriptor); base.CreateChangeData(j, wrapper3); } } this.batchWriter.WriteEndChangeset(); } this.batchWriter.WriteEndBatch(); this.batchWriter.Flush(); } return(requestMessage); }
internal LinkDescriptor(object source, string sourceProperty, object target, DataServiceProtocolVersion maxProtocolVersion) : this(source, sourceProperty, target, EntityStates.Unchanged) { ClientEdmModel model = ClientEdmModel.GetModel(maxProtocolVersion); this.IsSourcePropertyCollection = model.GetClientTypeAnnotation(model.GetOrCreateEdmType(source.GetType())).GetProperty(sourceProperty, false).IsEntityCollection; }
private Version ComputeVersionForPropertyCollection(IEnumerable<IEdmProperty> propertyCollection, HashSet<IEdmType> visitedComplexTypes, ClientEdmModel model) { Version version = Util.DataServiceVersion1; foreach (IEdmProperty property in propertyCollection) { ClientPropertyAnnotation clientPropertyAnnotation = model.GetClientPropertyAnnotation(property); if (clientPropertyAnnotation.IsPrimitiveOrComplexCollection || clientPropertyAnnotation.IsSpatialType) { WebUtil.RaiseVersion(ref version, Util.DataServiceVersion3); } else { if ((property.Type.TypeKind() == EdmTypeKind.Complex) && !clientPropertyAnnotation.IsDictionary) { if (visitedComplexTypes == null) { visitedComplexTypes = new HashSet<IEdmType>(EqualityComparer<IEdmType>.Default); } else if (visitedComplexTypes.Contains(property.Type.Definition)) { goto Label_00A6; } visitedComplexTypes.Add(property.Type.Definition); WebUtil.RaiseVersion(ref version, this.ComputeVersionForPropertyCollection(model.GetClientTypeAnnotation(property).EdmProperties(), visitedComplexTypes, model)); } Label_00A6:; } } return version; }
/// <summary> /// Constructor /// </summary> /// <param name="source">Source entity</param> /// <param name="sourceProperty">Navigation property on the source entity</param> /// <param name="target">Target entity</param> /// <param name="model">The client model.</param> internal LinkDescriptor(object source, string sourceProperty, object target, ClientEdmModel model) : this(source, sourceProperty, target, EntityStates.Unchanged) { this.IsSourcePropertyCollection = model.GetClientTypeAnnotation(model.GetOrCreateEdmType(source.GetType())).GetProperty(sourceProperty, false).IsEntityCollection; }