/// <summary> /// Initializes a new dummy host for the batch request. /// This host represents a single operation in the batch. /// </summary> /// <param name="absoluteServiceUri">Absolute Uri to the service.</param> /// <param name="operationMessage">The request message representing a batch operation to wrap.</param> /// <param name="contentId">Content id for the given operation host.</param> /// <param name="writer">ODataBatchWriter instance.</param> /// <param name="odataMaxVersion">OData-MaxVersion header on the batch request. If the OData-MaxVersion header is not specified in the current operation, we default to the MaxDSV from the batch level.</param> internal BatchServiceHost(Uri absoluteServiceUri, IODataRequestMessage operationMessage, string contentId, ODataBatchWriter writer, Version odataMaxVersion) : this(writer) { Debug.Assert(absoluteServiceUri != null && absoluteServiceUri.IsAbsoluteUri, "absoluteServiceUri != null && absoluteServiceUri.IsAbsoluteUri"); Debug.Assert(operationMessage != null, "operationMessage != null"); this.absoluteServiceUri = absoluteServiceUri; this.absoluteRequestUri = RequestUriProcessor.GetAbsoluteUriFromReference(operationMessage.Url, absoluteServiceUri); this.requestHttpMethod = operationMessage.Method; this.contentId = contentId; foreach (KeyValuePair<string, string> header in operationMessage.Headers) { this.requestHeaders.Add(header.Key, header.Value); } // If the MaxDSV header is not specified in the current operation, we default to the MaxDSV from the batch level. if (string.IsNullOrEmpty(this.requestHeaders[XmlConstants.HttpODataMaxVersion])) { Debug.Assert(odataMaxVersion != null, "odataMaxVersion != null"); this.requestHeaders[XmlConstants.HttpODataMaxVersion] = odataMaxVersion.ToString(); } this.requestStream = operationMessage.GetStream(); }
/// <summary> /// Constructs an internal wrapper around the <paramref name="requestMessage"/> /// that isolates the internal implementation of the ODataLib from the interface. /// </summary> /// <param name="requestMessage">The request message to wrap.</param> internal ODataRequestMessage(IODataRequestMessage requestMessage) { DebugUtils.CheckNoExternalCallers(); Debug.Assert(requestMessage != null, "requestMessage != null"); this.requestMessage = requestMessage; }
private void ProcessUpdateEntityReference(IODataRequestMessage requestMessage, IODataResponseMessage responseMessage, ODataPath odataPath) { // This is for change the reference in single-valued navigation property // PUT ~/Person(0)/Parent/$ref // { // "@odata.context": "http://host/service/$metadata#$ref", // "@odata.id": "Orders(10643)" // } if (this.HttpMethod == HttpMethod.PATCH) { throw Utility.BuildException(HttpStatusCode.MethodNotAllowed, "PATCH on a reference link is not supported.", null); } // Get the parent first var level = this.QueryContext.QueryPath.Count - 2; var parent = this.QueryContext.ResolveQuery(this.DataSource, level); var navigationPropertyName = ((NavigationPropertyLinkSegment)odataPath.LastSegment).NavigationProperty.Name; using (var messageReader = new ODataMessageReader(requestMessage, this.GetReaderSettings(), this.DataSource.Model)) { var referenceLink = messageReader.ReadEntityReferenceLink(); var queryContext = new QueryContext(this.ServiceRootUri, referenceLink.Url, this.DataSource.Model); var target = queryContext.ResolveQuery(this.DataSource); this.DataSource.UpdateProvider.UpdateLink(parent, navigationPropertyName, target); this.DataSource.UpdateProvider.SaveChanges(); } ResponseWriter.WriteEmptyResponse(responseMessage); }
internal override IEnumerable<ODataPayloadKind> DetectPayloadKind(IODataRequestMessage requestMessage, ODataPayloadKindDetectionInfo detectionInfo) { ExceptionUtils.CheckArgumentNotNull<IODataRequestMessage>(requestMessage, "requestMessage"); ExceptionUtils.CheckArgumentNotNull<ODataPayloadKindDetectionInfo>(detectionInfo, "detectionInfo"); Stream messageStream = ((ODataMessage) requestMessage).GetStream(); return this.DetectPayloadKindImplementation(messageStream, false, true, detectionInfo); }
public override void Process(IODataRequestMessage requestMessage, IODataResponseMessage responseMessage) { string asyncToken = this.QueryContext.AsyncToken; AsyncTask asyncTask = AsyncTask.GetTask(asyncToken); if (asyncTask == null) { // token is invalid or expired. throw Utility.BuildException(HttpStatusCode.NotFound); } else { if (!asyncTask.Ready) { ResponseWriter.WriteAsyncPendingResponse(responseMessage, asyncToken); } else { responseMessage.SetHeader(ServiceConstants.HttpHeaders.ContentType, "application/http"); responseMessage.SetHeader(ServiceConstants.HttpHeaders.ContentTransferEncoding, ServiceConstants.HttpHeaderValues.Binary); using (var messageWriter = this.CreateMessageWriter(responseMessage)) { var asyncWriter = messageWriter.CreateODataAsynchronousWriter(); var innerResponse = asyncWriter.CreateResponseMessage(); asyncTask.Execute(innerResponse); } } } }
public static void InitClass(TestContext testContext) { RequestWithApplicationJson = new ODataRequestMessageSimulator(); RequestWithApplicationJson.SetHeader(XmlConstants.HttpContentType, "aPPlicaTion/jSoN"); ResponseWithApplicationJson = new ODataResponseMessageSimulator(); ResponseWithApplicationJson.SetHeader(XmlConstants.HttpContentType, "aPPlicaTion/jSoN"); }
public override void Process(IODataRequestMessage requestMessage, IODataResponseMessage responseMessage) { responseMessage.SetStatusCode(HttpStatusCode.OK); using (var writer = this.CreateMessageWriter(responseMessage)) { writer.WriteServiceDocument(this.GenerateServiceDocument()); } }
/// <summary> /// Create a new feed generator /// </summary> /// <param name="requestMessage">The OData request message that was received</param> /// <param name="responseMessage">The OData response message to be populated by the generator</param> /// <param name="entityMap">The map to use to map RDF URIs to OData types and properties</param> /// <param name="baseUri">The base URI for the OData feed</param> /// <param name="messageWriterSettings">Additional settings to apply to the generated OData output</param> public ODataFeedGenerator(IODataRequestMessage requestMessage, IODataResponseMessage responseMessage, SparqlMap entityMap, string baseUri, ODataMessageWriterSettings messageWriterSettings) { _request = requestMessage; _response = responseMessage; _map = entityMap; _baseUri = baseUri; _writerSettings = messageWriterSettings; }
/// <summary> /// Constructs an internal wrapper around the <paramref name="requestMessage"/> /// that isolates the internal implementation of the ODataLib from the interface. /// </summary> /// <param name="requestMessage">The request message to wrap.</param> /// <param name="writing">true if the request message is being written; false when it is read.</param> /// <param name="disableMessageStreamDisposal">true if the stream returned should ignore dispose calls.</param> /// <param name="maxMessageSize">The maximum size of the message in bytes (or a negative value if no maximum applies).</param> internal ODataRequestMessage(IODataRequestMessage requestMessage, bool writing, bool disableMessageStreamDisposal, long maxMessageSize) : base(writing, disableMessageStreamDisposal, maxMessageSize) { DebugUtils.CheckNoExternalCallers(); Debug.Assert(requestMessage != null, "requestMessage != null"); this.requestMessage = requestMessage; }
/// <summary> /// Initializes a new instance of the <see cref="ClientPreference"/> class. /// </summary> /// <param name="requestDescription">The request description.</param> /// <param name="verb">The request verb.</param> /// <param name="requestMessage">The request message.</param> /// <param name="effectiveMaxResponseVersion">The effective max response version for the request, which is the min of MDSV and MPV.</param> public ClientPreference(RequestDescription requestDescription, HttpVerbs verb, IODataRequestMessage requestMessage, Version effectiveMaxResponseVersion) : this(InterpretClientPreference(requestDescription, verb, requestMessage)) { if (effectiveMaxResponseVersion >= VersionUtil.Version4Dot0) { this.annotationFilter = requestMessage.PreferHeader().AnnotationFilter; } }
public override void Process(IODataRequestMessage requestMessage, IODataResponseMessage responseMessage) { if (this.TryDispatch(requestMessage, responseMessage)) { return; } if (this.QueryContext.Target.TypeKind != EdmTypeKind.Collection) { throw Utility.BuildException(HttpStatusCode.BadRequest, "The new resource can only be created under collection resource.", null); } if (this.QueryContext.Target.IsReference) { this.ProcessCreateLink(requestMessage, responseMessage); return; } try { var targetEntitySet = (IEdmEntitySetBase)this.QueryContext.Target.NavigationSource; // TODO: [lianw] Try to remove "targetEntitySet" later. var queryResults = this.QueryContext.ResolveQuery(this.DataSource); if (!IsAllowInsert(targetEntitySet as IEdmEntitySet)) { throw new ODataServiceException(HttpStatusCode.BadRequest, "The insert request is not allowed.", null); } var bodyObject = ProcessPostBody(requestMessage, targetEntitySet, queryResults); using (var messageWriter = this.CreateMessageWriter(responseMessage)) { this.DataSource.UpdateProvider.SaveChanges(); // 11.4.2 Create an Entity // Upon successful completion the service MUST respond with either 201 Created, or 204 No Content if the request included a return Prefer header with a value of return=minimal. responseMessage.SetStatusCode(HttpStatusCode.Created); responseMessage.SetHeader(ServiceConstants.HttpHeaders.Location, Utility.BuildLocationUri(this.QueryContext, bodyObject).OriginalString); var currentETag = Utility.GetETagValue(bodyObject); // if the current entity has ETag field if (currentETag != null) { responseMessage.SetHeader(ServiceConstants.HttpHeaders.ETag, currentETag); } ResponseWriter.WriteEntry(messageWriter.CreateODataEntryWriter(targetEntitySet), bodyObject, targetEntitySet, ODataVersion.V4, null); } } catch { this.DataSource.UpdateProvider.ClearChanges(); throw; } }
/// <summary> /// Detects the payload kinds supported by this format for the specified message payload. /// </summary> /// <param name="requestMessage">The request message with the payload stream.</param> /// <param name="detectionInfo">Additional information available for the payload kind detection.</param> /// <returns>The set of <see cref="ODataPayloadKind"/>s that are supported with the specified payload.</returns> internal override IEnumerable<ODataPayloadKind> DetectPayloadKind( IODataRequestMessage requestMessage, ODataPayloadKindDetectionInfo detectionInfo) { DebugUtils.CheckNoExternalCallers(); ExceptionUtils.CheckArgumentNotNull(requestMessage, "requestMessage"); ExceptionUtils.CheckArgumentNotNull(detectionInfo, "detectionInfo"); return DetectPayloadKindImplementation(detectionInfo.ContentType); }
/// <summary> /// Detects the payload kinds supported by this format for the specified message payload. /// </summary> /// <param name="requestMessage">The request message with the payload stream.</param> /// <param name="detectionInfo">Additional information available for the payload kind detection.</param> /// <returns>The set of <see cref="ODataPayloadKind"/>s that are supported with the specified payload.</returns> internal override IEnumerable<ODataPayloadKind> DetectPayloadKind( IODataRequestMessage requestMessage, ODataPayloadKindDetectionInfo detectionInfo) { DebugUtils.CheckNoExternalCallers(); ExceptionUtils.CheckArgumentNotNull(requestMessage, "requestMessage"); ExceptionUtils.CheckArgumentNotNull(detectionInfo, "detectionInfo"); Stream messageStream = ((ODataMessage)requestMessage).GetStream(); return this.DetectPayloadKindImplementation(messageStream, /*readingResponse*/ false, /*synchronous*/ true, detectionInfo); }
/// <summary> /// Detects the payload kinds supported by this format for the specified message payload. /// </summary> /// <param name="requestMessage">The request message with the payload stream.</param> /// <param name="detectionInfo">Additional information available for the payload kind detection.</param> /// <returns>The set of <see cref="ODataPayloadKind"/>s that are supported with the specified payload.</returns> internal override IEnumerable<ODataPayloadKind> DetectPayloadKind( IODataRequestMessage requestMessage, ODataPayloadKindDetectionInfo detectionInfo) { DebugUtils.CheckNoExternalCallers(); ExceptionUtils.CheckArgumentNotNull(requestMessage, "requestMessage"); ExceptionUtils.CheckArgumentNotNull(detectionInfo, "detectionInfo"); // Metadata is not supported in requests! return Enumerable.Empty<ODataPayloadKind>(); }
public override void Process(IODataRequestMessage requestMessage, IODataResponseMessage responseMessage) { using (var messageWriter = this.CreateMessageWriter(responseMessage)) { ODataError error; HttpStatusCode statusCode; this.BuildODataError(out error, out statusCode); responseMessage.SetStatusCode(statusCode); messageWriter.WriteError(error, true); } }
public override void Process(IODataRequestMessage requestMessage, IODataResponseMessage responseMessage) { switch (this.HttpMethod) { case HttpMethod.POST: this.ProcessCreate(requestMessage.GetStream(), responseMessage); break; case HttpMethod.PUT: this.ProcessUpdate(requestMessage.GetStream(), responseMessage); break; } }
/// <summary> /// Applies headers in the dictionary to a request message. /// </summary> /// <param name="headers">The dictionary with the headers to apply.</param> /// <param name="requestMessage">The request message to apply the headers to.</param> /// <param name="ignoreAcceptHeader">If set to true the Accept header will be ignored.</param> internal static void ApplyHeadersToRequest(HeaderCollection headers, IODataRequestMessage requestMessage, bool ignoreAcceptHeader) { // NetCF bug with how the enumerators for dictionaries work. foreach (KeyValuePair <string, string> header in headers.AsEnumerable().ToList()) { if (string.Equals(header.Key, XmlConstants.HttpRequestAccept, StringComparison.Ordinal) && ignoreAcceptHeader) { continue; } requestMessage.SetHeader(header.Key, header.Value); } }
/// <summary> /// Gets the <see cref="ODataMessageReader"/> for the <see cref="HttpRequest"/> stream. /// </summary> /// <param name="request">The request.</param> /// <param name="requestContainer">The dependency injection container for the request.</param> /// <returns>A task object that produces an <see cref="ODataMessageReader"/> when completed.</returns> public static ODataMessageReader GetODataMessageReader(this HttpRequest request, IServiceProvider requestContainer) { if (request == null) { throw Error.ArgumentNull("request"); } IODataRequestMessage oDataRequestMessage = ODataMessageWrapperHelper.Create(request.Body, request.Headers, requestContainer); ODataMessageReaderSettings settings = requestContainer.GetRequiredService <ODataMessageReaderSettings>(); ODataMessageReader oDataMessageReader = new ODataMessageReader(oDataRequestMessage, settings); return(oDataMessageReader); }
public void TestCreateODataResourceReader_WithoutEntitySetOrType_DoesNotThrow() { // Arrange IODataRequestMessage request = CreateRequest(); ODataMessageReaderSettings settings = CreateSettings(); IEdmModel model = CreateModel(); using (ODataMessageReader reader = new ODataMessageReader(request, settings, model)) { // Act & Assert ExceptionAssert.DoesNotThrow(() => reader.CreateODataResourceReader()); } }
public void TestReadEntityReferenceLink_WithNavigationProperty_DoesNotThrow() { // Arrange IODataRequestMessage request = CreateRequest("{\"@odata.id\":\"aa:b\"}"); ODataMessageReaderSettings settings = CreateSettings(); IEdmModel model = CreateModel(); using (ODataMessageReader reader = new ODataMessageReader(request, settings, model)) { // Act & Assert Assert.DoesNotThrow(() => reader.ReadEntityReferenceLink()); } }
public override void Process(IODataRequestMessage requestMessage, IODataResponseMessage responseMessage) { switch (this.HttpMethod) { case HttpMethod.POST: this.ProcessCreate(requestMessage.GetStream(), responseMessage); break; case HttpMethod.PUT: this.ProcessUpdate(requestMessage.GetStream(), responseMessage); break; } }
public void TestCreateODataCollectionReader_WithoutTypeReference_Throws() { // Arrange IODataRequestMessage request = CreateRequest(); ODataMessageReaderSettings settings = CreateSettings(); IEdmModel model = CreateModel(); using (ODataMessageReader reader = new ODataMessageReader(request, settings, model)) { // Act & Assert ExceptionAssert.Throws <ODataException>(() => reader.CreateODataCollectionReader()); } }
public void TestReadProperty_InJsonLight_WithoutStructuralPropertyOrTypeReference_DoesNotThrows() { // Arrange IODataRequestMessage request = CreateJsonLightRequest("{\"value\":1}"); ODataMessageReaderSettings settings = CreateSettings(); IEdmModel model = CreateModel(); using (ODataMessageReader reader = new ODataMessageReader(request, settings, model)) { // Act & Assert Assert.DoesNotThrow(() => reader.ReadProperty()); } }
public ODataMessageReader(IODataRequestMessage requestMessage, ODataMessageReaderSettings settings, IEdmModel model) { this.readerPayloadKind = ODataPayloadKind.Unsupported; ExceptionUtils.CheckArgumentNotNull <IODataRequestMessage>(requestMessage, "requestMessage"); this.settings = (settings == null) ? new ODataMessageReaderSettings() : new ODataMessageReaderSettings(settings); ReaderValidationUtils.ValidateMessageReaderSettings(this.settings, false); this.readingResponse = false; this.message = new ODataRequestMessage(requestMessage, false, this.settings.DisableMessageStreamDisposal, this.settings.MessageQuotas.MaxReceivedMessageSize); this.urlResolver = requestMessage as IODataUrlResolver; this.version = ODataUtilsInternal.GetDataServiceVersion(this.message, this.settings.MaxProtocolVersion); this.model = model ?? EdmCoreModel.Instance; ODataVersionChecker.CheckVersionSupported(this.version, this.settings); }
public void TestCreateODataEntryReader_InJsonLight_WithoutEntitySetOrType_Throws() { // Arrange IODataRequestMessage request = CreateJsonLightRequest(); ODataMessageReaderSettings settings = CreateSettings(); IEdmModel model = CreateModel(); using (ODataMessageReader reader = new ODataMessageReader(request, settings, model)) { // Act & Assert Assert.Throws <ODataException>(() => reader.CreateODataEntryReader()); } }
public void TestReadEntityReferenceLink_InJsonLight_WithoutNavigationProperty_Throws() { // Arrange IODataRequestMessage request = CreateJsonLightRequest("{\"url\":\"aa:b\"}"); ODataMessageReaderSettings settings = CreateSettings(); IEdmModel model = CreateModel(); using (ODataMessageReader reader = new ODataMessageReader(request, settings, model)) { // Act & Assert Assert.Throws <ODataException>(() => reader.ReadEntityReferenceLink()); } }
/// <summary> /// Populates the given headers by accessing an expected property called 'Headers' on the given object, /// which must have an 'AllKeys' property and indexer, similar to WebHeaderCollection /// </summary> /// <param name="target">The object to get headers from</param> /// <param name="toPopulate">The headers to populate</param> private static void PopulateHeaders(object target, IDictionary <string, string> toPopulate) { ExceptionUtilities.CheckArgumentNotNull(target, "target"); ExceptionUtilities.CheckArgumentNotNull(toPopulate, "toPopulate"); IEnumerable <KeyValuePair <string, string> > headersDictionary = null; WebHeaderCollection webHeadersCollection = null; IODataResponseMessage responseMessage = target as IODataResponseMessage; if (responseMessage != null) { headersDictionary = responseMessage.Headers; } IODataRequestMessage requestMessage = target as IODataRequestMessage; if (requestMessage != null) { headersDictionary = requestMessage.Headers; } HttpWebRequest httpWebRequest = target as HttpWebRequest; if (httpWebRequest != null) { webHeadersCollection = httpWebRequest.Headers; } HttpWebResponse httpWebResponse = target as HttpWebResponse; if (httpWebResponse != null) { webHeadersCollection = httpWebResponse.Headers; } if (webHeadersCollection != null) { foreach (var header in webHeadersCollection.AllKeys) { toPopulate[header] = webHeadersCollection[header]; } } else { ExceptionUtilities.CheckObjectNotNull(headersDictionary, "Expected to find a Headers list"); foreach (var header in headersDictionary) { toPopulate[header.Key] = header.Value; } } }
public async Task TestReadProperty_WithoutStructuralPropertyOrTypeReference_DoesNotThrows() { // Arrange IODataRequestMessage request = await CreateRequest("{\"value\":1}"); ODataMessageReaderSettings settings = CreateSettings(); IEdmModel model = CreateModel(); using (ODataMessageReader reader = new ODataMessageReader(request, settings, model)) { // Act & Assert ExceptionAssert.DoesNotThrow(() => reader.ReadProperty()); } }
public async Task TestReadEntityReferenceLink_WithoutNavigationProperty_Throws() { // Arrange IODataRequestMessage request = await CreateRequest("{\"odata.id\":\"aa:b\"}"); ODataMessageReaderSettings settings = CreateSettings(); IEdmModel model = CreateModel(); using (ODataMessageReader reader = new ODataMessageReader(request, settings, model)) { // Act & Assert ExceptionAssert.Throws <ODataException>(() => reader.ReadEntityReferenceLink()); } }
public void TestCreateODataEntryReader_InJsonLight_WithEntityTypeButWithoutSet_Throws() { // Arrange IODataRequestMessage request = CreateJsonLightRequest(); ODataMessageReaderSettings settings = CreateSettings(); IEdmModel model = CreateModel(); IEdmEntityType entityType = model.EntityContainer.EntitySets().First().EntityType(); using (ODataMessageReader reader = new ODataMessageReader(request, settings, model)) { // Act & Assert Assert.Throws <ODataException>(() => reader.CreateODataEntryReader(null, entityType)); } }
public static ODataMessageReader GetODataMessageReader(this HttpRequest request, IServiceProvider requestContainer) { if (request == null) { throw new ArgumentNullException(nameof(request)); } // how to dispose it? IODataRequestMessage oDataRequestMessage = ODataMessageWrapperHelper.Create(request.Body, request.Headers, requestContainer); ODataMessageReaderSettings settings = requestContainer.GetRequiredService <ODataMessageReaderSettings>(); ODataMessageReader oDataMessageReader = new ODataMessageReader(oDataRequestMessage, settings); return(oDataMessageReader); }
public void TestCreateODataResourceReader_WithComplexTypeButWithoutSet_DoesnotThrow() { // Arrange IODataRequestMessage request = CreateRequest(); ODataMessageReaderSettings settings = CreateSettings(); IEdmModel model = CreateModel(); IEdmComplexType complexType = model.SchemaElements.OfType <IEdmComplexType>().First(); using (ODataMessageReader reader = new ODataMessageReader(request, settings, model)) { // Act & Assert ExceptionAssert.DoesNotThrow(() => reader.CreateODataResourceReader(null, complexType)); } }
public void TestReadProperty_InJsonLight_WithStructuralProperty_DoesNotThrow() { // Arrange IODataRequestMessage request = CreateJsonLightRequest("{\"value\":1}"); ODataMessageReaderSettings settings = CreateSettings(); IEdmModel model = CreateModel(); IEdmStructuralProperty property = model.EntityContainer.EntitySets().First().EntityType().StructuralProperties().First(); using (ODataMessageReader reader = new ODataMessageReader(request, settings, model)) { // Act & Assert Assert.DoesNotThrow(() => reader.ReadProperty(property)); } }
/// <summary> /// Read and deserialize incoming object from HTTP request stream. /// </summary> /// <param name="type">incoming request body object type.</param> /// <param name="defaultValue">default value for this type.</param> /// <param name="model">Edm model to reference when validating.</param> /// <param name="baseAddress">Base address of request.</param> /// <param name="internalRequest">HTTP request method that contains ODataPath.</param> /// <param name="getODataRequestMessage">Function to obtain customized ODataMessageWrapper.</param> /// <param name="getEdmTypeDeserializer">Function to obtain appropriate edm deserializer.</param> /// <param name="getODataPayloadDeserializer">Function to obtain appropriate deserialize for function payloads.</param> /// <param name="getODataDeserializerContext">Context for Deserializer.</param> /// <param name="registerForDisposeAction">Registration function for disposables.</param> /// <returns>Deserialized object.</returns> internal object ReadFromStream( Type type, object defaultValue, IEdmModel model, Uri baseAddress, HttpRequest internalRequest, Func <IODataRequestMessage> getODataRequestMessage, Func <IEdmTypeReference, ODataDeserializer> getEdmTypeDeserializer, Func <Type, ODataDeserializer> getODataPayloadDeserializer, Func <ODataDeserializerContext> getODataDeserializerContext, Action <IDisposable> registerForDisposeAction, Action <Exception> logErrorAction) { object result; IEdmTypeReference expectedPayloadType; ODataPath path = internalRequest.ODataFeature().Path; ODataDeserializer deserializer = GetDeserializer(type, path, model, getEdmTypeDeserializer, getODataPayloadDeserializer, out expectedPayloadType); if (deserializer == null) { throw new ArgumentException("type", "Formatter does not support reading type " + type.FullName); } try { ODataMessageReaderSettings oDataReaderSettings = internalRequest.GetReaderSettings(); oDataReaderSettings.BaseUri = baseAddress; oDataReaderSettings.Validations = oDataReaderSettings.Validations & ~ValidationKinds.ThrowOnUndeclaredPropertyForNonOpenType; IODataRequestMessage oDataRequestMessage = getODataRequestMessage(); ODataMessageReader oDataMessageReader = new ODataMessageReader(oDataRequestMessage, oDataReaderSettings, model); registerForDisposeAction(oDataMessageReader); ODataDeserializerContext readContext = getODataDeserializerContext(); readContext.Path = path; readContext.Model = model; readContext.ResourceType = type; readContext.ResourceEdmType = expectedPayloadType; result = deserializer.Read(oDataMessageReader, type, readContext); } catch (Exception e) { logErrorAction(e); result = defaultValue; } return(result); }
/// <summary> /// Creates a writer for the given request message and settings. /// </summary> /// <param name="requestMessage">The request message.</param> /// <param name="writerSettings">The writer settings.</param> /// <param name="isParameterPayload">true if the writer is intended to for a parameter payload, false otherwise.</param> /// <returns>Newly created writer.</returns> internal ODataMessageWriter CreateWriter(IODataRequestMessage requestMessage, ODataMessageWriterSettings writerSettings, bool isParameterPayload) { Debug.Assert(requestMessage != null, "requestMessage != null"); Debug.Assert(writerSettings != null, "writerSettings != null"); this.requestInfo.Context.Format.ValidateCanWriteRequestFormat(requestMessage, isParameterPayload); // When calling Execute() to invoke an Action, the client doesn't support parsing the target url // to determine which IEdmOperationImport to pass to the ODL writer. So the ODL writer is // serializing the parameter payload without metadata. Setting the model to null so ODL doesn't // do unecessary validations when writing without metadata. var model = isParameterPayload ? null : this.requestInfo.Model; return new ODataMessageWriter(requestMessage, writerSettings, model); }
public async Task ExecuteOperationAsync_CopiesPropertiesFromRequest_WithoutExcludedProperties() { // Arrange RequestDelegate handler = context => { context.Features[typeof(UnbufferedODataBatchHandlerTest)] = "foo"; return(Task.FromResult(context.Response)); }; UnbufferedODataBatchHandler batchHandler = new UnbufferedODataBatchHandler(); string batchRequest = @"--75148e61-e67a-4bb7-ac0f-78fa30d0da30 Content-Type: application/http Content-Transfer-Encoding: binary Content-ID: 318941389 GET / HTTP/1.1 Host: example.com --75148e61-e67a-4bb7-ac0f-78fa30d0da30-- "; HttpRequest request = RequestFactory.Create("Post", "http://example.com/$batch", opt => opt.AddModel(EdmCoreModel.Instance)); HttpContext httpContext = request.HttpContext; byte[] requestBytes = Encoding.UTF8.GetBytes(batchRequest); request.Body = new MemoryStream(requestBytes); request.ContentType = "multipart/mixed;boundary=\"75148e61-e67a-4bb7-ac0f-78fa30d0da30\""; request.ContentLength = 431; httpContext.ODataFeature().PrefixName = ""; IServiceProvider sp = request.GetSubServiceProvider(); IODataRequestMessage oDataRequestMessage = ODataMessageWrapperHelper.Create(httpContext.Request.Body, request.Headers, sp); ODataMessageReader oDataMessageReader = new ODataMessageReader(oDataRequestMessage, new ODataMessageReaderSettings { BaseUri = new Uri("http://example.com") }); ODataBatchReader batchReader = await oDataMessageReader.CreateODataBatchReaderAsync(); List <ODataBatchResponseItem> responses = new List <ODataBatchResponseItem>(); await batchReader.ReadAsync(); // Act var response = await batchHandler.ExecuteOperationAsync(batchReader, Guid.NewGuid(), httpContext.Request, handler); // Assert OperationResponseItem operationResponseItem = Assert.IsType <OperationResponseItem>(response); Assert.Equal("foo", operationResponseItem.Context.Features[typeof(UnbufferedODataBatchHandlerTest)]); }
public void TestCreateODataEntryReader_InJsonLight_WithEntitySetButWithoutType_DoesNotThrow() { // Arrange IODataRequestMessage request = CreateJsonLightRequest(); ODataMessageReaderSettings settings = CreateSettings(); IEdmModel model = CreateModel(); IEdmEntitySet entitySet = model.EntityContainer.EntitySets().First(); using (ODataMessageReader reader = new ODataMessageReader(request, settings, model)) { // Act & Assert Assert.DoesNotThrow(() => reader.CreateODataEntryReader(entitySet, null)); } }
public void TestReadEntityReferenceLink_InJsonLight_WithNavigationProperty_DoesNotThrow() { // Arrange IODataRequestMessage request = CreateJsonLightRequest("{\"url\":\"aa:b\"}"); ODataMessageReaderSettings settings = CreateSettings(); IEdmModel model = CreateModel(); IEdmNavigationProperty navigationProperty = model.EntityContainers().Single().EntitySets().First().NavigationTargets.First().NavigationProperty; using (ODataMessageReader reader = new ODataMessageReader(request, settings, model)) { // Act & Assert Assert.DoesNotThrow(() => reader.ReadEntityReferenceLink(navigationProperty)); } }
/// <summary> /// Creates a writer for the given request message and settings. /// </summary> /// <param name="requestMessage">The request message.</param> /// <param name="writerSettings">The writer settings.</param> /// <param name="isParameterPayload">true if the writer is intended to for a parameter payload, false otherwise.</param> /// <returns>Newly created writer.</returns> internal ODataMessageWriter CreateWriter(IODataRequestMessage requestMessage, ODataMessageWriterSettings writerSettings, bool isParameterPayload) { Debug.Assert(requestMessage != null, "requestMessage != null"); Debug.Assert(writerSettings != null, "writerSettings != null"); DataServiceClientFormat.ValidateCanWriteRequestFormat(requestMessage); // When calling Execute() to invoke an Action, the client doesn't support parsing the target url // to determine which IEdmOperationImport to pass to the ODL writer. So the ODL writer is // serializing the parameter payload without metadata. Setting the model to null so ODL doesn't // do unnecessary validations when writing without metadata. var model = isParameterPayload ? null : this.requestInfo.Model; return(new ODataMessageWriter(requestMessage, writerSettings, model)); }
public void TestCreateODataCollectionReader_WithTypeReference_DoesNotThrow() { // Arrange IODataRequestMessage request = CreateRequest(); ODataMessageReaderSettings settings = CreateSettings(); IEdmModel model = CreateModel(); IEdmTypeReference expectedItemTypeReference = new EdmPrimitiveTypeReference( EdmCoreModel.Instance.GetPrimitiveType(EdmPrimitiveTypeKind.Int32), false); using (ODataMessageReader reader = new ODataMessageReader(request, settings, model)) { // Act & Assert ExceptionAssert.DoesNotThrow(() => reader.CreateODataCollectionReader(expectedItemTypeReference)); } }
public void TestReadProperty_InJsonLight_WithTypeReference_DoesNotThrow() { // Arrange IODataRequestMessage request = CreateJsonLightRequest("{\"value\":1}"); ODataMessageReaderSettings settings = CreateSettings(); IEdmModel model = CreateModel(); IEdmTypeReference expectedPropertyTypeReference = new EdmPrimitiveTypeReference( EdmCoreModel.Instance.GetPrimitiveType(EdmPrimitiveTypeKind.Int32), false); using (ODataMessageReader reader = new ODataMessageReader(request, settings, model)) { // Act & Assert Assert.DoesNotThrow(() => reader.ReadProperty(expectedPropertyTypeReference)); } }
public static void SetODataRequestContent(IODataRequestMessage requestMessage, IEdmModel model, IInventoryItem inventoryItem) { var setting = new ODataMessageWriterSettings(); setting.SetContentType(ODataFormat.Atom); ODataMessageWriter oDatamessageWriter = new ODataMessageWriter(requestMessage, setting, model); ODataWriter oDataEntrywriter = oDatamessageWriter.CreateODataEntryWriter(); oDataEntrywriter.WriteStart(new ODataEntry() { TypeName = TypeName, Properties = GetODataProperties(inventoryItem) }); oDataEntrywriter.WriteEnd(); }
public void TestCreateODataCollectionReader_InJsonLight_WithTypeReference_DoesNotThrow() { // Arrange IODataRequestMessage request = CreateJsonLightRequest(); ODataMessageReaderSettings settings = CreateSettings(); IEdmModel model = CreateModel(); IEdmOperationImport producingOperationImport = model.EntityContainer.OperationImports().First(); IEdmTypeReference expectedItemTypeReference = new EdmPrimitiveTypeReference( EdmCoreModel.Instance.GetPrimitiveType(EdmPrimitiveTypeKind.Int32), false); using (ODataMessageReader reader = new ODataMessageReader(request, settings, model)) { // Act & Assert Assert.DoesNotThrow(() => reader.CreateODataCollectionReader(expectedItemTypeReference)); } }
/// <summary> /// Gets the <see cref="ODataMessageReader"/> for the <see cref="HttpContent"/> stream. /// </summary> /// <param name="content">The <see cref="HttpContent"/>.</param> /// <param name="settings">The <see cref="ODataMessageReaderSettings"/>.</param> /// <param name="cancellationToken">The token to monitor for cancellation requests.</param> /// <returns>A task object that produces an <see cref="ODataMessageReader"/> when completed.</returns> public static async Task <ODataMessageReader> GetODataMessageReaderAsync(this HttpContent content, ODataMessageReaderSettings settings, CancellationToken cancellationToken) { if (content == null) { throw Error.ArgumentNull("content"); } cancellationToken.ThrowIfCancellationRequested(); Stream contentStream = await content.ReadAsStreamAsync(); IODataRequestMessage oDataRequestMessage = ODataMessageWrapperHelper.Create(contentStream, content.Headers, new MockContainer()); ODataMessageReader oDataMessageReader = new ODataMessageReader(oDataRequestMessage, settings); return(oDataMessageReader); }
private Expression[] ProcessActionInvokePostBody(IODataRequestMessage message, IEdmOperation operation) { using (var messageReader = new ODataMessageReader(message, this.GetReaderSettings())) { List <Expression> parameterValues = new List <Expression>(); var parameterReader = messageReader.CreateODataParameterReader(operation); while (parameterReader.Read()) { switch (parameterReader.State) { case ODataParameterReaderState.Value: { object clrValue = ODataObjectModelConverter.ConvertPropertyValue(parameterReader.Value); parameterValues.Add(Expression.Constant(clrValue)); break; } case ODataParameterReaderState.Collection: { ODataCollectionReader collectionReader = parameterReader.CreateCollectionReader(); object clrValue = ODataObjectModelConverter.ConvertPropertyValue(ODataObjectModelConverter.ReadCollectionParameterValue(collectionReader)); parameterValues.Add(Expression.Constant(clrValue, clrValue.GetType())); break; } case ODataParameterReaderState.Resource: { var entryReader = parameterReader.CreateResourceReader(); object clrValue = ODataObjectModelConverter.ReadEntityOrEntityCollection(entryReader, false); parameterValues.Add(Expression.Constant(clrValue, clrValue.GetType())); break; } case ODataParameterReaderState.ResourceSet: { var feedReader = parameterReader.CreateResourceSetReader(); var collectionList = ODataObjectModelConverter.ReadEntityOrEntityCollection(feedReader, true); parameterValues.Add(Expression.Constant(collectionList, collectionList.GetType())); break; } } } return(parameterValues.ToArray()); } }
public void RequestMessageHeaderTest() { Func <bool, IODataRequestMessage>[] requestMessageFuncs = new Func <bool, IODataRequestMessage>[] { (writing) => CreateBatchOperationRequestMessage(writing), (writing) => new ODataRequestMessageWrapper(new TestRequestMessage(new TestStream()), writing, false), }; this.CombinatorialEngineProvider.RunCombinations( new bool[] { true, false }, requestMessageFuncs, (writing, func) => { IODataRequestMessage requestMessage = func(writing); RunHeaderTest(() => requestMessage.Headers, writing, requestMessage.GetHeader, requestMessage.SetHeader, this.Assert, this.ExceptionVerifier); }); }
internal static async Task <object> ReadFromStreamAsync(Type type, object defaultValue, Uri baseAddress, HttpRequest request, IList <IDisposable> disposes) { object result; IEdmModel model = request.GetModel(); IEdmTypeReference expectedPayloadType; ODataDeserializer deserializer = GetDeserializer(request, type, out expectedPayloadType); if (deserializer == null) { throw Error.Argument("type", SRResources.FormatterReadIsNotSupportedForType, type.FullName, typeof(ODataInputFormatter).FullName); } try { ODataMessageReaderSettings oDataReaderSettings = request.GetReaderSettings(); oDataReaderSettings.BaseUri = baseAddress; oDataReaderSettings.Validations = oDataReaderSettings.Validations & ~ValidationKinds.ThrowOnUndeclaredPropertyForNonOpenType; // WebAPI should read untyped values as structural values by setting ReadUntypedAsString=false. // In ODL 8.x, ReadUntypedAsString option will be deleted. oDataReaderSettings.ReadUntypedAsString = false; IODataRequestMessage oDataRequestMessage = ODataMessageWrapperHelper.Create(new StreamWrapper(request.Body), request.Headers, request.GetODataContentIdMapping(), request.GetSubServiceProvider()); ODataMessageReader oDataMessageReader = new ODataMessageReader(oDataRequestMessage, oDataReaderSettings, model); disposes.Add(oDataMessageReader); ODataPath path = request.ODataFeature().Path; ODataDeserializerContext readContext = BuildDeserializerContext(request); readContext.Path = path; readContext.Model = model; readContext.ResourceType = type; readContext.ResourceEdmType = expectedPayloadType; result = await deserializer.ReadAsync(oDataMessageReader, type, readContext).ConfigureAwait(false); } catch (Exception ex) { LoggerError(request.HttpContext, ex); result = defaultValue; } return(result); }
internal BatchServiceHost(Uri absoluteServiceUri, IODataRequestMessage operationMessage, string contentId, ODataBatchWriter writer, Version maxDataServiceVersion, Version minDataServiceVersion, Version dataServiceVersion) : this(writer) { this.absoluteServiceUri = absoluteServiceUri; this.absoluteRequestUri = RequestUriProcessor.GetAbsoluteUriFromReference(operationMessage.Url, absoluteServiceUri, dataServiceVersion); this.requestHttpMethod = operationMessage.Method; this.contentId = contentId; foreach (KeyValuePair<string, string> pair in operationMessage.Headers) { this.requestHeaders.Add(pair.Key, pair.Value); } if (string.IsNullOrEmpty(this.requestHeaders["MaxDataServiceVersion"])) { this.requestHeaders["MaxDataServiceVersion"] = maxDataServiceVersion.ToString(); } if (string.IsNullOrEmpty(this.requestHeaders["MinDataServiceVersion"])) { this.requestHeaders["MinDataServiceVersion"] = minDataServiceVersion.ToString(); } this.requestStream = operationMessage.GetStream(); }
public override void Process(IODataRequestMessage requestMessage, IODataResponseMessage responseMessage) { try { var odataPath = this.QueryContext.QueryPath; if (this.QueryContext.Target.IsReference && this.QueryContext.Target.TypeKind != EdmTypeKind.Collection) { ProcessUpdateEntityReference(requestMessage, responseMessage, odataPath); } else { ProcessUpdateOrUpsertEntity(requestMessage, responseMessage, odataPath); } } catch { this.DataSource.UpdateProvider.ClearChanges(); throw; } }
public override void Process(IODataRequestMessage requestMessage, IODataResponseMessage responseMessage) { // TODO: we will need to add server-driven paging for delta link object queryResults = this.QueryContext.ResolveQuery(this.DataSource); using (var messageWriter = this.CreateMessageWriter(responseMessage)) { IEdmNavigationSource navigationSource = this.QueryContext.Target.NavigationSource; IEnumerable iEnumerableResults = queryResults as IEnumerable; if (this.QueryContext.Target.NavigationSource != null && this.QueryContext.Target.TypeKind == EdmTypeKind.Collection) { IEdmEntitySetBase entitySet = navigationSource as IEdmEntitySetBase; IEdmEntityType entityType = this.QueryContext.Target.ElementType as IEdmEntityType; if (entitySet == null || entityType == null) { throw new InvalidOperationException("Invalid target when query feed."); } GenerateDeltaItemsFromFeed(iEnumerableResults, entitySet, ODataVersion.V4, this.QueryContext.QuerySelectExpandClause); Uri newDeltaLink = null; if (this.PreferenceContext.TrackingChanges) { var newDeltaToken = DeltaContext.GenerateDeltaToken(this.QueryContext.QueryUri, iEnumerableResults, entitySet, this.QueryContext.QuerySelectExpandClause); newDeltaLink = new Uri(string.Format("{0}?{1}={2}", this.ServiceRootUri, ServiceConstants.QueryOption_Delta, newDeltaToken)); responseMessage.AddPreferenceApplied(ServiceConstants.Preference_TrackChanging); } ODataDeltaWriter resultWriter = messageWriter.CreateODataDeltaWriter(entitySet, entityType); ResponseWriter.WriteDeltaFeed(resultWriter, this.DeltaItems, this.QueryContext.CountOption, newDeltaLink); resultWriter.Flush(); } else { throw Utility.BuildException(HttpStatusCode.Gone); } } }
public ODataResponseContext(IODataRequestMessage requestMessage, ODataFormat format, ODataVersion version, Uri baseAddress, string serviceOperationName) { if (requestMessage == null) { throw Error.ArgumentNull("requestMessage"); } if (baseAddress == null) { throw Error.ArgumentNull("baseAddress"); } if (String.IsNullOrEmpty(serviceOperationName)) { throw Error.ArgumentNullOrEmpty("serviceOperationName"); } _requestMessage = requestMessage; ODataFormat = format; ODataVersion = version; _baseAddress = baseAddress; _serviceOperationName = serviceOperationName; IsIndented = true; }
private Expression[] ProcessActionInvokePostBody(IODataRequestMessage message, IEdmOperation operation) { using (var messageReader = new ODataMessageReader(message, this.GetReaderSettings(), this.DataSource.Model)) { List<Expression> parameterValues = new List<Expression>(); var parameterReader = messageReader.CreateODataParameterReader(operation); while (parameterReader.Read()) { switch (parameterReader.State) { case ODataParameterReaderState.Value: { object clrValue = ODataObjectModelConverter.ConvertPropertyValue(parameterReader.Value); parameterValues.Add(Expression.Constant(clrValue)); break; } case ODataParameterReaderState.Collection: { ODataCollectionReader collectionReader = parameterReader.CreateCollectionReader(); object clrValue = ODataObjectModelConverter.ConvertPropertyValue(ODataObjectModelConverter.ReadCollectionParameterValue(collectionReader)); parameterValues.Add(Expression.Constant(clrValue, clrValue.GetType())); break; } case ODataParameterReaderState.Entry: { var entryReader = parameterReader.CreateEntryReader(); object clrValue = ODataObjectModelConverter.ConvertPropertyValue(ODataObjectModelConverter.ReadEntryParameterValue(entryReader)); parameterValues.Add(Expression.Constant(clrValue, clrValue.GetType())); break; } case ODataParameterReaderState.Feed: { IList collectionList = null; var feedReader = parameterReader.CreateFeedReader(); while (feedReader.Read()) { if (feedReader.State == ODataReaderState.EntryEnd) { object clrItem = ODataObjectModelConverter.ConvertPropertyValue(feedReader.Item); if (collectionList == null) { Type itemType = clrItem.GetType(); Type listType = typeof(List<>).MakeGenericType(new[] { itemType }); collectionList = (IList)Utility.QuickCreateInstance(listType); } collectionList.Add(clrItem); } } parameterValues.Add(Expression.Constant(collectionList, collectionList.GetType())); break; } } } return parameterValues.ToArray(); } }
private static ODataMessageReader GetODataMessageReader(IODataRequestMessage oDataRequestMessage, IEdmModel edmModel) { return new ODataMessageReader(oDataRequestMessage, new ODataMessageReaderSettings(), edmModel); }
protected bool TryDispatch(IODataRequestMessage requestMessage, IODataResponseMessage responseMessage) { RequestHandler handler = this.DispatchHandler(); if (handler != null) { handler.Process(requestMessage, responseMessage); return true; } return false; }
public override void Process(IODataRequestMessage requestMessage, IODataResponseMessage responseMessage) { object result; if (this.HttpMethod == HttpMethod.GET) { // we cannot invoke same action request multiple times, so only Functions are allowed to do the server-driven paging this.QueryContext.InitializeServerDrivenPaging(this.PreferenceContext); result = this.ProcessFunction(); if (this.PreferenceContext.MaxPageSize.HasValue) { responseMessage.AddPreferenceApplied(string.Format("{0}={1}", ServiceConstants.Preference_MaxPageSize, this.QueryContext.appliedPageSize.Value)); } } else { // TODO: currently ETag feature does not support action operation result = this.ProcessAction(requestMessage); } if (result == null) { // Protocol 9.1.4 Response Code 204 No Content // A request returns 204 No Content if the requested resource has the null value, // or if the service applies a return=minimal preference. In this case, the response body MUST be empty. ResponseWriter.WriteEmptyResponse(responseMessage); return; } using (var messageWriter = this.CreateMessageWriter(responseMessage)) { if (this.QueryContext.Target.TypeKind == EdmTypeKind.None || this.QueryContext.Target.TypeKind == EdmTypeKind.EntityReference || this.QueryContext.Target.ElementTypeKind == EdmTypeKind.EntityReference) { throw Utility.BuildException(HttpStatusCode.NotImplemented, "Unsupported return type in operation.", null); } else if (this.QueryContext.Target.TypeKind == EdmTypeKind.Entity || this.QueryContext.Target.ElementTypeKind == EdmTypeKind.Entity) { ODataWriter resultWriter; IEdmNavigationSource entitySource = this.QueryContext.OperationResultSource ?? this.QueryContext.Target.NavigationSource; if (this.QueryContext.Target.TypeKind == EdmTypeKind.Collection) { IEdmEntitySetBase entitySet = (IEdmEntitySetBase)entitySource; resultWriter = messageWriter.CreateODataFeedWriter(entitySet, (IEdmEntityType)this.QueryContext.Target.ElementType); ResponseWriter.WriteFeed(resultWriter, (IEdmEntityType)this.QueryContext.Target.ElementType, result as IEnumerable, entitySet, ODataVersion.V4, this.QueryContext.QuerySelectExpandClause, this.QueryContext.TotalCount, null, this.QueryContext.NextLink, this.RequestHeaders); } else { if (this.HttpMethod == HttpMethod.GET) { var currentETag = Utility.GetETagValue(result); // if the current entity has ETag field if (currentETag != null) { string requestETag; if (Utility.TryGetIfNoneMatch(this.RequestHeaders, out requestETag) && (requestETag == ServiceConstants.ETagValueAsterisk || requestETag == currentETag)) { ResponseWriter.WriteEmptyResponse(responseMessage, HttpStatusCode.NotModified); return; } responseMessage.SetHeader(ServiceConstants.HttpHeaders.ETag, currentETag); } } resultWriter = messageWriter.CreateODataEntryWriter(entitySource, (IEdmEntityType)this.QueryContext.Target.Type); ResponseWriter.WriteEntry(resultWriter, result, entitySource, ODataVersion.V4, this.QueryContext.QuerySelectExpandClause, this.RequestHeaders); } } else { ODataProperty property = new ODataProperty() { Name = "value", Value = ODataObjectModelConverter.CreateODataValue(result) }; messageWriter.WriteProperty(property); } } }
public virtual void Process(IODataRequestMessage requestMessage, IODataResponseMessage responseMessage) { throw new NotImplementedException(); }
protected virtual ODataMessageReader CreateMessageReader(IODataRequestMessage message) { return new ODataMessageReader( message, this.GetReaderSettings(), this.DataSource.Model); }
private void ProcessUpsertEntity(IODataRequestMessage requestMessage, IODataResponseMessage responseMessage, ODataPath odataPath) { if (this.QueryContext.Target.TypeKind == EdmTypeKind.Entity && !this.QueryContext.Target.IsReference) { Uri parentUri = this.QueryContext.Target.BuildContainerUri(this.ServiceRootUri); QueryContext parentContext = new QueryContext(this.ServiceRootUri, parentUri, this.DataSource.Model); if (parentContext.Target.IsEntitySet) { // Update a entity under a entity set => Upsert // TODO: Do we need to preserver the key value? new CreateHandler(this, parentContext.QueryUri).Process(requestMessage, responseMessage); } else { // Update Singleton or single value entity from null value. var parent = parentContext.ResolveQuery(this.DataSource); // TODO: It might not correct here, since the last segment could be type segment. NavigationPropertySegment navSegment = (NavigationPropertySegment)odataPath.LastSegment; var targetObject = Utility.CreateResource(this.QueryContext.Target.Type); parent.GetType().GetProperty(navSegment.NavigationProperty.Name).SetValue(parent, targetObject, null); ProcessUpdateRequestBody(requestMessage, responseMessage, targetObject, true); } } else { throw Utility.BuildException(HttpStatusCode.NotFound); } }
private void ProcessUpdateOrUpsertEntity(IODataRequestMessage requestMessage, IODataResponseMessage responseMessage, ODataPath odataPath) { var targetObject = this.QueryContext.ResolveQuery(this.DataSource); string targetETag = null; if (targetObject != null) { targetETag = Utility.GetETagValue(targetObject); } var requestETagKind = RequestETagKind.None; string requestETag; if (Utility.TryGetIfMatch(this.RequestHeaders, out requestETag)) { requestETagKind = RequestETagKind.IfMatch; } else if (Utility.TryGetIfNoneMatch(this.RequestHeaders, out requestETag)) { requestETagKind = RequestETagKind.IfNoneMatch; } switch (requestETagKind) { case RequestETagKind.None: { if (targetETag == null) { if (targetObject == null) { ProcessUpsertEntity(requestMessage, responseMessage, odataPath); } else { ProcessUpdateRequestBody(requestMessage, responseMessage, targetObject, false); } } else { ResponseWriter.WriteEmptyResponse(responseMessage, (HttpStatusCode)428); } break; } case RequestETagKind.IfMatch: { if (requestETag == ServiceConstants.ETagValueAsterisk || requestETag == targetETag) { if (targetObject == null) { throw Utility.BuildException(HttpStatusCode.NotFound); } ProcessUpdateRequestBody(requestMessage, responseMessage, targetObject, false); } else { ResponseWriter.WriteEmptyResponse(responseMessage, HttpStatusCode.PreconditionFailed); } break; } case RequestETagKind.IfNoneMatch: { if (requestETag == ServiceConstants.ETagValueAsterisk) { ProcessUpsertEntity(requestMessage, responseMessage, odataPath); } else if (requestETag != targetETag) { if (targetObject == null) { throw Utility.BuildException(HttpStatusCode.NotFound); } ProcessUpdateRequestBody(requestMessage, responseMessage, targetObject, false); } else { ResponseWriter.WriteEmptyResponse(responseMessage, HttpStatusCode.PreconditionFailed); } break; } } }
private void ProcessUpdateRequestBody(IODataRequestMessage requestMessage, IODataResponseMessage responseMessage, object targetObject, bool isUpsert) { if (this.QueryContext.Target.NavigationSource != null && this.QueryContext.Target.TypeKind == EdmTypeKind.Entity) { using (var messageReader = new ODataMessageReader(requestMessage, this.GetReaderSettings(), this.DataSource.Model)) { var entryReader = messageReader.CreateODataEntryReader(this.QueryContext.Target.NavigationSource, (IEdmEntityType)this.QueryContext.Target.Type); while (entryReader.Read()) { switch (entryReader.State) { case ODataReaderState.EntryEnd: var entry = (ODataEntry)entryReader.Item; foreach (var property in entry.Properties) { if (Utility.IsETagProperty(targetObject, property.Name)) continue; // the property might be an open property, so test null first var propertyInfo = targetObject.GetType().GetProperty(property.Name); if (propertyInfo != null) { if (!isUpsert && Utility.IsReadOnly(propertyInfo)) continue; } this.DataSource.UpdateProvider.Update(targetObject, property.Name, property.Value); } break; } } } } else if (this.QueryContext.Target.Property != null && this.QueryContext.Target.TypeKind == EdmTypeKind.Complex) { using (var messageReader = new ODataMessageReader(requestMessage, this.GetReaderSettings(), this.DataSource.Model)) { var property = messageReader.ReadProperty(this.QueryContext.Target.Property); ODataComplexValue complexValue = property.Value as ODataComplexValue; foreach (var p in complexValue.Properties) { if (Utility.IsETagProperty(targetObject, property.Name)) continue; this.DataSource.UpdateProvider.Update(targetObject, p.Name, p.Value); } } } else { throw Utility.BuildException( HttpStatusCode.NotImplemented, string.Format("PATCH/PUT for '{0}' type is not supported.", this.QueryContext.Target.TypeKind), null); } var currentETag = Utility.GetETagValue(targetObject); // if the current entity has ETag field if (currentETag != null) { if (!isUpsert) { this.DataSource.UpdateProvider.UpdateETagValue(targetObject); } this.DataSource.UpdateProvider.SaveChanges(); currentETag = Utility.GetETagValue(targetObject); responseMessage.SetHeader(ServiceConstants.HttpHeaders.ETag, currentETag); } else { this.DataSource.UpdateProvider.SaveChanges(); } ResponseWriter.WriteEmptyResponse(responseMessage); }