public void InitialHeadersComesFromConstructor() { var headers = new HeaderCollection(); headers.SetHeader("Header1", "Value1"); headers.SetHeader("Header #2", "A Second *value*"); SetupTest("ABCD", new Uri("https://www.example.com/odata.svc/"), headers).Headers.Should().Contain("Header1", "Value1").And.Contain("Header #2", "A Second *value*"); }
/// <summary> /// Creates the result object for the specified query parameters. /// </summary> /// <param name="source">The source object for the request.</param> /// <param name="context">The data service context.</param> /// <param name="callback">The AsyncCallback delegate.</param> /// <param name="state">The state object for the callback.</param> /// <param name="method">async method name at the source.</param> /// <returns>Result representing the create request. The request has not been initiated yet.</returns> private QueryResult CreateExecuteResult(object source, DataServiceContext context, AsyncCallback callback, object state, string method) { Debug.Assert(context != null, "context is null"); QueryComponents qc = this.QueryComponents(context.Model); RequestInfo requestInfo = new RequestInfo(context); Debug.Assert( string.CompareOrdinal(XmlConstants.HttpMethodPost, qc.HttpMethod) == 0 || string.CompareOrdinal(XmlConstants.HttpMethodGet, qc.HttpMethod) == 0 || string.CompareOrdinal(XmlConstants.HttpMethodDelete, qc.HttpMethod) == 0, "Only get, post and delete are supported in the execute pipeline, which should have been caught earlier"); if (qc.UriOperationParameters != null) { Debug.Assert(qc.UriOperationParameters.Any(), "qc.UriOperationParameters.Any()"); Serializer serializer = new Serializer(requestInfo); this.RequestUri = serializer.WriteUriOperationParametersToUri(this.RequestUri, qc.UriOperationParameters); } HeaderCollection headers = new HeaderCollection(); if (string.CompareOrdinal(XmlConstants.HttpMethodPost, qc.HttpMethod) == 0) { if (qc.BodyOperationParameters == null) { // set the content length to be 0 if there are no operation parameters. headers.SetHeader(XmlConstants.HttpContentLength, "0"); } else { context.Format.SetRequestContentTypeForOperationParameters(headers); } } // Validate and set the request DSV and MDSV header headers.SetRequestVersion(qc.Version, requestInfo.MaxProtocolVersionAsVersion); requestInfo.Format.SetRequestAcceptHeaderForQuery(headers, qc); // We currently do not have a descriptor to expose to the user for invoking something through Execute. Ideally we could expose an OperationDescriptor. ODataRequestMessageWrapper requestMessage = new RequestInfo(context).WriteHelper.CreateRequestMessage(context.CreateRequestArgsAndFireBuildingRequest(qc.HttpMethod, this.RequestUri, headers, context.HttpStack, null /*descriptor*/)); requestMessage.FireSendingRequest2(null /*descriptor*/); if (qc.BodyOperationParameters != null) { Debug.Assert(string.CompareOrdinal(XmlConstants.HttpMethodPost, qc.HttpMethod) == 0, "qc.HttpMethod == XmlConstants.HttpMethodPost"); Debug.Assert(qc.BodyOperationParameters.Any(), "unexpected body operation parameter count of zero."); Serializer serializer = new Serializer(requestInfo, context.EntityParameterSendOption); serializer.WriteBodyOperationParameters(qc.BodyOperationParameters, requestMessage); // pass in the request stream so that request payload can be written to the http webrequest. return(new QueryResult(source, method, this, requestMessage, requestInfo, callback, state, requestMessage.CachedRequestStream)); } return(new QueryResult(source, method, this, requestMessage, requestInfo, callback, state)); }
/// <summary> /// Creates a ODataRequestMessage for batch request. /// </summary> /// <returns>Returns an instance of ODataRequestMessage for the batch request.</returns> private ODataRequestMessageWrapper CreateBatchRequest() { Uri requestUri = UriUtil.CreateUri(this.RequestInfo.BaseUriResolver.GetBaseUriWithSlash(), UriUtil.CreateUri("$batch", UriKind.Relative)); HeaderCollection headers = new HeaderCollection(); headers.SetRequestVersion(Util.ODataVersion4, this.RequestInfo.MaxProtocolVersionAsVersion); headers.SetHeader(XmlConstants.HttpContentType, CreateMultiPartMimeContentType()); this.RequestInfo.Format.SetRequestAcceptHeaderForBatch(headers); return(this.CreateTopLevelRequest(XmlConstants.HttpMethodPost, requestUri, headers, this.RequestInfo.HttpStack, null /*descriptor*/)); }
/// <summary> /// Sets the content and the headers of the media resource request /// </summary> /// <param name="headers">The header collection to setup.</param> /// <param name="saveStream">DataServiceSaveStream instance containing all information about the stream.</param> /// <param name="etag">ETag header value to be set. If passed null, etag header is not set.</param> /// <remarks>This only works with the V2 MR support (SetSaveStream), this will not setup /// the request for V1 property based MRs.</remarks> private void SetupMediaResourceRequest(HeaderCollection headers, DataServiceSaveStream saveStream, string etag) { // Get the write stream for this MR this.mediaResourceRequestStream = saveStream.Stream; // Copy over headers for the request, except the accept header headers.SetHeaders(saveStream.Args.Headers.Where(h => !string.Equals(h.Key, XmlConstants.HttpRequestAccept, StringComparison.OrdinalIgnoreCase))); if (etag != null) { headers.SetHeader(XmlConstants.HttpRequestIfMatch, etag); } // Do NOT set the ContentLength since we don't know if the stream even supports reporting its length }
/// <summary>operation with exception</summary> /// <param name="e">exception object</param> /// <param name="response">response object</param> private void HandleOperationException(InvalidOperationException e, IODataResponseMessage response) { Debug.Assert(this.entryIndex >= 0 && this.entryIndex < this.ChangedEntries.Count, string.Format(System.Globalization.CultureInfo.InvariantCulture, "this.entryIndex = '{0}', this.ChangedEntries.Count = '{1}'", this.entryIndex, this.ChangedEntries.Count)); Descriptor current = this.ChangedEntries[this.entryIndex]; HeaderCollection headers = null; HttpStatusCode statusCode = HttpStatusCode.InternalServerError; Version responseVersion = null; if (response != null) { headers = new HeaderCollection(response); statusCode = (HttpStatusCode)response.StatusCode; this.HandleOperationResponseHeaders(statusCode, headers); e = BaseSaveResult.HandleResponse( this.RequestInfo, statusCode, response.GetHeader(XmlConstants.HttpODataVersion), response.GetStream, false /*throwOnFailure*/, out responseVersion); } else { headers = new HeaderCollection(); headers.SetHeader(XmlConstants.HttpContentType, XmlConstants.MimeTextPlain); // In V2 we used to merge individual responses from a call to SaveChanges() into a single batch response payload and then process that. // When we encounter an exception at this point in V2, we used to write the exception to the batch response payload and later on when we // process through the batch response, we create a DataServiceClientException for each failed operation. // For backcompat reason, we will always convert the exception type to DataServiceClientException here. Debug.Assert(e != null, "e != null"); if (e.GetType() != typeof(DataServiceClientException)) { e = new DataServiceClientException(e.Message, e); } } // For error scenarios, we never invoke the ReadingEntity event. this.cachedResponses.Add(new CachedResponse(current, headers, statusCode, responseVersion, null, e)); this.perRequest = null; this.CheckContinueOnError(); }
/// <summary> /// Creates a ODataRequestMessage for batch request. /// </summary> /// <returns>Returns an instance of ODataRequestMessage for the batch request.</returns> private ODataRequestMessageWrapper CreateBatchRequest() { Uri requestUri = UriUtil.CreateUri(this.RequestInfo.BaseUriResolver.GetBaseUriWithSlash(), UriUtil.CreateUri("$batch", UriKind.Relative)); HeaderCollection headers = new HeaderCollection(); headers.SetRequestVersion(Util.ODataVersion4, this.RequestInfo.MaxProtocolVersionAsVersion); headers.SetHeader(XmlConstants.HttpContentType, CreateMultiPartMimeContentType()); this.RequestInfo.Format.SetRequestAcceptHeaderForBatch(headers); return this.CreateTopLevelRequest(XmlConstants.HttpMethodPost, requestUri, headers, this.RequestInfo.HttpStack, null /*descriptor*/); }
internal List<Stream> GetChangeStream() { List<Stream> stream = new List<Stream>(); HeaderCollection headers = new HeaderCollection(); headers.SetHeader("Content-Type", "application/atom+xml;odata.metadata=minimal"); for (int i = 0; i < this.ChangedEntries.Count; ++i) { ODataRequestMessageWrapper requestMessage = ODataRequestMessageWrapper.CreateRequestMessageWrapper( new BuildingRequestEventArgs("GET", new Uri("http://service.svc/randomuri"), headers, null, HttpStack.Auto), this.RequestInfo); this.CreateChangeData(i, requestMessage); stream.Add(requestMessage.CachedRequestStream.Stream); } return stream; }
/// <summary> /// Create ODataRequestMessage for the given entity. /// </summary> /// <param name="entityDescriptor">resource</param> /// <returns>An instance of ODataRequestMessage for the given entity.</returns> protected ODataRequestMessageWrapper CreateRequest(EntityDescriptor entityDescriptor) { Debug.Assert(null != entityDescriptor, "null entityDescriptor"); Debug.Assert(entityDescriptor.State == EntityStates.Added || entityDescriptor.State == EntityStates.Deleted || entityDescriptor.State == EntityStates.Modified, "the entity must be in one of the 3 possible states"); EntityStates state = entityDescriptor.State; Uri requestUri = entityDescriptor.GetResourceUri(this.RequestInfo.BaseUriResolver, false /*queryLink*/); Debug.Assert(null != requestUri, "request uri is null"); Debug.Assert(requestUri.IsAbsoluteUri, "request uri is not absolute uri"); ClientEdmModel model = this.RequestInfo.Model; ClientTypeAnnotation clientType = model.GetClientTypeAnnotation(model.GetOrCreateEdmType(entityDescriptor.Entity.GetType())); Version requestVersion = DetermineRequestVersion(clientType); string httpMethod = this.GetHttpMethod(state, ref requestVersion); HeaderCollection headers = new HeaderCollection(); // Set the content type if (EntityStates.Deleted != entityDescriptor.State) { this.RequestInfo.Context.Format.SetRequestContentTypeForEntry(headers); } // Set IfMatch (etag) header for update and delete requests if ((EntityStates.Deleted == state) || (EntityStates.Modified == state)) { string etag = entityDescriptor.GetLatestETag(); if (etag != null) { headers.SetHeader(XmlConstants.HttpRequestIfMatch, etag); } } // Set the prefer header if required ApplyPreferences(headers, httpMethod, this.RequestInfo.AddAndUpdateResponsePreference, ref requestVersion); // Set the request DSV and request MDSV headers headers.SetRequestVersion(requestVersion, this.RequestInfo.MaxProtocolVersionAsVersion); this.RequestInfo.Format.SetRequestAcceptHeader(headers); return this.CreateRequestMessage(httpMethod, requestUri, headers, this.RequestInfo.HttpStack, entityDescriptor, this.IsBatchRequest ? entityDescriptor.ChangeOrder.ToString(CultureInfo.InvariantCulture) : null); }
/// <summary> /// Apply the response preferences for the client. /// </summary> /// <param name="headers">Headers to which preferences will be added.</param> /// <param name="method">HTTP method.</param> /// <param name="responsePreference">Response preference.</param> /// <param name="requestVersion">Request version so far for the request. The method may modify it.</param> protected static void ApplyPreferences(HeaderCollection headers, string method, DataServiceResponsePreference responsePreference, ref Version requestVersion) { // The AddAndUpdateResponsePreference only applies to POST/PUT/PATCH requests if (string.CompareOrdinal(XmlConstants.HttpMethodPost, method) != 0 && string.CompareOrdinal(XmlConstants.HttpMethodPut, method) != 0 && string.CompareOrdinal(XmlConstants.HttpMethodPatch, method) != 0) { return; } string preferHeaderValue = WebUtil.GetPreferHeaderAndRequestVersion(responsePreference, ref requestVersion); if (preferHeaderValue != null) { headers.SetHeader(XmlConstants.HttpPrefer, preferHeaderValue); } }
/// <summary>operation with exception</summary> /// <param name="e">exception object</param> /// <param name="response">response object</param> private void HandleOperationException(InvalidOperationException e, IODataResponseMessage response) { Debug.Assert(this.entryIndex >= 0 && this.entryIndex < this.ChangedEntries.Count(), string.Format(System.Globalization.CultureInfo.InvariantCulture, "this.entryIndex = '{0}', this.ChangedEntries.Count = '{1}'", this.entryIndex, this.ChangedEntries.Count())); Descriptor current = this.ChangedEntries[this.entryIndex]; HeaderCollection headers = null; HttpStatusCode statusCode = HttpStatusCode.InternalServerError; Version responseVersion = null; if (null != response) { headers = new HeaderCollection(response); statusCode = (HttpStatusCode)response.StatusCode; this.HandleOperationResponseHeaders(statusCode, headers); e = BaseSaveResult.HandleResponse( this.RequestInfo, statusCode, response.GetHeader(XmlConstants.HttpODataVersion), response.GetStream, false/*throwOnFailure*/, out responseVersion); } else { headers = new HeaderCollection(); headers.SetHeader(XmlConstants.HttpContentType, XmlConstants.MimeTextPlain); // In V2 we used to merge individual responses from a call to SaveChanges() into a single batch response payload and then process that. // When we encounter an exception at this point in V2, we used to write the exception to the batch response payload and later on when we // process through the batch response, we create a DataServiceClientException for each failed operation. // For backcompat reason, we will always convert the exception type to DataServiceClientException here. Debug.Assert(e != null, "e != null"); if (e.GetType() != typeof(DataServiceClientException)) { e = new DataServiceClientException(e.Message, e); } } // For error scenarios, we never invoke the ReadingEntity event. this.cachedResponses.Add(new CachedResponse(current, headers, statusCode, responseVersion, null, e)); this.perRequest = null; this.CheckContinueOnError(); }
/// <summary> /// Sets the content and the headers of the media resource request /// </summary> /// <param name="headers">The header collection to setup.</param> /// <param name="saveStream">DataServiceSaveStream instance containing all information about the stream.</param> /// <param name="etag">ETag header value to be set. If passed null, etag header is not set.</param> /// <remarks>This only works with the V2 MR support (SetSaveStream), this will not setup /// the request for V1 property based MRs.</remarks> private void SetupMediaResourceRequest(HeaderCollection headers, DataServiceSaveStream saveStream, string etag) { // Get the write stream for this MR this.mediaResourceRequestStream = saveStream.Stream; // Copy over headers for the request, except the accept header headers.SetHeaders(saveStream.Args.Headers.Where(h => !string.Equals(h.Key, XmlConstants.HttpRequestAccept, StringComparison.OrdinalIgnoreCase))); if (etag != null) { headers.SetHeader(XmlConstants.HttpRequestIfMatch, etag); } // Do NOT set the ContentLength since we don't know if the stream even supports reporting its length }
/// <summary> /// Check to see if the resource to be inserted is a media descriptor, and if so /// setup a POST request for the media content first and turn the rest of /// the operation into a PUT to update the rest of the properties. /// </summary> /// <param name="entityDescriptor">The resource to check/process</param> /// <returns>An instance of ODataRequestMessage to do POST to the media resource</returns> private ODataRequestMessageWrapper CheckAndProcessMediaEntryPost(EntityDescriptor entityDescriptor) { // TODO: Revisit the design of how media link entries are handled during update ClientEdmModel model = this.RequestInfo.Model; ClientTypeAnnotation type = model.GetClientTypeAnnotation(model.GetOrCreateEdmType(entityDescriptor.Entity.GetType())); if (!type.IsMediaLinkEntry && !entityDescriptor.IsMediaLinkEntry) { // this is not a media link descriptor, process normally return null; } if (type.MediaDataMember == null && entityDescriptor.SaveStream == null) { // The entity is marked as MLE but we don't have the content property // and the user didn't set the save stream. throw Error.InvalidOperation(Strings.Context_MLEWithoutSaveStream(type.ElementTypeName)); } Debug.Assert( (type.MediaDataMember != null && entityDescriptor.SaveStream == null) || (type.MediaDataMember == null && entityDescriptor.SaveStream != null), "Only one way of specifying the MR content is allowed."); ODataRequestMessageWrapper mediaRequest = null; if (type.MediaDataMember != null) { string contentType = null; int contentLength = 0; if (type.MediaDataMember.MimeTypeProperty == null) { contentType = XmlConstants.MimeApplicationOctetStream; } else { object mimeTypeValue = type.MediaDataMember.MimeTypeProperty.GetValue(entityDescriptor.Entity); String mimeType = mimeTypeValue != null ? mimeTypeValue.ToString() : null; if (String.IsNullOrEmpty(mimeType)) { throw Error.InvalidOperation( Strings.Context_NoContentTypeForMediaLink( type.ElementTypeName, type.MediaDataMember.MimeTypeProperty.PropertyName)); } contentType = mimeType; } object value = type.MediaDataMember.GetValue(entityDescriptor.Entity); if (value == null) { this.mediaResourceRequestStream = null; } else { byte[] buffer = value as byte[]; if (buffer == null) { string mime; Encoding encoding; ContentTypeUtil.ReadContentType(contentType, out mime, out encoding); if (encoding == null) { encoding = Encoding.UTF8; contentType += XmlConstants.MimeTypeUtf8Encoding; } buffer = encoding.GetBytes(ClientConvert.ToString(value)); } contentLength = buffer.Length; #if PORTABLELIB // Win8 doesn't allow accessing the buffer, so the constructor we normally use doesn't exist this.mediaResourceRequestStream = new MemoryStream(buffer, 0, buffer.Length, false); #else // Need to specify that the buffer is publicly visible as we need to access it later on this.mediaResourceRequestStream = new MemoryStream(buffer, 0, buffer.Length, false, true); #endif } HeaderCollection headers = new HeaderCollection(); headers.SetHeader(XmlConstants.HttpContentLength, contentLength.ToString(CultureInfo.InvariantCulture)); headers.SetHeader(XmlConstants.HttpContentType, contentType); mediaRequest = this.CreateMediaResourceRequest( entityDescriptor.GetResourceUri(this.RequestInfo.BaseUriResolver, false /*queryLink*/), XmlConstants.HttpMethodPost, Util.ODataVersion4, type.MediaDataMember == null, // sendChunked true, // applyResponsePreference headers, entityDescriptor); } else { HeaderCollection headers = new HeaderCollection(); this.SetupMediaResourceRequest(headers, entityDescriptor.SaveStream, null /*etag*/); mediaRequest = this.CreateMediaResourceRequest( entityDescriptor.GetResourceUri(this.RequestInfo.BaseUriResolver, false /*queryLink*/), XmlConstants.HttpMethodPost, Util.ODataVersion4, type.MediaDataMember == null, // sendChunked true, // applyResponsePreference headers, entityDescriptor); } // Convert the insert into an update for the media link descriptor we just created // (note that the identity still needs to be fixed up on the resbox once // the response comes with the 'location' header; that happens during processing // of the response in SavedResource()) entityDescriptor.State = EntityStates.Modified; return mediaRequest; }
/// <summary> /// Check to see if the resource to be inserted is a media descriptor, and if so /// setup a POST request for the media content first and turn the rest of /// the operation into a PUT to update the rest of the properties. /// </summary> /// <param name="entityDescriptor">The resource to check/process</param> /// <returns>An instance of ODataRequestMessage to do POST to the media resource</returns> private ODataRequestMessageWrapper CheckAndProcessMediaEntryPost(EntityDescriptor entityDescriptor) { // TODO: Revisit the design of how media link entries are handled during update ClientEdmModel model = this.RequestInfo.Model; ClientTypeAnnotation type = model.GetClientTypeAnnotation(model.GetOrCreateEdmType(entityDescriptor.Entity.GetType())); if (!type.IsMediaLinkEntry && !entityDescriptor.IsMediaLinkEntry) { // this is not a media link descriptor, process normally return(null); } if (type.MediaDataMember == null && entityDescriptor.SaveStream == null) { // The entity is marked as MLE but we don't have the content property // and the user didn't set the save stream. throw Error.InvalidOperation(Strings.Context_MLEWithoutSaveStream(type.ElementTypeName)); } Debug.Assert( (type.MediaDataMember != null && entityDescriptor.SaveStream == null) || (type.MediaDataMember == null && entityDescriptor.SaveStream != null), "Only one way of specifying the MR content is allowed."); ODataRequestMessageWrapper mediaRequest = null; if (type.MediaDataMember != null) { string contentType = null; int contentLength = 0; if (type.MediaDataMember.MimeTypeProperty == null) { contentType = XmlConstants.MimeApplicationOctetStream; } else { object mimeTypeValue = type.MediaDataMember.MimeTypeProperty.GetValue(entityDescriptor.Entity); String mimeType = mimeTypeValue != null?mimeTypeValue.ToString() : null; if (String.IsNullOrEmpty(mimeType)) { throw Error.InvalidOperation( Strings.Context_NoContentTypeForMediaLink( type.ElementTypeName, type.MediaDataMember.MimeTypeProperty.PropertyName)); } contentType = mimeType; } object value = type.MediaDataMember.GetValue(entityDescriptor.Entity); if (value == null) { this.mediaResourceRequestStream = null; } else { byte[] buffer = value as byte[]; if (buffer == null) { string mime; Encoding encoding; ContentTypeUtil.ReadContentType(contentType, out mime, out encoding); if (encoding == null) { encoding = Encoding.UTF8; contentType += XmlConstants.MimeTypeUtf8Encoding; } buffer = encoding.GetBytes(ClientConvert.ToString(value)); } contentLength = buffer.Length; // Need to specify that the buffer is publicly visible as we need to access it later on this.mediaResourceRequestStream = new MemoryStream(buffer, 0, buffer.Length, false, true); } HeaderCollection headers = new HeaderCollection(); headers.SetHeader(XmlConstants.HttpContentLength, contentLength.ToString(CultureInfo.InvariantCulture)); headers.SetHeader(XmlConstants.HttpContentType, contentType); mediaRequest = this.CreateMediaResourceRequest( entityDescriptor.GetResourceUri(this.RequestInfo.BaseUriResolver, false /*queryLink*/), XmlConstants.HttpMethodPost, Util.ODataVersion4, type.MediaDataMember == null, // sendChunked true, // applyResponsePreference headers, entityDescriptor); } else { HeaderCollection headers = new HeaderCollection(); this.SetupMediaResourceRequest(headers, entityDescriptor.SaveStream, null /*etag*/); mediaRequest = this.CreateMediaResourceRequest( entityDescriptor.GetResourceUri(this.RequestInfo.BaseUriResolver, false /*queryLink*/), XmlConstants.HttpMethodPost, Util.ODataVersion4, type.MediaDataMember == null, // sendChunked true, // applyResponsePreference headers, entityDescriptor); } // Convert the insert into an update for the media link descriptor we just created // (note that the identity still needs to be fixed up on the resbox once // the response comes with the 'location' header; that happens during processing // of the response in SavedResource()) entityDescriptor.State = EntityStates.Modified; return(mediaRequest); }
public void SetRequestVersionShouldSetCorrectValueWhenHeaderCollectionContainsODataVersionGreaterThan40() { var headers = new HeaderCollection(); headers.SetHeader("OData-Version", "5.0.0"); headers.SetHeader("OData-MaxVersion", "5.0.0"); headers.SetRequestVersion(new Version(4, 0, 0, 1), new Version(5, 0, 0, 1)); headers.GetHeader("OData-Version").Should().Be("5.0.0"); headers.GetHeader("OData-MaxVersion").Should().Be("5.0"); }
private void TestSetRequestHeader(Action<DataServiceClientFormat> configureFormat, Action<DataServiceClientFormat, HeaderCollection> setRequestHeader, string expectedHeaderToSet, string initialHeaderValue, string expectedValueAfterSet) { var headers = new HeaderCollection(); configureFormat(this.v3TestSubject); headers.SetHeader(expectedHeaderToSet, initialHeaderValue); // Verify header has the expected initial value. This ensures that SetHeader above actually what we expect, and didn't use a default value or ignore the set request. headers.GetHeader(expectedHeaderToSet).Should().Be(initialHeaderValue); // Try to set header to new value and verify setRequestHeader(this.v3TestSubject, headers); headers.GetHeader(expectedHeaderToSet).Should().Be(expectedValueAfterSet); if (expectedHeaderToSet == "Content-Type") { if (!this.v3TestSubject.UsingAtom || expectedValueAfterSet == TestConstants.MimeApplicationJsonODataMinimalMetadata) { headers.GetHeader("OData-Version").Should().Be("4.0"); } else { headers.GetHeader("OData-Version").Should().BeNull(); } } if (expectedHeaderToSet == "Accept") { headers.GetHeader("Accept-Charset").Should().Be("UTF-8"); } }
public void SerializeEnity_EnumProperty() { MyEntity1 myEntity1 = new MyEntity1() { ID = 2, MyColorValue = MyColor.Yellow, MyFlagsColorValue = MyFlagsColor.Blue, ComplexValue1Value = new ComplexValue1() { MyColorValue = MyColor.Green, MyFlagsColorValue = MyFlagsColor.Red }, MyFlagsColorCollection1 = new List<MyFlagsColor>() { MyFlagsColor.Blue, MyFlagsColor.Red, MyFlagsColor.Red }, MyColorCollection = new List<MyColor?>() }; DataServiceContext dataServiceContext = new DataServiceContext(new Uri("http://www.odata.org/service.svc")); dataServiceContext.EnableAtom = true; dataServiceContext.Format.UseAtom(); dataServiceContext.AttachTo("MyEntitySet1", myEntity1); var requestInfo = new RequestInfo(dataServiceContext); var serializer = new Serializer(requestInfo); var headers = new HeaderCollection(); headers.SetHeader("Content-Type", "application/atom+xml;odata.metadata=minimal"); var clientModel = new ClientEdmModel(ODataProtocolVersion.V4); var entityDescriptor = new EntityDescriptor(clientModel); entityDescriptor.State = EntityStates.Added; entityDescriptor.Entity = myEntity1; var requestMessageArgs = new BuildingRequestEventArgs("POST", new Uri("http://www.foo.com/Northwind"), headers, entityDescriptor, HttpStack.Auto); var linkDescriptors = new LinkDescriptor[] { }; var odataRequestMessageWrapper = ODataRequestMessageWrapper.CreateRequestMessageWrapper(requestMessageArgs, requestInfo); serializer.WriteEntry(entityDescriptor, linkDescriptors, odataRequestMessageWrapper); // read result: MemoryStream stream = (MemoryStream)(odataRequestMessageWrapper.CachedRequestStream.Stream); stream.Position = 0; string payload = (new StreamReader(stream)).ReadToEnd(); payload = Regex.Replace(payload, "<updated>[^<]*</updated>", ""); payload.Should().Be( "<?xml version=\"1.0\" encoding=\"utf-8\"?><entry xmlns=\"http://www.w3.org/2005/Atom\" " + "xmlns:d=\"http://docs.oasis-open.org/odata/ns/data\" xmlns:m=\"http://docs.oasis-open.org/odata/ns/metadata\" " + "xmlns:georss=\"http://www.georss.org/georss\" xmlns:gml=\"http://www.opengis.net/gml\">" + "<id />" + "<title />" + //"<updated>2013-11-11T19:29:54Z</updated>" + "<author><name /></author>" + "<content type=\"application/xml\">" + "<m:properties>" + "<d:ComplexValue1Value>" + "<d:MyColorValue m:type=\"#AstoriaUnitTests.TDD.Tests.Client.ODataWriterWrapperUnitTests_MyColor\">Green</d:MyColorValue>" + "<d:MyFlagsColorValue m:type=\"#AstoriaUnitTests.TDD.Tests.Client.ODataWriterWrapperUnitTests_MyFlagsColor\">Red</d:MyFlagsColorValue>" + "<d:StringValue m:null=\"true\" />" + "</d:ComplexValue1Value>" + "<d:ID m:type=\"Int64\">2</d:ID>" + "<d:MyColorCollection />" + "<d:MyColorValue m:type=\"#AstoriaUnitTests.TDD.Tests.Client.ODataWriterWrapperUnitTests_MyColor\">Yellow</d:MyColorValue>" + "<d:MyFlagsColorCollection1>" + "<m:element m:type=\"#AstoriaUnitTests.TDD.Tests.Client.ODataWriterWrapperUnitTests+MyFlagsColor\">Blue</m:element>" + "<m:element m:type=\"#AstoriaUnitTests.TDD.Tests.Client.ODataWriterWrapperUnitTests+MyFlagsColor\">Red</m:element>" + "<m:element m:type=\"#AstoriaUnitTests.TDD.Tests.Client.ODataWriterWrapperUnitTests+MyFlagsColor\">Red</m:element>" + "</d:MyFlagsColorCollection1>" + "<d:MyFlagsColorValue m:type=\"#AstoriaUnitTests.TDD.Tests.Client.ODataWriterWrapperUnitTests_MyFlagsColor\">Blue</d:MyFlagsColorValue>" + "</m:properties>" + "</content>" + "</entry>"); }