public void GetDomainMethod_NotFound()
        {
            DomainOperationEntry     returned;
            DomainServiceDescription description = DomainServiceDescription.GetDescription(typeof(DomainMethod_ValidProvider_MultipleMethods));

            // call with a domain method name that is not associated with the specified entityType. Verify null is returned
            returned = description.GetCustomMethod(typeof(City), "ProcessCounty");
            Assert.IsNull(returned);

            // call with non-entity type as entityType argument. Verify null is returned.
            returned = description.GetCustomMethod(typeof(string), "ProcessCity");
            Assert.IsNull(returned);
        }
        public async Task DomainService_CallSubmitDirectly()
        {
            DomainServiceDescription description      = DomainServiceDescription.GetDescription(typeof(DomainMethod_ValidProvider_MultipleMethods));
            List <ChangeSetEntry>    changeSetEntries = new List <ChangeSetEntry>();

            ChangeSetEntry processCityOperation = new ChangeSetEntry();

            processCityOperation.Entity = new City {
                Name = "Redmond", CountyName = "King", StateName = "WA"
            };
            processCityOperation.DomainOperationEntry = description.GetCustomMethod(typeof(City), "ProcessCity");
            processCityOperation.Operation            = DomainOperation.Update;
            processCityOperation.EntityActions        = new EntityActionCollection {
                { "ProcessCity", new object[] { new byte[] { byte.MaxValue, byte.MinValue, 123 } } }
            };
            changeSetEntries.Add(processCityOperation);

            ChangeSet changeset = new ChangeSet(changeSetEntries);
            DomainMethod_ValidProvider_MultipleMethods myTestProvider = ServerTestHelper.CreateInitializedDomainService <DomainMethod_ValidProvider_MultipleMethods>(DomainOperationType.Submit);
            await myTestProvider.SubmitAsync(changeset, CancellationToken.None);

            // check that the domain services have invoked the domain method correctly by checking the internal variables set
            Assert.AreEqual <string>("ProcessCity_", myTestProvider.Invoked);
            Assert.AreEqual <int>(3, myTestProvider.InputData.Length);
            Assert.AreEqual <byte>(123, myTestProvider.InputData[2]);
        }
        public void DomainService_CallSubmitWithMultipleInvocations()
        {
            DomainServiceDescription description      = DomainServiceDescription.GetDescription(typeof(DomainMethod_ValidProvider_MultipleMethods));
            List <ChangeSetEntry>    changeSetEntries = new List <ChangeSetEntry>();

            ChangeSetEntry processCountyOperation = new ChangeSetEntry();

            processCountyOperation.Id     = 1;
            processCountyOperation.Entity = new County {
                Name = "King", StateName = "WA"
            };
            processCountyOperation.DomainOperationEntry = description.GetCustomMethod(typeof(County), "ProcessCounty");
            processCountyOperation.Operation            = DomainOperation.Update;
            processCountyOperation.EntityActions        = new EntityActionCollection {
                { "ProcessCounty", null }
            };
            changeSetEntries.Add(processCountyOperation);

            ChangeSetEntry processCityOperation = new ChangeSetEntry();

            processCityOperation.Id     = 2;
            processCityOperation.Entity = new City {
                Name = "Redmond", CountyName = "King", StateName = "WA"
            };
            processCityOperation.DomainOperationEntry = description.GetCustomMethod(typeof(City), "ProcessCity");
            processCityOperation.Operation            = DomainOperation.Update;
            processCityOperation.EntityActions        = new EntityActionCollection {
                { "ProcessCity", new object[] { new byte[] { 123, 1 } } }
            };
            changeSetEntries.Add(processCityOperation);

            ChangeSet changeset = new ChangeSet(changeSetEntries);
            DomainMethod_ValidProvider_MultipleMethods myTestProvider = ServerTestHelper.CreateInitializedDomainService <DomainMethod_ValidProvider_MultipleMethods>(DomainOperationType.Submit);

            myTestProvider.Submit(changeset);

            // check that the domain services have invoked the domain method correctly by checking the internal variables set
            Assert.AreEqual <string>("ProcessCounty_ProcessCity_", myTestProvider.Invoked);
            Assert.AreEqual <int>(2, myTestProvider.InputData.Length);
        }
        public void GetDomainMethod_ExceptionCases()
        {
            DomainServiceDescription description = DomainServiceDescription.GetDescription(typeof(DomainMethod_ValidProvider_MultipleMethods));

            // call with null entityType, verify ArgumentNullEx
            ExceptionHelper.ExpectArgumentNullException(delegate
            {
                description.GetCustomMethod(null, "ProcessCity");
            }, "entityType");

            // call with empty domain method name. Verify ArgumentEx.
            ExceptionHelper.ExpectArgumentException(delegate
            {
                description.GetCustomMethod(typeof(City), "");
            }, string.Format(CultureInfo.CurrentCulture, Resource.DomainOperationEntry_ArgumentCannotBeNullOrEmpty, "methodName"));

            // call with null domain method name. Verify ArgumentEx.
            ExceptionHelper.ExpectArgumentException(delegate
            {
                description.GetCustomMethod(typeof(City), null);
            }, string.Format(CultureInfo.CurrentCulture, Resource.DomainOperationEntry_ArgumentCannotBeNullOrEmpty, "methodName"));
        }
        public void DomainServiceWithMultipleDomainMethods()
        {
            DomainServiceDescription description = DomainServiceDescription.GetDescription(typeof(DomainMethod_ValidProvider_MultipleMethods));

            Assert.IsNotNull(description);

            // verify GetDomainMethod returns the correct DomainOperationEntry
            DomainOperationEntry processCityMethod = description.GetCustomMethod(typeof(City), "ProcessCity");

            Assert.IsNotNull(processCityMethod);
            Assert.AreEqual(DomainOperation.Custom, processCityMethod.Operation);
            Assert.AreEqual <string>("ProcessCity", processCityMethod.Name);

            DomainOperationEntry processCountyMethod = description.GetCustomMethod(typeof(County), "ProcessCounty");

            Assert.IsNotNull(processCountyMethod);
            Assert.AreEqual(DomainOperation.Custom, processCityMethod.Operation);
            Assert.AreEqual <string>("ProcessCounty", processCountyMethod.Name);

            // retry with different casing. Verify null is returned since exact matching is needed.
            processCountyMethod = description.GetCustomMethod(typeof(County), "processcounty");
            Assert.IsNull(processCountyMethod);
        }
        public async Task Authorization_Custom_Authorization_On_Custom_Update()
        {
            // Specifically, the City data is marked so that no one can delete a Zip code
            // from WA unless their user name is WAGuy
            MockUser notWaGuy = new MockUser("notWAGuy");

            notWaGuy.IsAuthenticated = true;

            DomainServiceDescription serviceDescription = DomainServiceDescription.GetDescription(typeof(CityDomainService));
            City city = null;

            // Execute a query to get a City from WA
            using (CityDomainService cities = new CityDomainService())
            {
                DomainOperationEntry getCitiesQuery = serviceDescription.GetQueryMethod("GetCities");

                // Now prepare for a query to find a Zip in WA
                DomainServiceContext ctxt = new WcfDomainServiceContext(new MockDataService(notWaGuy), DomainOperationType.Query);
                cities.Initialize(ctxt);

                IEnumerable result = (await cities.QueryAsync <City>(new QueryDescription(getCitiesQuery), CancellationToken.None)).Result;

                city = result.OfType <City>().FirstOrDefault(z => z.StateName == "WA");
                Assert.IsNotNull(city, "Could not find a city in WA");
            }


            using (CityDomainService cities = new CityDomainService())
            {
                // Now prepare for a submit to invoke AssignCityZoneIfAuthorized as a named update method
                DomainServiceContext ctxt = new WcfDomainServiceContext(new MockDataService(notWaGuy), DomainOperationType.Submit);
                cities.Initialize(ctxt);

                // Prepare an attempt to delete this with a user whose name is not WAGuy
                // This should fail due to a custom auth attribute
                List <ChangeSetEntry> entries = new List <ChangeSetEntry>();

                ChangeSetEntry entry = new ChangeSetEntry();
                entry.DomainOperationEntry = serviceDescription.GetCustomMethod(typeof(City), "AssignCityZoneIfAuthorized");
                entry.EntityActions        = new EntityActionCollection {
                    { "AssignCityZoneIfAuthorized", new object[] { "SomeZone" } }
                };
                entry.Operation = DomainOperation.Update;
                entry.Entity    = city;
                entries.Add(entry);

                UnauthorizedAccessException exception = null;
                try
                {
                    await ChangeSetProcessor.ProcessAsync(cities, entries);
                }
                catch (UnauthorizedAccessException ex)
                {
                    exception = ex;
                }
                Assert.IsNotNull(exception, "Expected failure attempting to perform custom method on WA with inappropriate user name");
                Assert.AreEqual("Only one user is authorized to execute operation 'AssignCityZoneIfAuthorized', and it isn't you.", exception.Message);
            }

            // Now do that again but with a user who is WAGuy -- it should succeed
            using (CityDomainService cities = new CityDomainService())
            {
                MockUser waGuy = new MockUser("WAGuy");
                waGuy.IsAuthenticated = true;

                // Now prepare for a submit to invoke AssignCityZoneIfAuthorized as a named update method
                DomainServiceContext ctxt = new WcfDomainServiceContext(new MockDataService(waGuy), DomainOperationType.Submit);
                cities.Initialize(ctxt);

                // Prepare an attempt to delete this with a user whose name is not WAGuy
                // This should fail due to a custom auth attribute

                // Prepare a submit to call the AssignCityZoneIfAuthorized with an unauthorized user
                List <ChangeSetEntry> entries = new List <ChangeSetEntry>();

                ChangeSetEntry entry = new ChangeSetEntry();
                entry.DomainOperationEntry = serviceDescription.GetCustomMethod(typeof(City), "AssignCityZoneIfAuthorized");
                entry.EntityActions        = new EntityActionCollection {
                    { "AssignCityZoneIfAuthorized", new object[] { "SomeZone" } }
                };
                entry.Operation = DomainOperation.Update;
                entry.Entity    = city;
                entries.Add(entry);

                Exception exception = null;
                try
                {
                    await ChangeSetProcessor.ProcessAsync(cities, entries);
                }
                catch (UnauthorizedAccessException ex)
                {
                    exception = ex;
                }
                Assert.IsNull(exception, "Expected success attempting to delete a zip from WA with inappropriate user name");
            }
        }