/// <summary> /// Deserializes the payload using the JsonParser, then converts the resulting clr objects into payload element form /// Throws an TaupoInvalidOperationException if the json does not evaluate successfully. /// </summary> /// <param name="serialized">A raw json payload</param> /// <param name="payloadContext">Additional payload information to aid deserialization</param> /// <returns>A PayloadElement representation of the payload</returns> public ODataPayloadElement DeserializeFromBinary(byte[] serialized, ODataPayloadContext payloadContext) { ExceptionUtilities.CheckArgumentNotNull(serialized, "serialized"); ExceptionUtilities.CheckArgumentNotNull(payloadContext, "payloadContext"); string encodingName = payloadContext.EncodingName; ODataPayloadElement errorPayload = null; if (this.payloadErrorDeserializer.TryDeserializeErrorPayload(serialized, encodingName, out errorPayload)) { return(errorPayload); } // Evaluate the given JSON text Encoding encoding = HttpUtilities.GetEncodingOrDefault(encodingName); string payload = encoding.GetString(serialized, 0, serialized.Length); JsonValue jsonData = null; using (StringReader reader = new StringReader(payload)) { JsonTokenizer tokenizer = new JsonTokenizer(reader); JsonParser parser = new JsonParser(tokenizer); jsonData = parser.ParseValue(); } // convert the deserialized JsonValue objects into payload elements return(this.payloadConverter.ConvertToPayloadElement(jsonData)); }
private TElement GetNextObservedElement <TElement>() where TElement : ODataPayloadElement { var observed = this.observedElementStack.Peek(); this.Assert.AreEqual(ODataPayloadElement.GetElementType <TElement>(), observed.ElementType, "Unexpected element type"); return((TElement)observed); }
/// <summary> /// Validator for collections of primitive and complex types. /// </summary> /// <param name="payloadElement">The payload element to validate.</param> /// <param name="testConfigLimits">The test configuration limits to modify.</param> public static void NonEntityCollectionValidator(ODataPayloadElement payloadElement, TestConfigurationLimits testConfigLimits) { ExceptionUtilities.Assert(payloadElement is PrimitiveMultiValue || payloadElement is ComplexMultiValue, "This validator only works on collection values."); // Collection values require V3. testConfigLimits.RaiseMinPayloadVersion(ODataVersion.V4); }
/// <summary> /// Normalizes a workspace or resource collection's Atom title property value so that it matches the element's title annotation. /// </summary> /// <param name="payloadElement">The payload element to normalize</param> /// <param name="titlePropertyValue">The value of the payload element's title property</param> /// <param name="setPropertyValue">Delegate for setting the payload element's title property</param> private void NormalizeTitleValue(ODataPayloadElement payloadElement, string titlePropertyValue, Action <string> setPropertyValue) { XmlTreeAnnotation titleXmlTreeAnnotation = payloadElement.Annotations .OfType <XmlTreeAnnotation>() .SingleOrDefault(a => a.LocalName.Equals(TestAtomConstants.AtomTitleElementName)); if (titlePropertyValue != null) { if (titleXmlTreeAnnotation != null) { string titleAnnotationValue = titleXmlTreeAnnotation.PropertyValue; if (titleAnnotationValue == null) { titleXmlTreeAnnotation.PropertyValue = titlePropertyValue; } else { ExceptionUtilities.Assert(titlePropertyValue == titleAnnotationValue, "Title in workspace or resource collection has different values : Property=" + titlePropertyValue + ", Annotation=" + titleAnnotationValue); } } else { payloadElement.AtomTitle(titlePropertyValue, TestAtomConstants.AtomTextConstructTextKind); } } else if (titleXmlTreeAnnotation != null) { setPropertyValue(titleXmlTreeAnnotation.PropertyValue); } }
/// <summary> /// Normalizes the given payload root /// </summary> /// <param name="rootElement">The payload to normalize</param> /// <returns>The normalized payload</returns> public override ODataPayloadElement Normalize(ODataPayloadElement rootElement) { ExceptionUtilities.CheckArgumentNotNull(rootElement, "rootElement"); // TODO: convert to correct CLR type based on metadata annotations return(rootElement); }
private void ValidateAndPrintInfoOnError(ODataUri requestUri, ODataPayloadElement rootElement, QueryValue expectedValue) { try { this.Validator.Validate(rootElement, expectedValue); } catch (DataComparisonException) { // Doing this because of unit test failures, will need to fix this later if (this.QueryDataSet != null) { this.Logger.WriteLine(LogLevel.Info, "Actual Payload Entity Graph:"); this.Logger.WriteLine(LogLevel.Info, this.ODataPayloadElementEntityGraphPrettyPrinter.PrettyPrint(rootElement)); this.Logger.WriteLine(LogLevel.Info, "Expected Query Entity Graph:"); this.Logger.WriteLine(LogLevel.Info, this.ODataQueryValueEntityGraphPrettyPrinter.PrettyPrint(expectedValue, 10)); this.Logger.WriteLine(LogLevel.Info, "Query DataSet Data"); foreach (var entitySet in requestUri.GetAllEntitySetsIncludingExpands()) { this.Logger.WriteLine(LogLevel.Info, entitySet.Name + " DataSet"); var results = this.QueryDataSet[entitySet.Name]; this.Logger.WriteLine(LogLevel.Info, this.ODataQueryValueEntityGraphPrettyPrinter.PrettyPrint(results, 1)); } } throw; } }
/// <summary> /// Remove duplicate annotations that might be added /// </summary> /// <param name="payload">payload to remove duplicate annotations for</param> public static void RemoveEPMDuplicationAnnotations(ODataPayloadElement payload) { ODataLibPayloadElementComparer comparer = new ODataLibPayloadElementComparer(); for (int i = 0; i < payload.Annotations.Count; i++) { var epmAnn1 = payload.Annotations[i] as XmlTreeAnnotation; if (epmAnn1 == null) { continue; } for (int j = i + 1; j < payload.Annotations.Count; j++) { var epmAnn2 = payload.Annotations[j] as XmlTreeAnnotation; if (epmAnn2 == null) { continue; } if (epmAnn1.LocalName == epmAnn2.LocalName && epmAnn1.NamespaceName == epmAnn2.NamespaceName) { payload.Annotations.RemoveAt(j); } } } }
/// <summary> /// Applies expected result normalizers to the specified payload element. /// </summary> /// <param name="expectedResultPayloadElement">The payload element to apply the normalizers to.</param> /// <param name="testConfiguration">The test configuration to use.</param> /// <returns>The expected result after normalization.</returns> private ODataPayloadElement ApplyExpectedResultNormalizers(ODataPayloadElement expectedResultPayloadElement, ReaderTestConfiguration testConfiguration) { // If we have some normalizers and some of them do apply to this test configuration // make a copy and apply the normalizer. if (this.ExpectedResultNormalizers != null) { ODataPayloadElement expectedResultPayloadElementCopy = null; foreach (var getNormalizerFunc in this.ExpectedResultNormalizers) { var normalizer = getNormalizerFunc(testConfiguration); if (normalizer != null) { if (expectedResultPayloadElementCopy == null) { expectedResultPayloadElementCopy = expectedResultPayloadElement.DeepCopy(); } expectedResultPayloadElementCopy = normalizer(expectedResultPayloadElementCopy); } } expectedResultPayloadElement = expectedResultPayloadElementCopy ?? expectedResultPayloadElement; } return(expectedResultPayloadElement); }
/// <summary> /// Visits the root element of the operation. /// </summary> /// <param name="operation">The operation to visit</param> protected override void VisitResponseOperation(HttpResponseData operation) { var responseOperation = operation as ODataResponse; ExceptionUtilities.CheckObjectNotNull(responseOperation, "Operation must be a response"); ODataPayloadElement rootElement = null; string contentType = null; if (responseOperation.RootElement != null) { rootElement = responseOperation.RootElement; contentType = responseOperation.GetHeaderValueIfExists(Microsoft.OData.Core.ODataConstants.ContentTypeHeader); } if (rootElement != null) { ODataFormat format = null; if (contentType.Contains(MimeTypes.ApplicationAtomXml)) { format = ODataFormat.Atom; } else if (contentType.Contains(MimeTypes.ApplicationJson)) { format = ODataFormat.Json; } new ExpectedPayloadFixups().Fixup(rootElement, format); } }
/// <summary> /// Normalizes the given payload root /// </summary> /// <param name="rootElement">The payload to normalize</param> /// <returns>The normalized payload</returns> public override ODataPayloadElement Normalize(ODataPayloadElement rootElement) { ExceptionUtilities.CheckArgumentNotNull(rootElement, "rootElement"); ExceptionUtilities.Assert(rootElement.ElementType == ODataPayloadElementType.PrimitiveValue, "Only primitive values are supported by this format. Type was: '{0}'", rootElement.ElementType); var primitiveValue = (PrimitiveValue)rootElement; // replace non-null string with deserialized instance of correct type var serialized = primitiveValue.ClrValue as string; if (serialized != null) { var dataType = primitiveValue.Annotations.OfType <DataTypeAnnotation>().Select(t => t.DataType).OfType <PrimitiveDataType>().SingleOrDefault(); if (dataType != null) { var clrType = dataType.GetFacetValue <PrimitiveClrTypeFacet, Type>(null); if (clrType != null && clrType != typeof(string)) { var converted = this.XmlPrimitiveConverter.DeserializePrimitive(serialized, clrType); primitiveValue = primitiveValue.ReplaceWith(new PrimitiveValue(primitiveValue.FullTypeName, converted)); } } } return(primitiveValue); }
private ODataUri BuildODataUri(ODataPayloadElement payload) { var entityInstance = payload as EntityInstance; if (entityInstance != null) { EntityModelTypeAnnotation type = entityInstance.GetAnnotation <EntityModelTypeAnnotation>(); ExceptionUtilities.CheckObjectNotNull(type, "Type annotation was expected"); var entityType = ((EntityDataType)type.EntityModelType).Definition; // First is OK because MEST doesnt matter var entitySet = entityType.Model.EntityContainers.SelectMany(c => c.EntitySets).First(s => s.EntityType == entityType); return(new ODataUri(ODataUriBuilder.EntitySet(entitySet))); } var complexProperty = payload as ComplexProperty; if (complexProperty != null) { EntityModelTypeAnnotation type = entityInstance.GetAnnotation <EntityModelTypeAnnotation>(); ExceptionUtilities.CheckObjectNotNull(type, "Type annotation was expected"); var entityType = ((EntityDataType)type.EntityModelType).Definition; // First is OK because MEST doesnt matter var entitySet = entityType.Model.EntityContainers.SelectMany(c => c.EntitySets).First(s => s.EntityType == entityType); return(new ODataUri(ODataUriBuilder.EntitySet(entitySet))); } // TODO: Add support for other types return(null); }
/// <summary> /// For a given payload element determines its test configuration limits. /// </summary> /// <param name="payloadElement">The payload element to check.</param> /// <param name="validators">The collection of validators to use.</param> /// <returns>The test configuration limits computed.</returns> public static TestConfigurationLimits GetTestConfigurationLimits(ODataPayloadElement payloadElement, Validators validators) { TestConfigurationLimits testConfigLimits = new TestConfigurationLimits(); new Visitor(validators, testConfigLimits).Visit(payloadElement); return(testConfigLimits); }
public ODataPayloadElement DeserializeFromBinary(byte[] serialized, ODataPayloadContext payloadContext) { ExceptionUtilities.CheckArgumentNotNull(serialized, "serialized"); ExceptionUtilities.CheckArgumentNotNull(payloadContext, "payloadContext"); string encodingName = payloadContext.EncodingName; ODataPayloadElement errorPayload = null; if (this.payloadErrorDeserializer.TryDeserializeErrorPayload(serialized, encodingName, out errorPayload)) { return(errorPayload); } var encoding = HttpUtilities.GetEncodingOrDefault(encodingName); XDocument document = null; using (StreamReader reader = new StreamReader(new MemoryStream(serialized), encoding)) { document = XDocument.Load(reader); } ExceptionUtilities.Assert(document != null, "Deserialized document cannot be null."); return(this.xmlConverter.ConvertToPayloadElement(document.Root)); }
/// <summary> /// Called to write the payload to the specified <paramref name="messageWriter"/>. /// </summary> /// <param name="messageWriter">The <see cref="ODataMessageWriterTestWrapper"/> to use for writing the payload.</param> /// <param name="testConfiguration">The test configuration to generate the payload for.</param> protected override void WritePayload(ODataMessageWriterTestWrapper messageWriter, WriterTestConfiguration testConfiguration) { ODataPayloadElement payload = this.PayloadElement.DeepCopy(); if (testConfiguration.Format == ODataFormat.Json) { payload.Accept(new ODataPayloadJsonNormalizer()); //Fixup added as odatalib requires ids on feeds even though it can't be represented in json payload.Accept(new AddFeedIDFixup()); } else if (testConfiguration.Format == ODataFormat.Atom) { // TODO: Remove visitor payload.Accept(new ODataPayloadElementNullIDVisitor()); } ODataPayloadElementToObjectModelConverter converter = new ODataPayloadElementToObjectModelConverter(!testConfiguration.IsRequest); if (this.PayloadKind != ODataPayloadKind.Batch) { this.settings.ObjectModelToMessageWriter.WriteMessage(messageWriter, this.PayloadKind, converter.Convert(payload)); } else { TestWriterUtils.WriteBatchPayload(messageWriter, payload, converter, this.settings.ObjectModelToMessageWriter, this.Model, this.settings.Assert, testConfiguration, true); } }
/// <summary> /// Normalizes the given payload root /// </summary> /// <param name="rootElement">The payload to normalize</param> /// <returns>The normalized payload</returns> public override ODataPayloadElement Normalize(ODataPayloadElement rootElement) { ExceptionUtilities.CheckArgumentNotNull(rootElement, "rootElement"); // TODO: convert to correct CLR type based on metadata annotations return rootElement; }
/// <summary> /// Returns the serialized batch payload /// </summary> /// <param name="batchPayload">batch payload</param> /// <returns>bytes representing batch payload</returns> private static byte[] SerializeBatchPayload(ODataPayloadElement batchPayload, PayloadReaderTestDescriptor.Settings settings) { string boundary = null; Byte[] bytes = null; Func <ODataPayloadElement, string> getBoundaryAnnotation = (batchPayloadElement) => { var boundaryAnn = batchPayloadElement.Annotations.OfType <BatchBoundaryAnnotation>().Single(); ExceptionUtilities.CheckObjectNotNull(boundaryAnn, "bounday annotation cannot be null"); return(boundaryAnn.BatchBoundaryInPayload); }; var batchRequestPayload = batchPayload as BatchRequestPayload; if (batchRequestPayload != null) { boundary = getBoundaryAnnotation(batchRequestPayload); bytes = settings.BatchSerializer.SerializeBatchPayload(batchRequestPayload, boundary, Encoding.UTF8.WebName); // encoding assumed to be UTF8 } else { var batchResponsePayload = batchPayload as BatchResponsePayload; boundary = getBoundaryAnnotation(batchResponsePayload); ExceptionUtilities.CheckObjectNotNull(batchResponsePayload, "the specified batch payload is neither a request payload nor a response"); bytes = settings.BatchSerializer.SerializeBatchPayload(batchResponsePayload, boundary, Encoding.UTF8.WebName); // encoding assumed to be UTF8 } return(bytes); }
/// <summary> /// Normalizes the given payload root /// </summary> /// <param name="rootElement">The payload to normalize</param> /// <returns>The normalized payload</returns> public override ODataPayloadElement Normalize(ODataPayloadElement rootElement) { ExceptionUtilities.CheckArgumentNotNull(rootElement, "rootElement"); ExceptionUtilities.Assert(rootElement.ElementType == ODataPayloadElementType.PrimitiveValue, "Only primitive values are supported by this format. Type was: '{0}'", rootElement.ElementType); var primitiveValue = (PrimitiveValue)rootElement; // replace non-null string with deserialized instance of correct type var serialized = primitiveValue.ClrValue as string; if (serialized != null) { var dataType = primitiveValue.Annotations.OfType<DataTypeAnnotation>().Select(t => t.DataType).OfType<PrimitiveDataType>().SingleOrDefault(); if (dataType != null) { var clrType = dataType.GetFacetValue<PrimitiveClrTypeFacet, Type>(null); if (clrType != null && clrType != typeof(string)) { var converted = this.XmlPrimitiveConverter.DeserializePrimitive(serialized, clrType); primitiveValue = primitiveValue.ReplaceWith(new PrimitiveValue(primitiveValue.FullTypeName, converted)); } } } return primitiveValue; }
/// <summary> /// Normalizes the specified payload element. /// </summary> /// <param name="payloadElement">The payload element to normalize.</param> /// <returns>The normalized payload element.</returns> public ODataPayloadElement Normalize(ODataPayloadElement payloadElement) { // Allways make a deep copy since we will modify all the batch parts. payloadElement = payloadElement.DeepCopy(); this.Recurse(payloadElement); return(payloadElement); }
public virtual bool TryDeserializeErrorPayload(byte[] serialized, string encodingName, out ODataPayloadElement errorPayload) { ExceptionUtilities.CheckArgumentNotNull(serialized, "serialized"); ExceptionUtilities.CheckAllRequiredDependencies(this); // get the encoding based on the given encoding name var encoding = HttpUtilities.GetEncodingOrDefault(encodingName); using (StreamReader streamReader = new StreamReader(new MemoryStream(serialized), encoding)) { using (XmlReader reader = XmlReader.Create(streamReader)) { bool foundErrorPayload = false; while (reader.Read()) { if (reader.IsStartElement(ODataConstants.ErrorElementName, ODataConstants.DataServicesMetadataNamespaceName)) { foundErrorPayload = true; break; } } if (!foundErrorPayload) { errorPayload = null; return false; } errorPayload = this.ParseErrorFragment(reader); return true; } } }
/// <summary> /// Constructs an OData request body using the given settings /// </summary> /// <param name="contentType">The content type of the body</param> /// <param name="uri">The request uri</param> /// <param name="rootElement">The root payload element</param> /// <returns>An OData request body</returns> public ODataPayloadBody BuildBody(string contentType, ODataUri uri, ODataPayloadElement rootElement) { ExceptionUtilities.CheckArgumentNotNull(contentType, "contentType"); ExceptionUtilities.CheckArgumentNotNull(rootElement, "rootElement"); ExceptionUtilities.CheckAllRequiredDependencies(this); string charset = HttpUtilities.GetContentTypeCharsetOrNull(contentType); byte[] serializedBody = null; var batchRequestPayload = rootElement as BatchRequestPayload; if (batchRequestPayload != null) { string boundary; ExceptionUtilities.Assert(HttpUtilities.TryGetContentTypeParameter(contentType, HttpHeaders.Boundary, out boundary), "Could not find boundary in content type for batch payload. Content type was: '{0}'", contentType); serializedBody = this.BatchSerializer.SerializeBatchPayload(batchRequestPayload, boundary, charset); } else { IProtocolFormatStrategy strategy = this.FormatSelector.GetStrategy(contentType, uri); ExceptionUtilities.CheckObjectNotNull(strategy, "Strategy selector did not return a strategy for content type '{0}'", contentType); IPayloadSerializer serializer = strategy.GetSerializer(); ExceptionUtilities.CheckObjectNotNull(serializer, "Strategy returned a null serializer"); serializedBody = serializer.SerializeToBinary(rootElement, charset); } return(new ODataPayloadBody(serializedBody, rootElement)); }
private void VisitProperty(PropertyInstance payloadElement, ODataPayloadElement value, Action action) { ExceptionUtilities.CheckArgumentNotNull(payloadElement, "payloadElement"); try { var currentType = this.typeStack.Peek(); ExceptionUtilities.CheckObjectNotNull(currentType, "Current type should not be null"); var propertyInfo = currentType.GetProperty(payloadElement.Name); ExceptionUtilities.CheckObjectNotNull(propertyInfo, "Could not find property '{0}' on type '{1}'", payloadElement.Name, currentType); var genericCollectionType = propertyInfo.PropertyType.GetInterfaces().Where(t => t.IsGenericType()).SingleOrDefault(t => typeof(ICollection <>) == t.GetGenericTypeDefinition()); if (genericCollectionType != null) { this.typeStack.Push(genericCollectionType.GetGenericArguments()[0]); } else { this.typeStack.Push(propertyInfo.PropertyType); } base.VisitProperty(payloadElement, value); if (action != null) { action(); } } finally { this.typeStack.Pop(); } }
private ODataUri BuildODataUri(ODataPayloadElement payload) { var entityInstance = payload as EntityInstance; if (entityInstance != null) { EntityModelTypeAnnotation type = entityInstance.GetAnnotation<EntityModelTypeAnnotation>(); ExceptionUtilities.CheckObjectNotNull(type, "Type annotation was expected"); var entityType = ((EntityDataType)type.EntityModelType).Definition; // First is OK because MEST doesnt matter var entitySet = entityType.Model.EntityContainers.SelectMany(c => c.EntitySets).First(s => s.EntityType == entityType); return new ODataUri(ODataUriBuilder.EntitySet(entitySet)); } var complexProperty = payload as ComplexProperty; if (complexProperty != null) { EntityModelTypeAnnotation type = entityInstance.GetAnnotation<EntityModelTypeAnnotation>(); ExceptionUtilities.CheckObjectNotNull(type, "Type annotation was expected"); var entityType = ((EntityDataType)type.EntityModelType).Definition; // First is OK because MEST doesnt matter var entitySet = entityType.Model.EntityContainers.SelectMany(c => c.EntitySets).First(s => s.EntityType == entityType); return new ODataUri(ODataUriBuilder.EntitySet(entitySet)); } // TODO: Add support for other types return null; }
/// <summary> /// Annotates the given payload based on the metadata in the given uri /// </summary> /// <param name="rootElement">The payload to annotate with metadata information</param> /// <param name="uri">The uri that corresponds to the given payload</param> public void ResolveMetadata(ODataPayloadElement rootElement, ODataUri uri) { ExceptionUtilities.CheckArgumentNotNull(rootElement, "rootElement"); ExceptionUtilities.CheckArgumentNotNull(uri, "uri"); this.InitializeMetadataStack(uri); this.InitialStackSize = this.MetadataStack.Count; rootElement.Add(new ExpectedPayloadElementTypeAnnotation() { ExpectedType = uri.GetExpectedPayloadType() }); // if the uri did not contain any metadata, do nothing if (this.InitialStackSize > 0) { // if this is the result of service operation or action, the root element needs to have the function itself and its return type var serviceOperation = this.MetadataStack.OfType <Function>().FirstOrDefault(); if (serviceOperation != null) { rootElement.AddAnnotationIfNotExist(new FunctionAnnotation() { Function = serviceOperation }); rootElement.AddAnnotationIfNotExist(new DataTypeAnnotation() { DataType = serviceOperation.ReturnType }); } this.Recurse(rootElement); } }
/// <summary> /// Compares the two payload elements /// </summary> /// <param name="expected">The expected element</param> /// <param name="actual">The actual element</param> public void Compare(ODataPayloadElement expected, ODataPayloadElement actual) { var comparingVisitor = new PayloadComparingVisitor(this.BatchComparer, this.ignoreOrder, this.expectMetadataToBeComputedByConvention); comparingVisitor.Assert = this.Assert; comparingVisitor.Compare(expected, actual); }
/// <summary> /// Called to get the expected result of the test. /// </summary> /// <param name="testConfiguration">The test configuration to use.</param> /// <returns>The expected result.</returns> protected override ReaderTestExpectedResult GetExpectedResult(ReaderTestConfiguration testConfiguration) { ReaderTestExpectedResult expectedResult = base.GetExpectedResult(testConfiguration); if (expectedResult == null) { IEdmModel model = this.GetMetadataProvider(testConfiguration); ReaderMetadata readerMetadata = new ReaderMetadata(model, this.PayloadElement); // First use the input payload as the expected result. ODataPayloadElement expectedResultPayloadElement = this.PayloadElement; // If we have an override specifically for expected result, use that instead. if (this.ExpectedResultPayloadElement != null) { expectedResultPayloadElement = this.ExpectedResultPayloadElement(testConfiguration); } if (expectedResultPayloadElement.ElementType == ODataPayloadElementType.BatchRequestPayload || expectedResultPayloadElement.ElementType == ODataPayloadElementType.BatchResponsePayload) { if (this.ExpectedResultNormalizers.Count > 0) { expectedResultPayloadElement = new BatchPayloadExpectedResultNormalizer( testConfiguration, this.ApplyExpectedResultNormalizers).Normalize(expectedResultPayloadElement); } IEdmModel payloadModel = this.GetMetadataProvider(testConfiguration); return(new BatchReaderTestExpectedResult(this.settings.BatchExpectedResultSettings) { ExpectedBatchPayload = expectedResultPayloadElement, PayloadModel = payloadModel, ExpectedException = this.ExpectedException, }); } else { expectedResultPayloadElement = this.ApplyExpectedResultNormalizers(expectedResultPayloadElement, testConfiguration); } return(new PayloadReaderTestExpectedResult(this.settings.ExpectedResultSettings) { ExpectedPayloadElement = expectedResultPayloadElement, ExpectedException = this.ExpectedException, ReaderMetadata = readerMetadata, IgnorePropertyOrder = this.IgnorePropertyOrder, }); } else { PayloadReaderTestExpectedResult payloadReaderTestExpectedResult = expectedResult as PayloadReaderTestExpectedResult; if (payloadReaderTestExpectedResult != null && payloadReaderTestExpectedResult.ReaderMetadata == null) { IEdmModel model = this.GetMetadataProvider(testConfiguration); payloadReaderTestExpectedResult.ReaderMetadata = new ReaderMetadata(model, this.PayloadElement); } return(expectedResult); } }
private ODataPayloadElement ConvertRootObject(JsonObject jsonObject) { JsonValue toConvert; if (!this.TryGetSecurityPropertyValue(jsonObject, out toConvert)) { toConvert = jsonObject; } else if (toConvert.JsonType == JsonValueType.JsonObject) { // If toConvert is a json object it means it has already been unwrapped of the d: wrapper. // This is done to update the jsonObject to be the unwrapped version of the payload. jsonObject = (JsonObject)toConvert; } ODataPayloadElement converted = this.ConvertValue(toConvert); // an untyped root-level complex instance with one property should be 'unwrapped' if (converted.ElementType == ODataPayloadElementType.ComplexInstance) { var complex = (ComplexInstance)converted; // if there are multiple properties or any type information/metadata, do not unwrap it if (complex.Properties.Count() == 1 && jsonObject.Properties.Count() == 1) { converted = complex.Properties.Single(); } } return(converted); }
protected override void VisitRequestOperation(IHttpRequest operation) { var requestOperation = operation as ODataRequest; ExceptionUtilities.CheckObjectNotNull(requestOperation, "Operation must be request"); ODataPayloadElement rootElement = null; string contentType = null; if (requestOperation.Body != null && requestOperation.Body.RootElement != null) { rootElement = requestOperation.Body.RootElement; contentType = requestOperation.GetHeaderValueIfExists(Microsoft.OData.ODataConstants.ContentTypeHeader); } if (rootElement != null) { ODataFormat format = null; if (contentType.Contains(MimeTypes.ApplicationJson)) { format = ODataFormat.Json; } new ExpectedPayloadFixups().Fixup(rootElement, format); } }
/// <summary> /// Called to write the payload to the specified <paramref name="messageWriter"/>. /// </summary> /// <param name="messageWriter">The <see cref="ODataMessageWriterTestWrapper"/> to use for writing the payload.</param> /// <param name="testConfiguration">The test configuration to generate the payload for.</param> protected override void WritePayload(ODataMessageWriterTestWrapper messageWriter, WriterTestConfiguration testConfiguration) { Debug.Assert(this.messageStream != null, "Streaming test stream must have been created."); TestMessage testMessage = this.CreateInputMessageFromStream((TestStream)this.messageStream, testConfiguration, this.PayloadKind, string.Empty, this.UrlResolver); testMessage.SetContentType(testConfiguration.Format, this.PayloadKind); Exception exception = TestExceptionUtils.RunCatching(() => { ODataMessageReaderSettings readerSettings = this.settings.MessageReaderSettings.Clone(); readerSettings.EnableMessageStreamDisposal = testConfiguration.MessageWriterSettings.EnableMessageStreamDisposal; ReaderTestConfiguration readerConfig = new ReaderTestConfiguration( testConfiguration.Format, readerSettings, testConfiguration.IsRequest, testConfiguration.Synchronous); IEdmModel model = this.GetMetadataProvider(); using (ODataMessageReaderTestWrapper messageReaderWrapper = TestReaderUtils.CreateMessageReader(testMessage, model, readerConfig)) { ODataPayloadElementToObjectModelConverter payloadElementToOMConverter = new ODataPayloadElementToObjectModelConverter(!testConfiguration.IsRequest); ObjectModelToPayloadElementConverter reverseConverter = new ObjectModelToPayloadElementConverter(); ObjectModelWriteReadStreamer streamer = new ObjectModelWriteReadStreamer(); this.readObject = reverseConverter.Convert(streamer.WriteMessage(messageWriter, messageReaderWrapper, this.PayloadKind, payloadElementToOMConverter.Convert(this.PayloadElement)), !testConfiguration.IsRequest); } }); }
private static QueryValue CreateQueryScalarValue(ODataPayloadElement payload, QueryType queryTypeToBuild) { var primitiveValue = payload as PrimitiveValue; var queryScalarType = queryTypeToBuild as QueryScalarType; ExceptionUtilities.CheckObjectNotNull(queryScalarType, "payload is a primitive type so queryType must be as well"); return queryScalarType.CreateValue(primitiveValue.ClrValue); }
/// <summary> /// Wrapper for recursively visiting the given element. Used with the callback property to make unit tests easier. /// </summary> /// <param name="element">The element to visit</param> protected override void Recurse(ODataPayloadElement element) { // only recurse if we haven't yet found an error if (this.expectedError == null) { base.Recurse(element); } }
/// <summary> /// Returns the type from the entity model type annotation for this payload element. /// </summary> /// <param name="payloadElement">The payload element to return the type for.</param> /// <returns>The type from the annotation or null if none was present.</returns> private static IEdmTypeReference GetEdmTypeFromEntityModelTypeAnnotation(ODataPayloadElement payloadElement) { Debug.Assert(payloadElement != null, "payloadElement != null"); EntityModelTypeAnnotation typeAnnotation = payloadElement.GetAnnotation <EntityModelTypeAnnotation>(); return(typeAnnotation == null ? null : typeAnnotation.EdmModelType); }
/// <summary> /// Helper method for visiting properties /// </summary> /// <param name="payloadElement">The property to visit</param> /// <param name="value">The value of the property</param> protected override void VisitProperty(PropertyInstance payloadElement, ODataPayloadElement value) { using (new DelegateBasedDisposable(() => this.currentPath.Pop())) { this.currentPath.Push(payloadElement.Name); base.VisitProperty(payloadElement, value); } }
/// <summary> /// Helper method for visiting properties /// </summary> /// <param name="payloadElement">The property to visit</param> /// <param name="value">The value of the property</param> protected override void VisitProperty(PropertyInstance payloadElement, ODataPayloadElement value) { ExceptionUtilities.CheckArgumentNotNull(payloadElement, "payloadElement"); var property = this.MetadataStack.Peek() as MemberProperty; if (property != null) { ExceptionUtilities.Assert(payloadElement.Name == property.Name, "Property name mismatch"); payloadElement.AddAnnotationIfNotExist(new MemberPropertyAnnotation() { Property = property }); try { this.MetadataStack.Push(property.PropertyType); base.VisitProperty(payloadElement, value); } finally { this.MetadataStack.Pop(); } } else { var navprop = this.MetadataStack.Peek() as NavigationProperty; if (navprop != null) { ExceptionUtilities.Assert(payloadElement.Name == navprop.Name, "Property name mismatch"); try { this.MetadataStack.Push(this.CurrentEntitySet.GetRelatedEntitySet(navprop)); base.VisitProperty(payloadElement, value); } finally { this.MetadataStack.Pop(); } } else { var serviceOperation = this.MetadataStack.OfType <Function>().SingleOrDefault(f => f.Name.Equals(payloadElement.Name, StringComparison.Ordinal)); if (payloadElement.Name.Contains('.')) { // if the action has a name collision with a property in the entity, it will have the <container name>.<action name> in the payload // split the payloadElement.Name and get the last token which will match the function name string lastToken = payloadElement.Name.Split('.').Last(); serviceOperation = this.MetadataStack.OfType <Function>().SingleOrDefault(f => f.Name.Equals(lastToken, StringComparison.Ordinal)); } ExceptionUtilities.CheckObjectNotNull(serviceOperation, "Expected property, got " + this.MetadataStack.Peek().ToString()); // Non-entity values returned from a service operation call appear identical to member properties, // with the operation name as the property name base.VisitProperty(payloadElement, value); } } }
/// <summary> /// Serializes the given root element to a binary representation /// </summary> /// <param name="rootElement">The root element, must be a primitive value</param> /// <param name="encodingName">Optional name of an encoding to use if it is relevant to the current format. May be null if no character-set information was known.</param> /// <returns>The serialized value</returns> public override byte[] SerializeToBinary(ODataPayloadElement rootElement, string encodingName) { ExceptionUtilities.CheckArgumentNotNull(rootElement, "rootElement"); ExceptionUtilities.Assert(rootElement.ElementType == ODataPayloadElementType.PrimitiveValue, "Only primitive values can be serialized as raw values. Type was: {0}", rootElement.ElementType); var value = (rootElement as PrimitiveValue).ClrValue; var encoding = HttpUtilities.GetEncodingOrDefault(encodingName); return encoding.GetBytes(this.XmlPrimitiveConverter.SerializePrimitive(value)); }
/// <summary> /// Visit the collection payload element and updates the collection name to an empty string (if it is present). /// </summary> /// <param name="payloadElement">The root of the payload element tree to visit.</param> /// <remarks>This method will modify the input payload element, so if there is a need to /// preserve the actual input payload element it should be cloned. /// </remarks> public static ODataPayloadElement Visit(ODataPayloadElement payloadElement) { if (payloadElement != null) { new RemoveCollectionNameAnnotationForCollectionPayloadElementVisitor().Recurse(payloadElement); } return payloadElement; }
/// <summary> /// Visit the payload element and removes UriString value from ExpandedLinks. /// </summary> /// <param name="payloadElement">The root of the payload element tree to visit.</param> /// <remarks>This method will modify the input payload element, so if there is a need to /// preserve the actual input payload element it should be cloned. /// </remarks> public static ODataPayloadElement Visit(ODataPayloadElement payloadElement) { if (payloadElement != null) { new RemoveExpandedLinkUriStringVisitor().Recurse(payloadElement); } return payloadElement; }
private void RunMessageSizeLimitTests( IEnumerable <ReaderTestConfiguration> testConfigurations, EdmModel model, ODataPayloadElement payload, MessageSizeLimitTestCase[] testCases, Func <ReaderTestConfiguration, bool> skipTestConfigurationFunc = null) { var transformScope = this.Settings.PayloadTransformFactory.EmptyScope(); using (transformScope.Apply()) { this.CombinatorialEngineProvider.RunCombinations( testCases, testConfigurations, (testCase, testConfiguration) => { int size = -1; if (testConfiguration.Format == ODataFormat.Atom && testCase.AtomSizes != null) { size = testConfiguration.IsRequest ? testCase.AtomSizes.RequestSize : testCase.AtomSizes.ResponseSize; } else if (testConfiguration.Format == ODataFormat.Json && testCase.JsonLightSizes != null) { size = testConfiguration.IsRequest ? testCase.JsonLightSizes.RequestSize : testCase.JsonLightSizes.ResponseSize; } else if (testCase.RawSizes != null) { size = testConfiguration.IsRequest ? testCase.RawSizes.RequestSize : testCase.RawSizes.ResponseSize; } int maxSize = testCase.MaxMessageSize >= 0 ? testCase.MaxMessageSize : 1024 * 1024; ExpectedException expectedException = size < 0 ? null : ODataExpectedExceptions.ODataException("MessageStreamWrappingStream_ByteLimitExceeded", size.ToString(), maxSize.ToString()); var testDescriptor = new PayloadReaderTestDescriptor(this.Settings) { PayloadEdmModel = model, PayloadElement = payload.DeepCopy(), ExpectedException = expectedException, SkipTestConfiguration = skipTestConfigurationFunc, ApplyPayloadTransformations = false, }; testDescriptor.ExpectedResultNormalizers.Add( tc => (Func <ODataPayloadElement, ODataPayloadElement>)null); if (testCase.MaxMessageSize > 0) { testConfiguration = new ReaderTestConfiguration(testConfiguration); testConfiguration.MessageReaderSettings.MessageQuotas.MaxReceivedMessageSize = testCase.MaxMessageSize; } testDescriptor.RunTest(testConfiguration); }); } }
/// <summary> /// Visit the collection payload element and updates the collection name to an empty string (if it is present). /// </summary> /// <param name="payloadElement">The root of the payload element tree to visit.</param> /// <remarks>This method will modify the input payload element, so if there is a need to /// preserve the actual input payload element it should be cloned. /// </remarks> public static ODataPayloadElement Visit(ODataPayloadElement payloadElement) { if (payloadElement != null) { new EmptyCollectionNameForCollectionPayloadElementVisitor().Recurse(payloadElement); } return(payloadElement); }
/// <summary> /// Prints an entity graph /// </summary> /// <param name="rootElement">The root element of the payload</param> /// <returns> an entity graph to visualize</returns> public string PrettyPrint(ODataPayloadElement rootElement) { ExceptionUtilities.CheckArgumentNotNull(rootElement, "rootElement"); ExceptionUtilities.CheckAllRequiredDependencies(this); this.builder = new StringBuilder(); this.currentDepth = 0; this.Recurse(rootElement); return this.builder.ToString(); }
/// <summary> /// Validates a payload with the given root element against the given expected value /// </summary> /// <param name="rootElement">The root element of the payload</param> /// <param name="expectedValue">The expected value</param> public void Validate(ODataPayloadElement rootElement, QueryValue expectedValue) { ExceptionUtilities.CheckArgumentNotNull(rootElement, "rootElement"); ExceptionUtilities.CheckArgumentNotNull(expectedValue, "expectedValue"); ExceptionUtilities.CheckAllRequiredDependencies(this); this.Assert.IsNull(expectedValue.EvaluationError, string.Format(CultureInfo.InvariantCulture, "Query evaluation error: {0}", expectedValue.EvaluationError)); var visitor = new PayloadDataValidatingVisitor(this); visitor.Validate(rootElement, expectedValue); }
/// <summary> /// Annotates payload with version as appropriate. /// </summary> /// <param name="payloadElement">The root of the payload to annotate.</param> /// <param name="version">The format version to annotate with.</param> /// <param name="requestPayload">true if the payload should represent a request payload, false if it's a response payload.</param> public static void AnnotateVerboseJson(ODataPayloadElement payloadElement, DataServiceProtocolVersion version, bool requestPayload) { PayloadFormatVersionAnnotatingVisitor visitor = new PayloadFormatVersionAnnotatingVisitor(version, requestPayload); visitor.Recurse(payloadElement); // Add the version/response annotation to the root if it's a response. if (!requestPayload && !(payloadElement is ODataErrorPayload)) { payloadElement.SetAnnotation(new PayloadFormatVersionAnnotation() { Version = version, Response = true, ResponseWrapper = true }); } }
/// <summary> /// Converts the given payload element into an Json representation. /// </summary> /// <param name="rootElement">The root payload element to convert.</param> /// <returns>The Json representation of the payload.</returns> public string ConvertToJson(ODataPayloadElement rootElement) { StringBuilder builder = new StringBuilder(); using (StringWriter strWriter = new StringWriter(builder, CultureInfo.CurrentCulture)) { this.writer = new JsonWriter(strWriter); this.Serialize(rootElement); this.Dispose(); } return builder.ToString(); }
public byte[] SerializeToBinary(ODataPayloadElement rootElement, string encodingName) { string json = this.payloadElementToStringConverter(rootElement); var encoding = HttpUtilities.GetEncodingOrDefault(encodingName); using (var writer = new StreamWriter(new MemoryStream(), encoding)) { writer.Write(json); writer.Flush(); return ((MemoryStream)writer.BaseStream).ToArray(); } }
/// <summary> /// Write the <paramref name="element"/> payload element to the <paramref name="writer"/> OData writer. /// </summary> /// <param name="writer">The OData writer to write to.</param> /// <param name="element">The element to write.</param> public void WritePayload(ODataWriter writer, ODataPayloadElement element) { this.writer = writer; try { base.Recurse(element); this.writer.Flush(); } finally { this.writer = null; } }
/// <summary> /// The base for recursing a property to write a property using ODataMessageWriter /// </summary> /// <param name="writer">The message writer to use for writing the property</param> /// <param name="payload">The payload to be written as a property</param> public void WriteProperty(ODataMessageWriter writer, ODataPayloadElement payload) { this.writer = writer; payload.Accept(this); ExceptionUtilities.CheckObjectNotNull(this.odataProperties, "ODataProperty cannot be null"); ExceptionUtilities.Assert(this.odataProperties.Count == 1, "There can be only one property left when writing the result"); #if SILVERLIGHT this.writer.WriteProperty(this.odataProperties.First()); #else this.writer.WritePropertyAsync(this.odataProperties.First()).Wait(); #endif this.odataProperties.Clear(); }
private string AtomFixup(ODataPayloadElement payload) { // We have removed all the annotations except for Self Link which also we can remove since it shows up as ID and // convert primitives to expected JSON representations // TODO: Remove visitor payload.Accept(new ODataPayloadElementNullIDVisitor()); payload.Accept(new AddExpandedLinkMetadata()); payload.Accept(new ODataPayloadElementAddDefaultAtomMetadata()); payload.Accept(new ODataPayloadElementNullTypenameVisitor()); payload.Accept(new NullStringTypenameFixup()); payload.Accept(new RemoveAnnotations()); return MimeTypes.ApplicationAtomXml; }
/// <summary> /// Calculates the Protocol Version based on the payloadElement provided /// </summary> /// <param name="payloadElement">Payload Element</param> /// <param name="contentType">Content Type</param> /// <param name="maxProtocolVersion">The max protocol version</param> /// <param name="maxDataServiceVersion">The max data service version of the request</param> /// <returns>Data Service protocol version</returns> public DataServiceProtocolVersion CalculateProtocolVersion(ODataPayloadElement payloadElement, string contentType, DataServiceProtocolVersion maxProtocolVersion, DataServiceProtocolVersion maxDataServiceVersion) { ExceptionUtilities.CheckArgumentNotNull(payloadElement, "payloadElement"); ExceptionUtilities.CheckArgumentNotNull(contentType, "contentType"); ExceptionUtilities.Assert(maxProtocolVersion != DataServiceProtocolVersion.Unspecified, "Max protocol version cannot be unspecified"); this.responseContentType = contentType; this.version = DataServiceProtocolVersion.V4; this.currentMaxProtocolVersion = maxProtocolVersion; this.currentMaxDataServiceVersion = maxDataServiceVersion; payloadElement.Accept(this); return this.version; }
private string JsonFixup(ODataPayloadElement payload) { // We have removed all the annotations except for Self Link which also we can remove since it shows up as ID and // convert primitives to expected JSON representations payload.Accept(new ODataPayloadJsonNormalizer()); payload.Accept(new RemoveFeedIDFixup()); payload.Accept(new ReorderProperties()); payload.Accept(new ODataPayloadElementNullTypenameVisitor()); payload.Accept(new RemoveMLEAnnotation()); payload.Accept(new RemoveAnnotations()); payload.Accept(new JsonSelfLinkToEditLinkFixup()); payload.Accept(new RemoveExpandedLinkUriStringVisitor()); return MimeTypes.ApplicationJson; }
/// <summary> /// Converts the given payload into a series of named value pairs /// </summary> /// <param name="payload">The payload to convert</param> /// <returns>The named-value pairs represented by the given payload</returns> public IEnumerable<NamedValue> ConvertToNamedValues(ODataPayloadElement payload) { ExceptionUtilities.CheckArgumentNotNull(payload, "payload"); ExceptionUtilities.Assert(this.currentPath.Count == 0, "Stack was not empty"); ExceptionUtilities.CheckAllRequiredDependencies(this); this.orderedNames.Clear(); this.valuesByName.Clear(); this.Recurse(payload); ExceptionUtilities.Assert(this.orderedNames.Count == this.valuesByName.Count, "Number of names does not match number of values"); return this.orderedNames.Select(n => this.valuesByName[n]); }
/// <summary> /// Fixes up payload based on format /// </summary> /// <param name="payloadElement">The payload element to fix.</param> /// <param name="format">The format to fix up for.</param> public string Fixup(ODataPayloadElement payload, ODataFormat format) { if (format == ODataFormat.Json) { return this.JsonFixup(payload); } else if (format == ODataFormat.Atom) { return this.AtomFixup(payload); } else if (format == null && (payload is BatchRequestPayload || payload is BatchResponsePayload)) { return this.DefaultFixup(payload); } return MimeTypes.ApplicationXml; }
/// <summary> /// Serializes the given root element to a binary representation /// </summary> /// <param name="rootElement">The root element, must be a primitive value with either a null or binary value</param> /// <param name="encodingName">Optional name of an encoding to use if it is relevant to the current format. May be null if no character-set information was known.</param> /// <returns>The serialized value</returns> public override byte[] SerializeToBinary(ODataPayloadElement rootElement, string encodingName) { ExceptionUtilities.CheckArgumentNotNull(rootElement, "rootElement"); ExceptionUtilities.Assert(rootElement.ElementType == ODataPayloadElementType.PrimitiveValue, "Only primitive values can be serialized as raw values. Type was: {0}", rootElement.ElementType); var value = (rootElement as PrimitiveValue).ClrValue; if (value == null) { return new byte[0]; } var binary = value as byte[]; ExceptionUtilities.CheckObjectNotNull(binary, "Payload element was not a binary value"); return binary; }
/// <summary> /// Serializes the given root element to a binary representation /// </summary> /// <param name="rootElement">The root element</param> /// <param name="encodingName">Optional name of an encoding to use if it is relevant to the current format</param> /// <returns>The serialized value</returns> public override byte[] SerializeToBinary(ODataPayloadElement rootElement, string encodingName) { ExceptionUtilities.CheckArgumentNotNull(rootElement, "rootElement"); ExceptionUtilities.Assert(rootElement.ElementType == ODataPayloadElementType.ComplexInstance, "Only complex instances form values can be serialized as html forms. Type was: {0}", rootElement.ElementType); var complexInstance = (ComplexInstance)rootElement; var queryOpions = new List<KeyValuePair<string, string>>(); foreach (var property in complexInstance.Properties) { string value; if (property.ElementType == ODataPayloadElementType.PrimitiveProperty) { value = this.LiteralConverter.SerializePrimitive(((PrimitiveProperty)property).Value.ClrValue); } else if (property.ElementType == ODataPayloadElementType.ComplexProperty) { value = this.JsonConverter.ConvertToJson(((ComplexProperty)property).Value); } else if (property.ElementType == ODataPayloadElementType.PrimitiveMultiValueProperty) { value = this.JsonConverter.ConvertToJson(((PrimitiveMultiValueProperty)property).Value); } else { ExceptionUtilities.Assert(property.ElementType == ODataPayloadElementType.ComplexMultiValueProperty, "Only primitive, complex, and multi-value properties are supported"); value = this.JsonConverter.ConvertToJson(((ComplexMultiValueProperty)property).Value); } var option = new KeyValuePair<string, string>(property.Name, value); queryOpions.Add(option); } StringBuilder builder = new StringBuilder(); UriHelpers.ConcatenateQueryOptions(builder, queryOpions); var encoding = HttpUtilities.GetEncodingOrDefault(encodingName); return encoding.GetBytes(builder.ToString()); }
/// <summary> /// Deserializes the given html payload a error payload or returns null /// </summary> /// <param name="serialized">The payload that was sent over HTTP</param> /// <param name="encodingName">Optional name of an encoding to use if it is relevant to the current format. May be null if no character-set information was known.</param> /// <param name="errorPayload">Error payload that is found</param> /// <returns>True if it finds and error, false if not</returns> public bool TryDeserializeErrorPayload(byte[] serialized, string encodingName, out ODataPayloadElement errorPayload) { Encoding encoding = HttpUtilities.GetEncodingOrDefault(encodingName); string payload = encoding.GetString(serialized, 0, serialized.Length); errorPayload = null; // <html> // <body> // <div id="content"> // <p class="heading1">Request Error</p> // <p>Error message goes here</p> // <p>Stack trace goes here</p> // </div> // <body> // </html> // The server encountered an error processing the request. The exception message is ' // trim the html to only contain the <body> </body> section of the HTML. if (payload.Contains("<html")) { errorPayload = new HtmlErrorPayload(); var htmlPayload = errorPayload as HtmlErrorPayload; payload = payload.Substring(payload.IndexOf("<body>", StringComparison.OrdinalIgnoreCase)).Replace("</html>", string.Empty); payload = payload.Replace("The server encountered an error processing the request. The exception message is '", string.Empty); payload = payload.Replace("'. See server logs for more details. The exception stack trace is: ", string.Empty); XDocument errorDocument = XDocument.Parse(payload); XElement body = errorDocument.Element(XName.Get("body")); XElement errorContent = body.Element(XName.Get("div")); XElement errorMessage = errorContent.Elements(XName.Get("p")).Skip(1).First(); XElement stackTrace = errorContent.Elements(XName.Get("p")).Skip(2).First(); htmlPayload.Message = errorMessage.Value; htmlPayload.StackTrace = stackTrace.Value; return true; } return false; }
public byte[] SerializeToBinary(ODataPayloadElement rootElement, string encodingName) { bool omitDeclaration = false; SerializationEncodingNameAnnotation encodingNameAnnotation = (SerializationEncodingNameAnnotation)rootElement.GetAnnotation(typeof(SerializationEncodingNameAnnotation)); if (encodingNameAnnotation != null) { encodingName = encodingNameAnnotation.EncodingName; omitDeclaration = encodingNameAnnotation.OmitDeclaration; } var encoding = HttpUtilities.GetEncodingOrDefault(encodingName); XDocument document = new XDocument(this.payloadElementConverter.ConvertToXml(rootElement)); if (!omitDeclaration) { document.Declaration = new XDeclaration("1.0", encoding.WebName, "yes"); } // settings taken from server XmlWriterSettings settings = new XmlWriterSettings(); settings.Encoding = encoding; settings.OmitXmlDeclaration = omitDeclaration; settings.Indent = true; settings.NewLineHandling = NewLineHandling.Entitize; settings.NamespaceHandling = NamespaceHandling.OmitDuplicates; using (MemoryStream stream = new MemoryStream()) { using (XmlWriter writer = XmlWriter.Create(stream, settings)) { document.Save(writer); writer.Flush(); return stream.ToArray(); } } }
/// <summary> /// Annotates the given payload based on the metadata in the given uri /// </summary> /// <param name="rootElement">The payload to annotate with metadata information</param> /// <param name="uri">The uri that corresponds to the given payload</param> public void ResolveMetadata(ODataPayloadElement rootElement, ODataUri uri) { ExceptionUtilities.CheckArgumentNotNull(rootElement, "rootElement"); ExceptionUtilities.CheckArgumentNotNull(uri, "uri"); this.InitializeMetadataStack(uri); this.InitialStackSize = this.MetadataStack.Count; rootElement.Add(new ExpectedPayloadElementTypeAnnotation() { ExpectedType = uri.GetExpectedPayloadType() }); // if the uri did not contain any metadata, do nothing if (this.InitialStackSize > 0) { // if this is the result of service operation or action, the root element needs to have the function itself and its return type var serviceOperation = this.MetadataStack.OfType<Function>().FirstOrDefault(); if (serviceOperation != null) { rootElement.AddAnnotationIfNotExist(new FunctionAnnotation() { Function = serviceOperation }); rootElement.AddAnnotationIfNotExist(new DataTypeAnnotation() { DataType = serviceOperation.ReturnType }); } this.Recurse(rootElement); } }
/// <summary> /// Converts the given payload into a series of named value pairs /// </summary> /// <param name="element">The payload to convert</param> /// <param name="queryTypeToBuild">Query Type to build</param> /// <returns>The queryValue that represents the ODataPayload</returns> public QueryValue Convert(ODataPayloadElement element, QueryType queryTypeToBuild) { var typedValue = element as ITypedValue; if (typedValue != null && typedValue.IsNull) { return queryTypeToBuild.NullValue; } var queryCollectionType = queryTypeToBuild as QueryCollectionType; // return empty QueryCollectionValue for all types of empty collections PrimitiveCollection primitiveCollection = element as PrimitiveCollection; ComplexInstanceCollection complexInstanceCollection = element as ComplexInstanceCollection; PrimitiveMultiValue primitiveMultiValue = element as PrimitiveMultiValue; ComplexMultiValue complexMultiValue = element as ComplexMultiValue; if ((primitiveCollection != null && primitiveCollection.Count == 0) || (complexInstanceCollection != null && complexInstanceCollection.Count == 0) || (primitiveMultiValue != null && primitiveMultiValue.Count == 0) || (complexMultiValue != null && complexMultiValue.Count == 0)) { return queryCollectionType.CreateCollectionWithValues(new QueryValue[] { }); } if (element.ElementType == ODataPayloadElementType.PrimitiveValue) { return CreateQueryScalarValue(element, queryTypeToBuild); } else if (queryCollectionType != null && element.ElementType == ODataPayloadElementType.PrimitiveMultiValue) { return queryCollectionType.CreateCollectionWithValues(primitiveMultiValue.Select(p => CreateQueryScalarValue(p, queryCollectionType.ElementType))); } var namedValues = this.PayloadElementToNamedValuesConverter.ConvertToNamedValues(element); return this.NamedValueToQueryValueConverter.Convert(namedValues, queryTypeToBuild); }
/// <summary> /// Normalizes the payload for WCF DS Server mode. /// </summary> /// <param name="payloadElement">The payload element to normalize.</param> /// <param name="format">The format ot use.</param> /// <returns>The normalized payload element.</returns> public static ODataPayloadElement Normalize(ODataFormat format, EdmModel payloadEdmModel, ODataPayloadElement payloadElement) { new WcfDsServerPayloadElementNormalizer(format, payloadEdmModel).Recurse(payloadElement); return payloadElement; }
/// <summary> /// Visit the payload element and replace null error messages. /// </summary> /// <param name="payloadElement">The root of the payload element tree to visit.</param> /// <returns>The <paramref name="payloadElement"/> after it has been visited.</returns> public static ODataPayloadElement Visit(ODataPayloadElement payloadElement) { new ErrorMessageNormalizer().Recurse(payloadElement); return payloadElement; }
private static ODataPayloadElement ConvertToStringPayloadElement(ODataPayloadElement binaryPayload) { Debug.Assert(binaryPayload != null && binaryPayload.ElementType == ODataPayloadElementType.PrimitiveValue, "Expected non-null, primitive value as payload"); PrimitiveValue primitiveValue = (PrimitiveValue)binaryPayload; Debug.Assert(primitiveValue.ClrValue.GetType() == typeof(byte[]), "Only expect byte[] primitive values."); byte[] bytes = (byte[])primitiveValue.ClrValue; return PayloadBuilder.PrimitiveValue(System.Text.Encoding.UTF8.GetString(bytes, 0, bytes.Length)); }