public void JsonBatchBinaryContentTypeTest()
        {
            ODataJsonBatchPayloadTestCase testCase = new ODataJsonBatchPayloadTestCase
            {
                Description    = "Batch request of binary body and headers in different order, or content-type header is an empty string.",
                RequestPayload = @"
                        {
                          ""requests"": [
                            {
                              ""body"": ""__ENCODED_BINARY_CONTENT__"",
                              ""headers"": {
                                ""Content-Type"": ""my-binary/*"",
                                ""OData-Version"": ""4.0""
                              },
                              ""method"": ""POST"",
                              ""url"": ""http://odata.org/test/Users HTTP/1.1"",

                              ""id"": ""r1""
                            },
                            {
                              ""id"": ""r2"",
                              ""headers"": {
                                ""Content-Type"": ""my-other-binary/*""
                              },
                              ""method"": ""POST"",
                              ""url"": ""http://odata.org/test/Users HTTP/1.1"",
                              ""body"": ""__ENCODED_BINARY_CONTENT__""
                            },
                            {
                              ""id"": ""r3"",
                              ""headers"": {
                                ""Content-Type"": """"
                              },
                              ""method"": ""POST"",
                              ""url"": ""http://odata.org/test/Users HTTP/1.1"",
                              ""body"": ""__ENCODED_BINARY_CONTENT__""
                            }
                          ]
                        }",
                RequestMessageDependsOnIdVerifier = null,
                ContentTypeVerifier = (message, offset) =>
                                      VerifyOperationRequestMessage(
                    message,
                    offset,
                    new string[] { "r1", "r2", "r3" },
                    new int[] { 2, 1, 1 })
            };

            testCase.PopulateEncodedContent("__ENCODED_BINARY_CONTENT__", JsonLightUtils.GetBase64UrlEncodedString(this.binarySampleBytes));

            ServiceProcessBatchRequest(testCase, ODataVersion.V4);
        }
        private void ServiceProcessBatchRequest(ODataJsonBatchPayloadTestCase testCase, ODataVersion version)
        {
            string requestPayload = testCase.RequestPayload;

            ODataJsonBatchPayloadTestCase.ValidateContentType requestMessageContentTypeVerifier = testCase.ContentTypeVerifier;

            IODataRequestMessage requestMessage = new InMemoryMessage()
            {
                Stream = new MemoryStream(Encoding.ASCII.GetBytes(requestPayload))
            };

            requestMessage.SetHeader("Content-Type", batchContentTypeApplicationJson);

            using (ODataMessageReader messageReader =
                       new ODataMessageReader(requestMessage, new ODataMessageReaderSettings()
            {
                Version = version, BaseUri = new Uri("http://odata.org")
            }, this.edmModel))
            {
                ODataBatchReader batchReader = messageReader.CreateODataBatchReader();

                int operationIdx = 0;
                while (batchReader.Read())
                {
                    switch (batchReader.State)
                    {
                    case ODataBatchReaderState.Operation:
                        ODataBatchOperationRequestMessage operationMessage = batchReader.CreateOperationRequestMessage();

                        // Verify operation message content type processing.
                        requestMessageContentTypeVerifier.Invoke(operationMessage, operationIdx);

                        operationIdx++;
                        break;
                    }
                }
            }
        }
        public void JsonBatchDontEncodeColonInAbsoluteQueryString()
        {
            string requestUrl = @"http://test/Users?$filter=" +
                                "Name eq 'Smith' OR Name eq 'Smith' OR Name eq 'Smith' OR Name eq 'Smith' OR Name eq 'Smith' OR Name eq 'Smith' OR Name eq 'Smith' OR " +
                                "Name eq 'Smith' OR Name eq 'Smith' OR Name eq 'Smith' OR Name eq 'Smith' OR Name eq 'Smith' OR Name eq 'Smith' OR Name eq 'Smith' OR " +
                                "Name eq 'Smith' OR Name eq 'Smith' OR Name eq 'Smith' OR Name eq 'Smith' OR Name eq 'Smith' OR Name eq 'Smith' OR Name eq 'Smith' OR " +
                                "Name eq 'Smith' OR Name eq 'Smith' OR Name eq 'Smith' OR Name eq 'Smith' OR Name eq 'Smith' OR Name eq 'Smith' OR Name eq 'Smith' OR " +
                                "Name eq 'Smith' OR Name eq 'Smith' OR Name eq 'Smith' OR Name eq 'Smith' OR Name eq 'Smith' OR Name eq 'Smith' OR Name eq 'Smith' OR " +
                                "Name eq 'Smith' OR Name eq 'Smith' OR Name eq 'Smith' OR Name eq 'Smith' OR Name eq 'Smith' OR Name eq 'Smith' OR Name eq 'Smith' OR " +
                                "Name eq 'Smith' OR Name eq 'Smith' OR Name eq 'Smith' OR Name eq 'Smith' OR Name eq 'Smith' OR Name eq 'Smith' OR Name eq 'Smith' OR " +
                                "Name eq 'Smith' OR Name eq 'Smith' OR Name eq 'Smith' OR Name eq 'Smith' OR Name eq 'Smith' OR Name eq 'Smith' OR Name eq 'Smith' OR " +
                                "BirthDate eq 2020-02-01T12:00:00Z";
            string batchRequest = @"
                        {
                          ""requests"": [
                            {
                              ""id"": ""r1"",
                              ""method"": ""GET"",
                              ""url"": ""{requestUrl}"",
                              ""headers"": {
                                ""Content-Type"": ""application/json; odata.metadata=minimal; odata.streaming=true"",
                                ""OData-Version"": ""4.0""
                              }
                            }
                          ]
                        }";

            ODataJsonBatchPayloadTestCase testCase = new ODataJsonBatchPayloadTestCase
            {
                Description    = "Batch request of Json body and headers in different order.",
                RequestPayload = batchRequest.Replace("{requestUrl}", requestUrl),
                RequestMessageDependsOnIdVerifier = null,
                ContentTypeVerifier =
                    (message, offset) => { Assert.Equal(requestUrl, message.Url.OriginalString); }
            };

            ServiceProcessBatchRequest(testCase, ODataVersion.V4);
        }
        public void JsonBatchTextualContentTypeTest()
        {
            ODataJsonBatchPayloadTestCase testCase = new ODataJsonBatchPayloadTestCase
            {
                Description    = "Batch request of Textual body and headers in different order.",
                RequestPayload = @"
                        {
                          ""requests"": [
                            {
                              ""body"": ""__ENCODED_TEXTUAL_CONTENT__"",
                              ""method"": ""POST"",
                              ""url"": ""http://odata.org/test/Users HTTP/1.1"",
                              ""headers"": {
                                ""Content-Type"": ""text/plain"",
                                ""OData-Version"": ""4.0""
                              },
                              ""id"": ""r1""
                            },
                            {
                              ""id"": ""r2"",
                              ""method"": ""POST"",
                              ""url"": ""http://odata.org/test/Users HTTP/1.1"",
                              ""headers"": {
                                ""Content-Type"": ""text/*; odata.metadata=minimal""
                              },
                              ""body"": ""__ENCODED_TEXTUAL_CONTENT__""
                            }
                          ]
                        }",
                RequestMessageDependsOnIdVerifier = null,
                ContentTypeVerifier =
                    (message, offset) => VerifyOperationRequestMessage(message, offset, new string[] { "r1", "r2" }, new int[] { 2, 1 })
            };

            testCase.PopulateEncodedContent("__ENCODED_TEXTUAL_CONTENT__", JsonLightUtils.GetJsonEncodedString(textualSampleString));

            ServiceProcessBatchRequest(testCase, ODataVersion.V4);
        }
        public void JsonBatchJsonContentTypeTest()
        {
            ODataJsonBatchPayloadTestCase testCase = new ODataJsonBatchPayloadTestCase
            {
                Description    = "Batch request of Json body and headers in different order.",
                RequestPayload = @"
                        {
                          ""requests"": [
                            {
                              ""id"": ""r1"",
                              ""body"": {""userPrincipalName"": ""*****@*****.**"", ""givenName"": ""Jon6"", ""surname"": ""Doe""},
                              ""method"": ""POST"",
                              ""url"": ""http://odata.org/test/Users HTTP/1.1"",
                              ""headers"": {
                                ""Content-Type"": ""application/json; odata.metadata=minimal; odata.streaming=true"",
                                ""OData-Version"": ""4.0""
                              }
                            },
                            {
                              ""id"": ""r2"",
                              ""method"": ""POST"",
                              ""url"": ""http://odata.org/test/Users HTTP/1.1"",
                              ""headers"": {
                                ""Content-Type"": ""application/json; odata.metadata=minimal""
                              },
                              ""body"": {""userPrincipalName"": ""*****@*****.**""}
                            }
                          ]
                        }",
                RequestMessageDependsOnIdVerifier = null,
                ContentTypeVerifier =
                    (message, offset) => VerifyOperationRequestMessage(message, offset, new string[] { "r1", "r2" }, new int[] { 2, 1 })
            };

            ServiceProcessBatchRequest(testCase, ODataVersion.V4);
        }
        private byte[] ServiceReadSingletonBatchRequestAndWriterBatchResponse(ODataJsonBatchPayloadTestCase testCase, ODataVersion version)
        {
            string requestPayload = testCase.RequestPayload;
            Action <ODataBatchOperationRequestMessage, IList <string> > requestOpMessageVerifier = testCase.RequestMessageDependsOnIdVerifier;

            IODataRequestMessage requestMessage = new InMemoryMessage()
            {
                Stream = new MemoryStream(Encoding.ASCII.GetBytes(requestPayload))
            };

            requestMessage.SetHeader("Content-Type", batchContentTypeApplicationJson);

            MemoryStream responseStream = new MemoryStream();

            using (ODataMessageReader messageReader =
                       new ODataMessageReader(requestMessage, new ODataMessageReaderSettings()
            {
                Version = version
            }, this.edmModel))
            {
                IODataResponseMessage responseMessage = new InMemoryMessage {
                    Stream = responseStream
                };

                // Client is expected to receive the response message in the same format as that is used in the request sent.
                responseMessage.SetHeader("Content-Type", batchContentTypeApplicationJson);

                ODataMessageWriterSettings settings = new ODataMessageWriterSettings()
                {
                    Version = version
                };
                settings.SetServiceDocumentUri(new Uri(serviceDocumentUri));

                ODataMessageWriter messageWriter = new ODataMessageWriter(responseMessage, settings, null);
                int operationIdx = 0;

                ODataBatchWriter batchWriter = messageWriter.CreateODataBatchWriter();
                batchWriter.WriteStartBatch();

                ODataBatchReader batchReader = messageReader.CreateODataBatchReader();
                while (batchReader.Read())
                {
                    switch (batchReader.State)
                    {
                    case ODataBatchReaderState.Operation:
                        // Encountered an operation (either top-level or in a change set)
                        ODataBatchOperationRequestMessage operationMessage = batchReader.CreateOperationRequestMessage();

                        // Verify operation message if applicable.
                        requestOpMessageVerifier?.Invoke(operationMessage, testCase.ListOfDependsOnIds.ElementAt(operationIdx));

                        if (operationMessage.Method == "POST")
                        {
                            ODataBatchOperationResponseMessage response = batchWriter.CreateOperationResponseMessage(operationMessage.ContentId);
                            response.StatusCode = 201;
                            response.SetHeader("Content-Type", batchContentTypeApplicationJson);
                        }
                        else if (operationMessage.Method == "GET")
                        {
                            ODataBatchOperationResponseMessage response = batchWriter.CreateOperationResponseMessage(operationMessage.ContentId);
                            response.StatusCode = 200;
                            response.SetHeader("Content-Type", batchContentTypeApplicationJson);

                            using (ODataMessageWriter operationMessageWriter = new ODataMessageWriter(response, settings, this.edmModel))
                            {
                                ODataWriter entryWriter = operationMessageWriter.CreateODataResourceWriter(this.singleton,
                                                                                                           this.userType);
                                ODataResource entry = new ODataResource()
                                {
                                    TypeName   = "NS.User",
                                    Properties =
                                        new[]
                                    {
                                        new ODataProperty()
                                        {
                                            Name = "UserPrincipalName", Value = "*****@*****.**"
                                        },
                                        new ODataProperty()
                                        {
                                            Name = "GivenName", Value = "Jon"
                                        }
                                    }
                                };
                                entryWriter.WriteStart(entry);
                                entryWriter.WriteEnd();
                            }
                        }

                        operationIdx++;
                        break;

                    case ODataBatchReaderState.ChangesetStart:
                        batchWriter.WriteStartChangeset();
                        break;

                    case ODataBatchReaderState.ChangesetEnd:
                        batchWriter.WriteEndChangeset();
                        break;
                    }
                }

                batchWriter.WriteEndBatch();
            }

            responseStream.Position = 0;
            return(responseStream.ToArray());
        }