public void Collection_ChangeInterceptors()
            {
                var metadata = CreateMetadataForXFeatureEntity();

                InterceptorServiceDefinition service = new InterceptorServiceDefinition()
                {
                    Metadata = metadata,
                    CreateDataSource = (m) => new DSPContext(),
                    Writable = true,
                    EnableChangeInterceptors = true
                };

                // client cases
                TestUtil.RunCombinations(new string[] { "POST", "PUT", "PATCH", "DELETE" }, new bool[] { false, true }, (httpMethod, batch) =>
                {
                    using (DSPResourceWithCollectionProperty.CollectionPropertiesResettable.Restore())
                    using (TestWebRequest request = service.CreateForInProcessWcf())
                    {
                        DSPResourceWithCollectionProperty.CollectionPropertiesResettable.Value = true;
                        request.Accept = "application/atom+xml,application/xml";
                        request.StartService();

                        DataServiceContext ctx = new DataServiceContext(request.ServiceRoot, ODataProtocolVersion.V4);
                        ctx.EnableAtom = true;
                        ctx.Format.UseAtom();

                        if (httpMethod != "POST")
                        {
                            service.EnableChangeInterceptors = false;
                            PopulateClientContextWithTestEntities(ctx);
                            service.EnableChangeInterceptors = true;
                        }

                        ctx.IgnoreResourceNotFoundException = true;

                        var resource = ctx.CreateQuery<XFeatureTestsEntity>("Entities").FirstOrDefault();
                        SaveChangesOptions saveOptions = batch ? SaveChangesOptions.BatchWithSingleChangeset : SaveChangesOptions.None;
                        switch (httpMethod)
                        {
                            case "POST":
                                resource = new XFeatureTestsEntity() { ID = 42, Strings = new List<string>(), Structs = new List<XFeatureTestsComplexType>() };
                                ctx.AddObject("Entities", resource);
                                break;
                            case "PUT":
                                saveOptions |= SaveChangesOptions.ReplaceOnUpdate;
                                ctx.UpdateObject(resource);
                                break;
                            case "PATCH":
                                ctx.UpdateObject(resource);
                                break;
                            case "DELETE":
                                ctx.DeleteObject(resource);
                                break;
                        }
                        ctx.SaveChanges(saveOptions);

                        Assert.AreEqual((int?)resource.ID, service.ChangeInterceptorCalledOnEntityId, "The change interceptor was not called or it was called with a wrong entity");
                        service.ChangeInterceptorCalledOnEntityId = null;
                    }
                });

                service.EnableChangeInterceptors = true;
                service.ChangeInterceptorCalledOnEntityId = null;

                // server cases (these operations can't be done using client API)
                TestUtil.RunCombinations(
                    new string[] { "Strings", "Structs" }, 
                    new string[] { UnitTestsUtil.MimeApplicationXml}, 
                    (collectionPropertyName, format) =>
                {
                    using (DSPResourceWithCollectionProperty.CollectionPropertiesResettable.Restore())
                    using (TestWebRequest request = service.CreateForInProcessWcf())
                    {
                        DSPResourceWithCollectionProperty.CollectionPropertiesResettable.Value = true;
                        request.StartService();

                        DataServiceContext ctx = new DataServiceContext(request.ServiceRoot, ODataProtocolVersion.V4);
                        ctx.EnableAtom = true;
                        ctx.Format.UseAtom();
                        service.EnableChangeInterceptors = false;
                        PopulateClientContextWithTestEntities(ctx);
                        service.EnableChangeInterceptors = true;

                        // Get the collection property payload
                        var payload = UnitTestsUtil.GetResponseAsAtomXLinq(request, "/Entities(1)/" + collectionPropertyName, format);

                        // And send a PUT with that payload back
                        request.HttpMethod = "PUT";
                        request.Accept = format;
                        request.RequestContentType = format;
                        request.RequestUriString = "/Entities(1)/" + collectionPropertyName;
                        request.SetRequestStreamAsText(payload.ToString());
                        request.SendRequest();

                        Assert.AreEqual((int?)1, service.ChangeInterceptorCalledOnEntityId, "The change interceptor was not called or it was called with a wrong entity");
                        service.ChangeInterceptorCalledOnEntityId = null;
                    }
                });
            }
 private void QueryInterceptors_VerifyQueryInterceptorCalled(InterceptorServiceDefinition service)
 {
     Assert.AreEqual(1, service.QueryInterceptorCallCount, "The query interceptor should have been called just once");
     service.QueryInterceptorCallCount = 0;
 }
 private void QueryInterceptors_VerifyClientEntity(int? entityId, XFeatureTestsEntity entity, InterceptorServiceDefinition service)
 {
     QueryInterceptors_VerifyQueryInterceptorCalled(service);
     if (entityId.HasValue)
     {
         Assert.AreEqual(entityId.Value, entity.ID, "The entity with ID 2 should have been filtered out.");
     }
     else
     {
         Assert.IsNull(entity, "No entity should have been returned.");
     }
 }
 private void QueryInterceptors_VerifyServerRequest(int statusCode, string uri, TestWebRequest request, InterceptorServiceDefinition service)
 {
     request.RequestUriString = uri;
     TestUtil.RunCatching(request.SendRequest);
     QueryInterceptors_VerifyQueryInterceptorCalled(service);
     Assert.AreEqual(statusCode, request.ResponseStatusCode, "Unexpected status code returned.");
 }
            public void Collection_QueryInterceptors()
            {
                var metadata = CreateMetadataForXFeatureEntity();

                InterceptorServiceDefinition service = new InterceptorServiceDefinition()
                {
                    Metadata = metadata,
                    CreateDataSource = (m) => new DSPContext(),
                    Writable = true
                };
                using (TestWebRequest request = service.CreateForInProcessWcf())
                {
                    request.StartService();

                    DataServiceContext ctx = new DataServiceContext(request.ServiceRoot, ODataProtocolVersion.V4);
                    ctx.EnableAtom = true;
                    ctx.Format.UseAtom();
                    PopulateClientContextWithTestEntities(ctx);

                    ctx.IgnoreResourceNotFoundException = true;

                    // Client test cases
                    QueryInterceptors_VerifyClientEntity(1, ctx.Execute<XFeatureTestsEntity>(new Uri("/Entities", UriKind.Relative)).AsEnumerable().First(), service);
                    QueryInterceptors_VerifyClientEntity(1, ctx.CreateQuery<XFeatureTestsEntity>("Entities").AsEnumerable().First(), service);
                    QueryInterceptors_VerifyClientEntity(1, ctx.CreateQuery<XFeatureTestsEntity>("Entities").OrderBy(e => e.ID).AsEnumerable().First(), service);
                    QueryInterceptors_VerifyClientEntity(1, ctx.CreateQuery<XFeatureTestsEntity>("Entities").Where(e => e.ID == 1).First(), service);
                    QueryInterceptors_VerifyClientEntity(null, ctx.CreateQuery<XFeatureTestsEntity>("Entities").Where(e => e.ID == 2).FirstOrDefault(), service);
                    // .Where(e => e.ID < 3) means "consider just first two entities". In this case we skip the first entity and the second is not there so null is expected
                    QueryInterceptors_VerifyClientEntity(null, ctx.CreateQuery<XFeatureTestsEntity>("Entities").Where(e => e.ID < 3).Skip(1).FirstOrDefault(), service);
                    QueryInterceptors_VerifyClientEntity(1, ctx.CreateQuery<XFeatureTestsEntity>("Entities").Select(e =>
                        new XFeatureTestsEntity { Strings = e.Strings }).AsEnumerable().First(), service);
                    QueryInterceptors_VerifyClientEntity(1, ctx.CreateQuery<XFeatureTestsEntity>("Entities").Select(e =>
                        new XFeatureTestsEntity { Structs = e.Structs }).AsEnumerable().First(), service);
                    QueryInterceptors_VerifyClientEntity(1, ctx.CreateQuery<XFeatureTestsEntity>("Entities").Select(e =>
                        new XFeatureTestsEntity { ID = e.ID }).AsEnumerable().First(), service);

                    // Server test cases (queries like this can't be executed through client API)
                    QueryInterceptors_VerifyServerRequest(200, "/Entities(1)/Strings", request, service);
                    QueryInterceptors_VerifyServerRequest(404, "/Entities(2)/Strings", request, service);
                    QueryInterceptors_VerifyServerRequest(200, "/Entities(1)/Structs", request, service);
                    QueryInterceptors_VerifyServerRequest(404, "/Entities(2)/Structs", request, service);
                }
            }