public void QueryFailureUsingExecuteBatch() { DataServiceRequest <northwindClient.Customers> request = new DataServiceRequest <northwindClient.Customers>(new Uri(ctx.BaseUri.OriginalString + "/Customers('QUICK')")); DataServiceRequest <northwindClient.Customers> request1 = new DataServiceRequest <northwindClient.Customers>(new Uri(ctx.BaseUri.OriginalString + "/Customers('NONEXIST')")); DataServiceResponse response = ctx.ExecuteBatch(request, request1); Utils.IsBatchResponse(response); List <QueryOperationResponse> responses = new List <QueryOperationResponse>(); foreach (QueryOperationResponse queryResponse in response) { responses.Add(queryResponse); } Assert.IsTrue(responses.Count == 2, "expecting 2 responses in batch query"); // first one to succeed Utils.IsSuccessResponse(responses[0], HttpStatusCode.OK); Assert.IsTrue(responses[0].Query == request, "expecting the same request object"); // expecting the second one to fail Utils.IsErrorResponse(responses[1], HttpStatusCode.NotFound, true); Assert.IsTrue(responses[1].Query == request1, "expecting the same request object1"); }
bool GenerateSecurityToken() { if (securityToken != string.Empty) { return(true); } securityToken = string.Empty; Uri uri = new Uri("GenerateSecurityToken", UriKind.Relative); DataServiceRequest <string> loginRequest = new DataServiceRequest <string>(uri); var loginResponse = sldDataServiceContext.ExecuteBatch(loginRequest); QueryOperationResponse <string> queryOperationResponse = loginResponse.FirstOrDefault() as QueryOperationResponse <string>; if (queryOperationResponse == null) { return(false); } string token = queryOperationResponse.FirstOrDefault(); if (token == null) { return(false); } securityToken = token; return(true); }
public IEnumerable <T> ExecuteBatch <T>(DataServiceRequest request) { #if NETFRAMEWORK return(_context.ExecuteBatch(request) .Cast <QueryOperationResponse>() .SelectMany(o => o.Cast <T>())); #else throw new Exception("not ported"); #endif }
private bool LoginIntoSLD(string URL, string SLDUsername, string SLDPassword) { lock (this) { try { cookies = new CookieContainer(); sldDataServiceContext = new DataServiceContext(new Uri(URL)); sldDataServiceContext.SendingRequest += new EventHandler <SendingRequestEventArgs>(sldDataServiceContext_SendingRequest); sldDataServiceContext.IgnoreMissingProperties = true; string strLogonCmd = string.Empty; string tempUser = System.Web.HttpUtility.UrlEncode(SLDUsername, System.Text.Encoding.UTF8); string tempPassword = System.Web.HttpUtility.UrlEncode(SLDPassword, System.Text.Encoding.UTF8); strLogonCmd = string.Format("LogonByNamedUser?Account='{0}'&Password='******'", tempUser, tempPassword); Uri uri = new Uri(strLogonCmd, UriKind.Relative); DataServiceRequest <bool> loginRequest = new DataServiceRequest <bool>(uri); var loginResponse = sldDataServiceContext.ExecuteBatch(loginRequest); foreach (var response in loginResponse) { var queryOperationResponse = response as QueryOperationResponse <bool>; if (queryOperationResponse == null || !queryOperationResponse.FirstOrDefault()) { return(false); } } } catch { throw; } try { if (!GenerateSecurityToken()) { return(false); } } catch { throw; } return(true); } }
public static IEnumerable ExecuteQuery(DataServiceContext context, DataServiceRequest query, QueryMode queryMode) { bool isQuery = (null != (query as DataServiceQuery)); object result = null; switch (queryMode) { case QueryMode.GetEnumerator: // IEnumerable.GetEnumerator { if (isQuery) { result = query; } else { goto case QueryMode.ExecuteMethod; } break; } case QueryMode.ExecuteMethod: // DataServiceQuery<T>.Execute { if (isQuery) { result = UnitTestCodeGen.InvokeMethod(query.GetType(), "Execute", null, null, query, null); } else { result = UnitTestCodeGen.InvokeMethod(typeof(DataServiceContext), "Execute", TypesUri, new Type[] { query.ElementType }, context, query.RequestUri); } break; } case QueryMode.AsyncExecute: // DataServiceQuery<T>.BeginExecute and wait { if (isQuery) { IAsyncResult async = (IAsyncResult)UnitTestCodeGen.InvokeMethod(query.GetType(), "BeginExecute", TypesAsyncCallbackObject, null, query, new object[] { null, null }); if (!async.CompletedSynchronously) { Assert.IsTrue(async.AsyncWaitHandle.WaitOne(new TimeSpan(0, 0, TestConstants.MaxTestTimeout), false), "BeginExecute timeout"); } result = UnitTestCodeGen.InvokeMethod(query.GetType(), "EndExecute", TypesIAsyncResult, null, query, new object[] { async }); } else { IAsyncResult async = UnitTestCodeGen.InvokeMethod <DataServiceContext, IAsyncResult>("BeginExecute", TypesUriAsyncCallbackObject, new Type[] { query.ElementType }, context, query.RequestUri, null, null); if (!async.CompletedSynchronously) { Assert.IsTrue(async.AsyncWaitHandle.WaitOne(new TimeSpan(0, 0, TestConstants.MaxTestTimeout), false), "BeginExecute timeout"); } result = UnitTestCodeGen.InvokeMethod(typeof(DataServiceContext), "EndExecute", TypesIAsyncResult, new Type[] { query.ElementType }, context, async); } break; } case QueryMode.AsyncExecuteWithCallback: // DataServiceQuery<T>.BeginExecute with callback { ExecuteCallback callback = new ExecuteCallback(); IAsyncResult async; if (isQuery) { async = (IAsyncResult)UnitTestCodeGen.InvokeMethod(query.GetType(), "BeginExecute", TypesAsyncCallbackObject, null, query, new object[] { (AsyncCallback)callback.CallbackMethod, new object[] { query, context } }); } else { async = UnitTestCodeGen.InvokeMethod <DataServiceContext, IAsyncResult>("BeginExecute", TypesUriAsyncCallbackObject, new Type[] { query.ElementType }, context, new object[] { query.RequestUri, (AsyncCallback)callback.CallbackMethod, new object[] { query, context } }); } Assert.IsTrue(callback.Finished.WaitOne(new TimeSpan(0, 0, TestConstants.MaxTestTimeout), false), "Asyncallback timeout"); Assert.IsTrue(async.IsCompleted); if (null != callback.CallbackFailure) { Assert.IsNull(callback.CallbackResult, callback.CallbackFailure.ToString()); throw new Exception("failure in callback", callback.CallbackFailure); } result = callback.CallbackResult; Assert.IsNotNull(result); break; } case QueryMode.BatchExecute: // DataServiceContext.ExecuteBatch { LastUriRequest = query.RequestUri; int countBefore = context.Entities.Count + context.Links.Count; DataServiceResponse response = context.ExecuteBatch(query); int countAfter = context.Entities.Count + context.Links.Count; Assert.AreEqual(countBefore, countAfter, "should not materialize during ExecuteBatch"); result = HandleQueryResponse(response, query, context); } break; case QueryMode.BatchAsyncExecute: // DataServiceContext.BeginExecuteBatch and wait { int count = context.Entities.Count + context.Links.Count; LastUriRequest = query.RequestUri; IAsyncResult async = context.BeginExecuteBatch(null, null, query); if (!async.CompletedSynchronously) { Assert.IsTrue(async.AsyncWaitHandle.WaitOne(new TimeSpan(0, 0, TestConstants.MaxTestTimeout), false), "BeginExecuteBatch timeout"); } Assert.AreEqual(count, context.Entities.Count + context.Links.Count, "should not materialize until EndExecuteBatch"); DataServiceResponse response = context.EndExecuteBatch(async); result = HandleQueryResponse(response, query, context); break; } case QueryMode.BatchAsyncExecuteWithCallback: // DataServiceContext.BeginExecuteBatch with callback { ExecuteBatchCallback callback = new ExecuteBatchCallback(); LastUriRequest = query.RequestUri; IAsyncResult async = context.BeginExecuteBatch(callback.CallbackMethod, new object[] { query, context }, query); Assert.IsTrue(callback.Finished.WaitOne(new TimeSpan(0, 0, TestConstants.MaxTestTimeout), false), "Asyncallback timeout {0}", LastUriRequest); Assert.IsTrue(async.IsCompleted); if (null != callback.CallbackFailure) { Assert.IsNull(callback.CallbackResult, callback.CallbackFailure.ToString()); throw new Exception("failure in callback", callback.CallbackFailure); } result = callback.CallbackResult; Assert.IsNotNull(result); break; } default: Assert.Fail("shouldn't be here"); break; } return((IEnumerable)result); }
/// <summary> /// Extension method to perform sync/async version of DataServiceContext.ExecuteBatch dynamically /// </summary> /// <param name="context">The context to call execute batch on</param> /// <param name="continuation">The asynchronous continuation</param> /// <param name="async">A value indicating whether or not to use async API</param> /// <param name="queries">The queries to execute</param> /// <param name="onCompletion">A callback for when the call completes</param> public static void ExecuteBatch(this DataServiceContext context, IAsyncContinuation continuation, bool async, IEnumerable <DataServiceRequest> queries, Action <DataServiceResponse> onCompletion) { ExceptionUtilities.CheckArgumentNotNull(context, "context"); AsyncHelpers.InvokeSyncOrAsyncMethodCall <DataServiceResponse>(continuation, async, () => context.ExecuteBatch(queries.ToArray()), c => context.BeginExecuteBatch(c, null, queries.ToArray()), r => context.EndExecuteBatch(r), onCompletion); }
public IEnumerable <T> ExecuteBatch <T>(DataServiceRequest request) { return(_context.ExecuteBatch(request) .Cast <QueryOperationResponse>() .SelectMany(o => o.Cast <T>())); }
[Ignore] // Remove Atom // [TestCategory("Partition2"), TestMethod, Variation] public void BatchContentTypeTest() { var testCases = new BatchContentTypeTestCase[] { // Completely wrong content type new BatchContentTypeTestCase { ContentType = "text/plain", ExpectedErrorStatusCode = 400, ExpectedClientErrorMessage = DataServicesClientResourceUtil.GetString("Batch_ExpectedContentType", "text/plain") }, // Just type is correct, subtype is wrong new BatchContentTypeTestCase { ContentType = "multipart/text", ExpectedErrorStatusCode = 400, ExpectedClientErrorMessage = DataServicesClientResourceUtil.GetString("Batch_ExpectedContentType", "multipart/text") }, // No boundary - still wrong new BatchContentTypeTestCase { ContentType = "multipart/mixed", ExpectedErrorStatusCode = 400, ExpectedClientErrorMessage = ODataLibResourceUtil.GetString("MediaTypeUtils_BoundaryMustBeSpecifiedForBatchPayloads", "multipart/mixed", "boundary") }, // Some other parameter but no boundary new BatchContentTypeTestCase { ContentType = "multipart/mixed;param=value", ExpectedErrorStatusCode = 400, ExpectedClientErrorMessage = ODataLibResourceUtil.GetString("MediaTypeUtils_BoundaryMustBeSpecifiedForBatchPayloads", "multipart/mixed;param=value", "boundary") }, // Empty boundary - fails new BatchContentTypeTestCase { ContentType = "multipart/mixed;boundary=", ExpectedErrorStatusCode = 400, ExpectedClientErrorMessage = ODataLibResourceUtil.GetString("ValidationUtils_InvalidBatchBoundaryDelimiterLength", string.Empty, "70") }, new BatchContentTypeTestCase { ContentType = "multipart/mixed;boundary=;param=value", ExpectedErrorStatusCode = 400, ExpectedClientErrorMessage = ODataLibResourceUtil.GetString("ValidationUtils_InvalidBatchBoundaryDelimiterLength", string.Empty, "70") }, // Two boundary parameters - wrong new BatchContentTypeTestCase { ContentType = "multipart/mixed;boundary=one;boundary=two", ExpectedErrorStatusCode = 400, ExpectedClientErrorMessage = ODataLibResourceUtil.GetString("MediaTypeUtils_BoundaryMustBeSpecifiedForBatchPayloads", "multipart/mixed;boundary=one;boundary=two", "boundary") }, // Valid simple boundary new BatchContentTypeTestCase { ContentType = "multipart/mixed;boundary=batchboundary", PayloadBatchBoundary = "batchboundary" }, // Valid simple boundary - mimetype using different casing new BatchContentTypeTestCase { ContentType = "MultiPart/mIxed;boundary=batchboundary", PayloadBatchBoundary = "batchboundary" }, // Valid simple boundary - boundary parameter name different casing new BatchContentTypeTestCase { ContentType = "multipart/mixed;BounDary=batchboundary", PayloadBatchBoundary = "batchboundary" }, }; OpenWebDataServiceDefinition serverService = new OpenWebDataServiceDefinition() { DataServiceType = typeof(CustomDataContext) }; PlaybackServiceDefinition clientService = new PlaybackServiceDefinition(); TestUtil.RunCombinations( testCases, (testCase) => { using (TestWebRequest request = serverService.CreateForInProcess()) { request.RequestContentType = testCase.ContentType; request.SetRequestStreamAsText(string.Format( "--{0}\r\n" + "Content-Type: multipart/mixed; boundary=changesetresponse_00000001-0000-0000-0000-000000000000\r\n\r\n" + "--changesetresponse_00000001-0000-0000-0000-000000000000\r\n" + "--changesetresponse_00000001-0000-0000-0000-000000000000--\r\n" + "--{0}--\r\n", testCase.PayloadBatchBoundary)); request.RequestUriString = "/$batch"; request.HttpMethod = "POST"; Exception exception = TestUtil.RunCatching(request.SendRequest); int actualStatusCode = 0; if (exception != null) { actualStatusCode = request.ResponseStatusCode; } else { Assert.AreEqual(202, request.ResponseStatusCode, "Wrong response code for no-exception request."); BatchWebRequest batchResponse = BatchWebRequest.FromResponse(InMemoryWebRequest.FromResponse(request)); if (batchResponse.Parts.Count > 0) { actualStatusCode = batchResponse.Parts[0].ResponseStatusCode; if (actualStatusCode == 200) { actualStatusCode = 0; } } } Assert.AreEqual(testCase.ExpectedErrorStatusCode, actualStatusCode, "Wrong status code."); } using (TestWebRequest request = clientService.CreateForInProcessWcf()) { request.StartService(); clientService.ProcessRequestOverride = clientRequest => { var clientResponse = new InMemoryWebRequest(); clientResponse.SetResponseStatusCode(202); clientResponse.ResponseHeaders["Content-Type"] = testCase.ContentType; clientResponse.SetResponseStreamAsText(string.Format( "--{0}\r\n" + "Content-Type: application/http\r\n" + "Content-Transfer-Encoding: binary\r\n" + "\r\n" + "200 OK\r\n" + "<feed xmlns='http://www.w3.org/2005/Atom'/>\r\n" + "--{0}--\r\n", testCase.PayloadBatchBoundary)); return(clientResponse); }; DataServiceContext ctx = new DataServiceContext(request.ServiceRoot); Exception exception = TestUtil.RunCatching(() => ctx.ExecuteBatch(ctx.CreateQuery <Customer>("/Customers"))); if (exception != null) { exception = ((DataServiceRequestException)exception).InnerException; Assert.AreEqual(testCase.ExpectedClientErrorMessage, exception.Message, "Unexpected error message."); } else { Assert.IsNull(testCase.ExpectedClientErrorMessage, "Expected exception, but none was thrown."); } } }); }
public void NamedStreams_Projections_MergeInfoOptions() { // Make sure that based on the MergeOption, the value of the DataServiceStreamLink is updated TestUtil.RunCombinations( new EntityStates[] { EntityStates.Added, EntityStates.Deleted, EntityStates.Modified, EntityStates.Unchanged }, new MergeOption[] { MergeOption.AppendOnly, MergeOption.OverwriteChanges, MergeOption.PreserveChanges }, new int[] { -1, 0, 1 }, // -1 indicates less links, 0 means exact same number of links, 1 means some extra links UnitTestsUtil.BooleanValues, (entityState, mergeOption, extraLinks, useBatchMode) => { using (PlaybackService.OverridingPlayback.Restore()) { DataServiceContext context = new DataServiceContext(request.ServiceRoot, ODataProtocolVersion.V4); context.EnableAtom = true; context.Format.UseAtom(); context.MergeOption = mergeOption; // Populate the context with a single customer instance with 2 named streams string originalServiceRoot = "http://randomservice/Foo.svc"; string newServiceRoot = "http://randomservice1/Foo1.svc"; string payload = AtomParserTests.AnyEntry( id: NamedStreamTests.Id, editLink: request.ServiceRoot.AbsoluteUri + "/editLink/Customers(1)", properties: NamedStreamTests.Properties, links: NamedStreamTests.GetNamedStreamEditLink(originalServiceRoot + "/Customers(1)/EditLink/Thumbnail")); PlaybackService.OverridingPlayback.Value = PlaybackService.ConvertToPlaybackServicePayload(null, payload); DataServiceQuery<StreamType2> query = (DataServiceQuery<StreamType2>)context.CreateQuery<StreamType2>("Customers"); StreamType2 c = DataServiceContextTestUtil.CreateEntity<StreamType2>(context, "Customers", entityState, query); PlaybackService.OverridingPlayback.Value = null; string linksPayload = null; if (extraLinks == -1) { // send no links } else if (extraLinks == 0) { linksPayload = NamedStreamTests.GetNamedStreamEditLink(newServiceRoot + "/Customers(1)/EditLink/Thumbnail"); } else { linksPayload = NamedStreamTests.GetNamedStreamEditLink(newServiceRoot + "/Customers(1)/EditLink/Thumbnail") + NamedStreamTests.GetNamedStreamEditLink(newServiceRoot + "/Customers(1)/EditLink/Photo", name: "Photo"); } payload = AtomParserTests.AnyEntry( id: NamedStreamTests.Id, editLink: request.ServiceRoot.AbsoluteUri + "/editLink/Customers(1)", properties: NamedStreamTests.Properties, links: linksPayload); PlaybackService.OverridingPlayback.Value = PlaybackService.ConvertToPlaybackServicePayload(null, payload); if (useBatchMode) { PlaybackService.OverridingPlayback.Value = PlaybackService.ConvertToBatchQueryResponsePayload(PlaybackService.OverridingPlayback.Value); QueryOperationResponse<StreamType2> resp = (QueryOperationResponse<StreamType2>)context.ExecuteBatch((DataServiceRequest)query).Single(); c = resp.First(); } else { switch (extraLinks) { case -1: c = query.Select(s => new StreamType2() { ID = s.ID, Name = s.Name }).Single(); break; case 0: c = query.Select(s => new StreamType2() { ID = s.ID, Name = s.Name, Thumbnail = s.Thumbnail }).Single(); break; default: c = query.Select(s => new StreamType2() { ID = s.ID, Name = s.Name, Thumbnail = s.Thumbnail, Photo = s.Photo }).Single(); break; } } EntityDescriptor entityDescriptor = context.Entities.Where(ed => Object.ReferenceEquals(c, ed.Entity)).Single(); StreamDescriptor thumbnail = entityDescriptor.StreamDescriptors.Where(ns => ns.StreamLink.Name == "Thumbnail").SingleOrDefault(); //Assert.IsTrue(thumbnail == null || object.ReferenceEquals(thumbnail.EntityDescriptor, entityDescriptor), "StreamDescriptor.EntityDescriptor should point to the same instance of entity descriptor"); StreamDescriptor photo = entityDescriptor.StreamDescriptors.Where(ns => ns.StreamLink.Name == "Photo").SingleOrDefault(); //Assert.IsTrue(photo == null || object.ReferenceEquals(photo.EntityDescriptor, entityDescriptor), "StreamDescriptor.EntityDescriptor should point to the same instance of entity descriptor for photo"); string newEditLink = newServiceRoot + "/Customers(1)/EditLink/{0}"; string existingEditLink = originalServiceRoot + "/Customers(1)/EditLink/{0}"; if (entityState == EntityStates.Added) { Assert.AreEqual(2, context.Entities.Count, "since its in added state, we will get a new entity descriptor"); Assert.AreEqual(1 + extraLinks, entityDescriptor.StreamDescriptors.Count, "number of named streams was not as expected"); if (extraLinks == -1) { Assert.AreEqual(thumbnail, null, "photo must be null when extra links = -1 and state = added"); } else if (extraLinks == 0) { NamedStreamTests.VerifyNamedStreamInfo(thumbnail, null, newEditLink, null, null); } else if (extraLinks == 1) { NamedStreamTests.VerifyNamedStreamInfo(thumbnail, null, newEditLink, null, null); NamedStreamTests.VerifyNamedStreamInfo(photo, null, newEditLink, null, null); } } else if (mergeOption == MergeOption.OverwriteChanges || (mergeOption == MergeOption.PreserveChanges && (entityState == EntityStates.Deleted || entityState == EntityStates.Unchanged))) { Assert.AreEqual(1, context.Entities.Count, "since its not in added state, we will only have one entity descriptor"); int numOfNamedStreams = 1; if (extraLinks == 1) { numOfNamedStreams = 2; } Assert.AreEqual(numOfNamedStreams, entityDescriptor.StreamDescriptors.Count, "number of named streams was not as expected"); if (extraLinks == -1) { NamedStreamTests.VerifyNamedStreamInfo(thumbnail, null, existingEditLink, null, null); Assert.AreEqual(photo, null, "photo must be null when extra links = -1"); } else if (extraLinks == 0) { NamedStreamTests.VerifyNamedStreamInfo(thumbnail, null, newEditLink, null, null); Assert.AreEqual(photo, null, "photo must be null when extra links = 0"); } else if (extraLinks == 1) { NamedStreamTests.VerifyNamedStreamInfo(thumbnail, null, newEditLink, null, null); NamedStreamTests.VerifyNamedStreamInfo(photo, null, newEditLink, null, null); } } else { // no change should be made Assert.AreEqual(1, context.Entities.Count, "since its not in added state, we will only have one entity descriptor"); Assert.AreEqual(1, entityDescriptor.StreamDescriptors.Count, "number of named streams was not as expected"); NamedStreamTests.VerifyNamedStreamInfo(thumbnail, null, existingEditLink, null, null); Assert.AreEqual(photo, null, "photo must be null when extra links = 0"); } } }); }
public void VerifyEntityDescriptorMergeFunctionality() { // Make sure that based on the MergeOption, the right links are exposed in the entity descriptor TestUtil.RunCombinations( new EntityStates[] { EntityStates.Added, EntityStates.Deleted, EntityStates.Modified, EntityStates.Unchanged }, new MergeOption[] { MergeOption.AppendOnly, MergeOption.OverwriteChanges, MergeOption.PreserveChanges }, new int[] { -1, 0, 1 }, // -1 indicates less links, 0 means exact same number of links, 1 means some extra links UnitTestsUtil.BooleanValues, UnitTestsUtil.BooleanValues, (entityState, mergeOption, extraLinks, useBatchMode, returnETag) => { using (PlaybackService.OverridingPlayback.Restore()) { DataServiceContext context = new DataServiceContext(request.ServiceRoot, ODataProtocolVersion.V4); context.EnableAtom = true; context.MergeOption = mergeOption; // Populate the context with a single customer instance with 2 named streams string originalServiceRoot = "http://randomservice/Foo.svc"; string newServiceRoot = "http://randomservice1/Foo1.svc"; string payload = AtomParserTests.AnyEntry( id: Id, editLink: request.ServiceRoot.AbsoluteUri + "/editLink/Customers(1)", properties: Properties, links: GetNamedStreamSelfLink(originalServiceRoot + "/Customers(1)/SelfLink/Thumbnail", contentType: MediaContentType) + GetNamedStreamEditLink(originalServiceRoot + "/Customers(1)/EditLink/Thumbnail", contentType: MediaContentType, etag: MediaETag) + GetNamedStreamSelfLink(originalServiceRoot + "/Customers(1)/SelfLink/Photo", contentType: MediaContentType, name: "Photo") + GetNamedStreamEditLink(originalServiceRoot + "/Customers(1)/EditLink/Photo", contentType: MediaContentType, name: "Photo")); PlaybackService.OverridingPlayback.Value = PlaybackService.ConvertToPlaybackServicePayload(null, payload); Customer c = DataServiceContextTestUtil.CreateEntity<Customer>(context, "Customers", entityState); PlaybackService.OverridingPlayback.Value = null; string linksPayload = null; string newETag = returnETag ? MediaETag + 1 : null; if (extraLinks == -1) { linksPayload = GetNamedStreamSelfLink(newServiceRoot + "/Customers(1)/SelfLink/Thumbnail", contentType: MediaContentType) + GetNamedStreamEditLink(newServiceRoot + "/Customers(1)/EditLink/Thumbnail", contentType: MediaContentType, etag: newETag); } else if (extraLinks == 0) { linksPayload = GetNamedStreamSelfLink(newServiceRoot + "/Customers(1)/SelfLink/Thumbnail", contentType: MediaContentType) + GetNamedStreamEditLink(newServiceRoot + "/Customers(1)/EditLink/Thumbnail", contentType: MediaContentType, etag: newETag) + GetNamedStreamSelfLink(newServiceRoot + "/Customers(1)/SelfLink/Photo", contentType: MediaContentType, name: "Photo") + GetNamedStreamEditLink(newServiceRoot + "/Customers(1)/EditLink/Photo", contentType: MediaContentType, name: "Photo", etag: newETag); } else { linksPayload = GetNamedStreamSelfLink(newServiceRoot + "/Customers(1)/SelfLink/Thumbnail", contentType: MediaContentType) + GetNamedStreamEditLink(newServiceRoot + "/Customers(1)/EditLink/Thumbnail", contentType: MediaContentType, etag: newETag) + GetNamedStreamSelfLink(newServiceRoot + "/Customers(1)/SelfLink/Photo", contentType: MediaContentType, name: "Photo") + GetNamedStreamEditLink(newServiceRoot + "/Customers(1)/EditLink/Photo", contentType: MediaContentType, etag: newETag, name: "Photo") + GetNamedStreamSelfLink(newServiceRoot + "/Customers(1)/SelfLink/HighResolutionPhoto", contentType: MediaContentType, name: "HighResolutionPhoto") + GetNamedStreamEditLink(newServiceRoot + "/Customers(1)/EditLink/HighResolutionPhoto", contentType: MediaContentType, name: "HighResolutionPhoto", etag: newETag); } payload = AtomParserTests.AnyEntry( id: Id, editLink: request.ServiceRoot.AbsoluteUri + "/editLink/Customers(1)", properties: Properties, links: linksPayload); PlaybackService.OverridingPlayback.Value = PlaybackService.ConvertToPlaybackServicePayload(null, payload); if (useBatchMode) { PlaybackService.OverridingPlayback.Value = PlaybackService.ConvertToBatchQueryResponsePayload(PlaybackService.OverridingPlayback.Value); QueryOperationResponse<Customer> resp = (QueryOperationResponse<Customer>)context.ExecuteBatch(context.CreateQuery<Customer>("/Customers(123)")).Single(); c = resp.First(); } else { c = context.CreateQuery<Customer>("/Customers(123)").Execute().First(); } EntityDescriptor entityDescriptor = context.Entities.Where(ed => Object.ReferenceEquals(c, ed.Entity)).Single(); StreamDescriptor thumbnail = entityDescriptor.StreamDescriptors.Where(ns => ns.StreamLink.Name == "Thumbnail").SingleOrDefault(); StreamDescriptor photo = entityDescriptor.StreamDescriptors.Where(ns => ns.StreamLink.Name == "Photo").SingleOrDefault(); StreamDescriptor highResPhoto = entityDescriptor.StreamDescriptors.Where(ns => ns.StreamLink.Name == "HighResolutionPhoto").SingleOrDefault(); string newSelfLink = newServiceRoot + "/Customers(1)/SelfLink/{0}"; string newEditLink = newServiceRoot + "/Customers(1)/EditLink/{0}"; string existingSelfLink = originalServiceRoot + "/Customers(1)/SelfLink/{0}"; string existingEditLink = originalServiceRoot + "/Customers(1)/EditLink/{0}"; if (entityState == EntityStates.Added) { Assert.AreEqual(2, context.Entities.Count, "since its in added state, we will get a new entity descriptor"); Assert.AreEqual(2 + extraLinks, entityDescriptor.StreamDescriptors.Count, "number of named streams was not as expected"); VerifyNamedStreamInfo(thumbnail, newSelfLink, newEditLink, newETag, contentType: MediaContentType); if (extraLinks == -1) { Assert.AreEqual(photo, null, "photo must be null when extra links = -1 and state = added"); Assert.AreEqual(highResPhoto, null, "highResPhoto must be null when extra links = -1 and state = added"); } else if (extraLinks == 0) { VerifyNamedStreamInfo(photo, newSelfLink, newEditLink, newETag, contentType: MediaContentType); Assert.AreEqual(highResPhoto, null, "highResPhoto must be null when extra links = 0 and state = added"); } else if (extraLinks == 1) { VerifyNamedStreamInfo(photo, newSelfLink, newEditLink, newETag, contentType: MediaContentType); VerifyNamedStreamInfo(highResPhoto, newSelfLink, newEditLink, newETag, contentType: MediaContentType); } } else if (mergeOption == MergeOption.OverwriteChanges || (mergeOption == MergeOption.PreserveChanges && (entityState == EntityStates.Deleted || entityState == EntityStates.Unchanged))) { Assert.AreEqual(1, context.Entities.Count, "since its not in added state, we will only have one entity descriptor"); int numOfNamedStreams = 2; if (extraLinks == 1) { numOfNamedStreams = 3; } Assert.AreEqual(numOfNamedStreams, entityDescriptor.StreamDescriptors.Count, "number of named streams was not as expected"); VerifyNamedStreamInfo(thumbnail, newSelfLink, newEditLink, newETag ?? MediaETag, MediaContentType); if (extraLinks == -1) { VerifyNamedStreamInfo(photo, existingSelfLink, existingEditLink, null, MediaContentType); Assert.AreEqual(highResPhoto, null, "highResPhoto must be null when extra links = -1 and state = added"); } else if (extraLinks == 0) { VerifyNamedStreamInfo(photo, newSelfLink, newEditLink, newETag, MediaContentType); Assert.AreEqual(highResPhoto, null, "highResPhoto must be null when extra links = 0 and state = added"); } else if (extraLinks == 1) { VerifyNamedStreamInfo(photo, newSelfLink, newEditLink, newETag, MediaContentType); VerifyNamedStreamInfo(highResPhoto, newSelfLink, newEditLink, newETag, MediaContentType); } } else { // no change should be made Assert.AreEqual(1, context.Entities.Count, "since its not in added state, we will only have one entity descriptor"); Assert.AreEqual(2, entityDescriptor.StreamDescriptors.Count, "number of named streams was not as expected"); VerifyNamedStreamInfo(thumbnail, existingSelfLink, existingEditLink, MediaETag, MediaContentType); VerifyNamedStreamInfo(photo, existingSelfLink, existingEditLink, null, MediaContentType); Assert.AreEqual(highResPhoto, null, "highResPhoto must be null in AppendOnly"); } } }); }
public void NamedStreams_PropertyOnClientNotDataServiceStreamLink() { // [Client-ODataLib-Integration] Astoria client does not fail if the client and server stream property does not match TestUtil.RunCombinations( new MergeOption[] { MergeOption.AppendOnly, MergeOption.OverwriteChanges, MergeOption.PreserveChanges }, UnitTestsUtil.BooleanValues, (mergeOption, useBatchMode) => { using (PlaybackService.OverridingPlayback.Restore()) { DataServiceContext context = new DataServiceContext(request.ServiceRoot, ODataProtocolVersion.V4); context.EnableAtom = true; context.MergeOption = mergeOption; // Populate the context with a single customer instance with 2 named streams string originalServiceRoot = "http://randomservice/Foo.svc"; string payload = AtomParserTests.AnyEntry( id: NamedStreamTests.Id, editLink: request.ServiceRoot.AbsoluteUri + "/editLink/Customers(1)", properties: NamedStreamTests.Properties, links: NamedStreamTests.GetNamedStreamEditLink(originalServiceRoot + "/Customers(1)/EditLink/Thumbnail")); PlaybackService.OverridingPlayback.Value = PlaybackService.ConvertToPlaybackServicePayload(null, payload); DataServiceQuery<StreamTypeWithMismatchedStreamProperty> query = (DataServiceQuery<StreamTypeWithMismatchedStreamProperty>)context.CreateQuery<StreamTypeWithMismatchedStreamProperty>("Customers"); Exception exception = null; if (useBatchMode) { PlaybackService.OverridingPlayback.Value = PlaybackService.ConvertToBatchQueryResponsePayload(PlaybackService.OverridingPlayback.Value); var batchResponse = context.ExecuteBatch(query); foreach (var queryResponse in batchResponse.OfType<QueryOperationResponse<StreamTypeWithMismatchedStreamProperty>>()) { exception = TestUtil.RunCatching<InvalidOperationException>(() => { foreach (var entity in queryResponse) { Assert.Fail("Should not reach here"); } }); } } else { exception = TestUtil.RunCatching<InvalidOperationException>(() => query.ToList()); } Assert.IsNotNull(exception, "Expected error on mismatched client named stream link property type"); Assert.IsInstanceOfType(exception, typeof(InvalidOperationException), "Expected InvalidOperationException on mismatched client named stream link property type"); string expectedErrorMessage = ODataLibResourceUtil.GetString("ValidationUtils_MismatchPropertyKindForStreamProperty", "Thumbnail"); Assert.AreEqual(expectedErrorMessage, exception.Message); } }); }
public void BatchContentTypeTest() { var testCases = new BatchContentTypeTestCase[] { // Completely wrong content type new BatchContentTypeTestCase { ContentType = "text/plain", ExpectedErrorStatusCode = 400, ExpectedClientErrorMessage = DataServicesClientResourceUtil.GetString("Batch_ExpectedContentType", "text/plain") }, // Just type is correct, subtype is wrong new BatchContentTypeTestCase { ContentType = "multipart/text", ExpectedErrorStatusCode = 400, ExpectedClientErrorMessage = DataServicesClientResourceUtil.GetString("Batch_ExpectedContentType", "multipart/text") }, // No boundary - still wrong new BatchContentTypeTestCase { ContentType = "multipart/mixed", ExpectedErrorStatusCode = 400, ExpectedClientErrorMessage = ODataLibResourceUtil.GetString("MediaTypeUtils_BoundaryMustBeSpecifiedForBatchPayloads", "multipart/mixed", "boundary") }, // Some other parameter but no boundary new BatchContentTypeTestCase { ContentType = "multipart/mixed;param=value", ExpectedErrorStatusCode = 400, ExpectedClientErrorMessage = ODataLibResourceUtil.GetString("MediaTypeUtils_BoundaryMustBeSpecifiedForBatchPayloads", "multipart/mixed;param=value", "boundary") }, // Empty boundary - fails new BatchContentTypeTestCase { ContentType = "multipart/mixed;boundary=", ExpectedErrorStatusCode = 400, ExpectedClientErrorMessage = ODataLibResourceUtil.GetString("ValidationUtils_InvalidBatchBoundaryDelimiterLength", string.Empty, "70") }, new BatchContentTypeTestCase { ContentType = "multipart/mixed;boundary=;param=value", ExpectedErrorStatusCode = 400, ExpectedClientErrorMessage = ODataLibResourceUtil.GetString("ValidationUtils_InvalidBatchBoundaryDelimiterLength", string.Empty, "70") }, // Two boundary parameters - wrong new BatchContentTypeTestCase { ContentType = "multipart/mixed;boundary=one;boundary=two", ExpectedErrorStatusCode = 400, ExpectedClientErrorMessage = ODataLibResourceUtil.GetString("MediaTypeUtils_BoundaryMustBeSpecifiedForBatchPayloads", "multipart/mixed;boundary=one;boundary=two", "boundary") }, // Valid simple boundary new BatchContentTypeTestCase { ContentType = "multipart/mixed;boundary=batchboundary", PayloadBatchBoundary = "batchboundary" }, // Valid simple boundary - mimetype using different casing new BatchContentTypeTestCase { ContentType = "MultiPart/mIxed;boundary=batchboundary", PayloadBatchBoundary = "batchboundary" }, // Valid simple boundary - boundary parameter name different casing new BatchContentTypeTestCase { ContentType = "multipart/mixed;BounDary=batchboundary", PayloadBatchBoundary = "batchboundary" }, }; OpenWebDataServiceDefinition serverService = new OpenWebDataServiceDefinition() { DataServiceType = typeof(CustomDataContext) }; PlaybackServiceDefinition clientService = new PlaybackServiceDefinition(); TestUtil.RunCombinations( testCases, (testCase) => { using (TestWebRequest request = serverService.CreateForInProcess()) { request.RequestContentType = testCase.ContentType; request.SetRequestStreamAsText(string.Format( "--{0}\r\n" + "Content-Type: multipart/mixed; boundary=changesetresponse_00000001-0000-0000-0000-000000000000\r\n\r\n" + "--changesetresponse_00000001-0000-0000-0000-000000000000\r\n" + "--changesetresponse_00000001-0000-0000-0000-000000000000--\r\n" + "--{0}--\r\n", testCase.PayloadBatchBoundary)); request.RequestUriString = "/$batch"; request.HttpMethod = "POST"; Exception exception = TestUtil.RunCatching(request.SendRequest); int actualStatusCode = 0; if (exception != null) { actualStatusCode = request.ResponseStatusCode; } else { Assert.AreEqual(202, request.ResponseStatusCode, "Wrong response code for no-exception request."); BatchWebRequest batchResponse = BatchWebRequest.FromResponse(InMemoryWebRequest.FromResponse(request)); if (batchResponse.Parts.Count > 0) { actualStatusCode = batchResponse.Parts[0].ResponseStatusCode; if (actualStatusCode == 200) actualStatusCode = 0; } } Assert.AreEqual(testCase.ExpectedErrorStatusCode, actualStatusCode, "Wrong status code."); } using (TestWebRequest request = clientService.CreateForInProcessWcf()) { request.StartService(); clientService.ProcessRequestOverride = clientRequest => { var clientResponse = new InMemoryWebRequest(); clientResponse.SetResponseStatusCode(202); clientResponse.ResponseHeaders["Content-Type"] = testCase.ContentType; clientResponse.SetResponseStreamAsText(string.Format( "--{0}\r\n" + "Content-Type: application/http\r\n" + "Content-Transfer-Encoding: binary\r\n" + "\r\n" + "200 OK\r\n" + "<feed xmlns='http://www.w3.org/2005/Atom'/>\r\n" + "--{0}--\r\n", testCase.PayloadBatchBoundary)); return clientResponse; }; DataServiceContext ctx = new DataServiceContext(request.ServiceRoot); Exception exception = TestUtil.RunCatching(() => ctx.ExecuteBatch(ctx.CreateQuery<Customer>("/Customers"))); if (exception != null) { exception = ((DataServiceRequestException)exception).InnerException; Assert.AreEqual(testCase.ExpectedClientErrorMessage, exception.Message, "Unexpected error message."); } else { Assert.IsNull(testCase.ExpectedClientErrorMessage, "Expected exception, but none was thrown."); } } }); }