Пример #1
0
        public IEnumerable <ServiceAction> GetActions(Type typeWithActions)
        {
            var actionInfos = ActionFinder.GetActionsFromType(typeWithActions).ToArray();

            foreach (var actionInfo in actionInfos)
            {
                var method = actionInfo.ActionMethod;

                string       actionName  = method.Name;
                ResourceType returnType  = method.ReturnType == typeof(void) ? null: GetResourceType(method.ReturnType);
                ResourceSet  resourceSet = GetResourceSet(returnType);

                var           parameters = GetParameters(method, actionInfo.Binding != OperationParameterBindingKind.Never);
                ServiceAction action     = new ServiceAction(
                    actionName,
                    returnType,
                    resourceSet,
                    actionInfo.Binding,
                    parameters
                    );

                // Store the method associated with this Action.
                action.CustomState = actionInfo;
                action.SetReadOnly();
                yield return(action);
            }
        }
Пример #2
0
        public OperationSerializerTests()
        {
            ResourceType intType = ResourceType.GetPrimitiveResourceType(typeof(int));

            var customerType = new ResourceType(typeof(object), ResourceTypeKind.EntityType, null, "FQ.NS", "Customer", false);

            customerType.CanReflectOnInstanceType = false;
            customerType.AddProperty(new ResourceProperty("Id", ResourcePropertyKind.Primitive | ResourcePropertyKind.Key, intType)
            {
                CanReflectOnInstanceTypeProperty = false
            });
            customerType.SetReadOnly();

            var operation = new ServiceAction("Action", intType, OperationParameterBindingKind.Sometimes, new[] { new ServiceActionParameter("P1", customerType), new ServiceActionParameter("P2", intType) }, null);

            operation.SetReadOnly();
            this.baseTypeOperation = new OperationWrapper(operation);

            var bestCustomerType = new ResourceType(typeof(object), ResourceTypeKind.EntityType, customerType, "FQ.NS", "BestCustomer", false);

            bestCustomerType.SetReadOnly();

            operation = new ServiceAction("Action", intType, OperationParameterBindingKind.Sometimes, new[] { new ServiceActionParameter("P1", bestCustomerType) }, null);
            operation.SetReadOnly();
            this.derivedTypeOperation = new OperationWrapper(operation);

            operation = new ServiceAction("Unambiguous", intType, OperationParameterBindingKind.Sometimes, new[] { new ServiceActionParameter("P1", customerType) }, null);
            operation.SetReadOnly();
            this.unambiguousOperation = new OperationWrapper(operation);

            this.entityToSerialize = EntityToSerialize.CreateFromExplicitValues(new object(), bestCustomerType, new TestSerializedEntityKey("http://odata.org/Service.svc/Customers(0)/", bestCustomerType.FullName));

            this.testSubject = CreateOperationSerializer(AlwaysAdvertiseActions);
        }
        public void MetadataProviderModelShouldGoDirectlyToProviderWhenLookingUpOperationsInSelect()
        {
            var entityType           = CreateResourceTypeWithKeyProperties("Id");
            var derivedType          = CreateDerivedType("Derived", entityType);
            var veryDerivedType      = CreateDerivedType("VeryDerived", derivedType);
            var unrelatedDerivedType = CreateDerivedType("UnrelatedDerived", entityType);
            var action1 = new ServiceAction("Action", null, null, OperationParameterBindingKind.Always, new[] { new ServiceActionParameter("p1", entityType) });
            var action2 = new ServiceAction("Action", null, null, OperationParameterBindingKind.Always, new[] { new ServiceActionParameter("p1", derivedType) });
            var actionWithDifferentName = new ServiceAction("Action2", null, null, OperationParameterBindingKind.Always, new[] { new ServiceActionParameter("p1", derivedType) });
            var action3 = new ServiceAction("Action", null, null, OperationParameterBindingKind.Always, new[] { new ServiceActionParameter("p1", veryDerivedType) });

            action1.SetReadOnly();
            action2.SetReadOnly();
            actionWithDifferentName.SetReadOnly();
            action3.SetReadOnly();
            int calls          = 0;
            var actionProvider = new TestActionProvider
            {
                GetByBindingTypeCallback = (o, t) =>
                {
                    calls++;

                    if (t == entityType)
                    {
                        return(new[] { action1 });
                    }

                    if (t == derivedType)
                    {
                        return(new[] { action2, actionWithDifferentName });
                    }

                    if (t == veryDerivedType)
                    {
                        return(new[] { action3 });
                    }

                    t.Should().NotBeSameAs(unrelatedDerivedType);
                    return(null);
                }
            };

            var metadataProvider = new DataServiceProviderSimulator();

            metadataProvider.AddResourceType(entityType);
            metadataProvider.AddResourceType(derivedType);
            metadataProvider.AddResourceType(veryDerivedType);
            metadataProvider.AddResourceType(unrelatedDerivedType);
            var model      = CreateMetadataProviderEdmModel(metadataProvider, actionProvider);
            var schemaType = (IEdmEntityType)model.EnsureSchemaType(derivedType);
            var result     = model.FindDeclaredBoundOperations(schemaType).FilterByName(false, "Action");

            result.Should().NotBeNull();
            result.Should().HaveCount(3);
            result.Should().OnlyContain(f => f.Name == "Action");
            calls.Should().Be(3);
        }
            public IEnumerable <ServiceAction> GetServiceActionsByBindingParameterType(DataServiceOperationContext operationContext, ResourceType bindingParameterType)
            {
                var collectionType = bindingParameterType as EntityCollectionResourceType;

                if (collectionType != null && collectionType.ItemType.Name == "EntityTypeWithStringKey")
                {
                    var serviceAction = new ServiceAction("Action", ResourceType.GetPrimitiveResourceType(typeof(string)), OperationParameterBindingKind.Always, new[] { new ServiceActionParameter("param1", bindingParameterType) }, null);
                    serviceAction.SetReadOnly();
                    yield return(serviceAction);
                }
            }
Пример #5
0
        /// <summary>
        /// Adds an service action to the internal dictionary.
        /// </summary>
        /// <param name="action">Service action to add.</param>
        /// <param name="method">Service action method.</param>
        /// <param name="instance">Instance object where the service action method is to be invoked.</param>
        /// <returns></returns>
        private ServiceAction AddServiceAction(ServiceAction action, MethodInfo method, object instance)
        {
            if (method != null)
            {
                action.CustomState = new DSPServiceActionInfo {
                    Instance = instance, Method = method
                };
            }

            action.SetReadOnly();
            this.serviceActions.Add(action.Name, action);
            return(action);
        }
            public bool TryResolveServiceAction(DataServiceOperationContext operationContext, string serviceActionName, out ServiceAction serviceAction)
            {
                if (serviceActionName == "Action")
                {
                    IDataServiceMetadataProvider metadataProvider = (IDataServiceMetadataProvider)operationContext.GetService(typeof(IDataServiceMetadataProvider));
                    ResourceType resourceType;
                    metadataProvider.TryResolveResourceType(EntityTypeNameWithStringKey, out resourceType);
                    Assert.IsNotNull(resourceType);
                    serviceAction = new ServiceAction("Action", ResourceType.GetPrimitiveResourceType(typeof(string)), OperationParameterBindingKind.Always, new[] { new ServiceActionParameter("param1", ResourceType.GetEntityCollectionResourceType(resourceType)) }, null);
                    serviceAction.SetReadOnly();
                    return(true);
                }

                serviceAction = null;
                return(false);
            }
        public OperationLinkBuilderTests()
        {
            ResourceType intType = ResourceType.GetPrimitiveResourceType(typeof(int));

            var customerType = new ResourceType(typeof(object), ResourceTypeKind.EntityType, null, "FQ.NS", "Customer", false);

            customerType.CanReflectOnInstanceType = false;
            customerType.AddProperty(new ResourceProperty("Id", ResourcePropertyKind.Primitive | ResourcePropertyKind.Key, intType)
            {
                CanReflectOnInstanceTypeProperty = false
            });
            customerType.SetReadOnly();

            var operation = new ServiceAction("Action", intType, OperationParameterBindingKind.Sometimes, new[] { new ServiceActionParameter("P1", customerType), new ServiceActionParameter("P2", intType) }, null);

            operation.SetReadOnly();
            this.operationWithParameters = new OperationWrapper(operation);

            var typeWithEscapedName = new ResourceType(typeof(object), ResourceTypeKind.ComplexType, null, "FQ NS", "+ /", false);

            typeWithEscapedName.CanReflectOnInstanceType = false;
            typeWithEscapedName.AddProperty(new ResourceProperty("Number", ResourcePropertyKind.Primitive, intType)
            {
                CanReflectOnInstanceTypeProperty = false
            });
            typeWithEscapedName.SetReadOnly();

            operation = new ServiceAction("Action", intType, OperationParameterBindingKind.Sometimes, new[] { new ServiceActionParameter("P1", customerType), new ServiceActionParameter("P2", typeWithEscapedName) }, null);
            operation.SetReadOnly();
            this.operationWithEscapedParameter = new OperationWrapper(operation);

            var bestCustomerType = new ResourceType(typeof(object), ResourceTypeKind.EntityType, customerType, "FQ.NS", "BestCustomer", false);

            bestCustomerType.SetReadOnly();

            operation = new ServiceAction("Action", intType, OperationParameterBindingKind.Sometimes, new[] { new ServiceActionParameter("P1", customerType) }, null);
            operation.SetReadOnly();
            this.operationBoundToBaseType = new OperationWrapper(operation);

            this.entityToSerialize = EntityToSerialize.CreateFromExplicitValues(new object(), bestCustomerType, new TestSerializedEntityKey("http://odata.org/Service.svc/Customers/", bestCustomerType.FullName));

            var metadataUri = new Uri("http://odata.org/Service.svc/$metadata");

            this.testSubject = new OperationLinkBuilder("MyContainer", metadataUri);
        }
Пример #8
0
    static ActionProvider()
    {
        ServiceAction movieRateAction = new ServiceAction(
            "Action1",                                             // name of the action
            ResourceType.GetPrimitiveResourceType(typeof(string)), // no return type i.e. void
            null,                                                  // no return type means we don’t need to know the ResourceSet so use null.
            OperationParameterBindingKind.Never,
            new ServiceActionParameter[] {
            new ServiceActionParameter("val", ResourceType.GetPrimitiveResourceType(typeof(string)))
        }
            );

        movieRateAction.SetReadOnly();
        actions = new List <ServiceAction>()
        {
            movieRateAction
        };
    }
        public void ActionProviderWrapperShouldFailOnDuplicateOverload()
        {
            var duplicateAction1 = new ServiceAction("Duplicate", ResourceType.GetPrimitiveResourceType(typeof(string)), OperationParameterBindingKind.Sometimes, new[] { new ServiceActionParameter("p1", this.entityType), new ServiceActionParameter("p2", ResourceType.GetPrimitiveResourceType(typeof(string))) }, null);

            duplicateAction1.SetReadOnly();
            var duplicateAction2 = new ServiceAction("Duplicate", ResourceType.GetPrimitiveResourceType(typeof(int)), OperationParameterBindingKind.Sometimes, new[] { new ServiceActionParameter("p1", this.entityType) }, null);

            duplicateAction2.SetReadOnly();
            this.provider.ActionProvider = new TestActionProvider
            {
                GetByBindingTypeCallback = (context, rt) => new[] { duplicateAction1, duplicateAction2 },
            };

            Action getByParameterType = () => this.actionProvider.GetServiceActionsByBindingParameterType(this.entityType);

            getByParameterType.ShouldThrow <DataServiceException>()
            .WithMessage(ErrorStrings.DataServiceActionProviderWrapper_DuplicateAction("Duplicate"))
            .And.StatusCode.Should().Be(500);
        }
        public void ActionProviderWrapperShouldGatherAllActionsForAllTypesInSet()
        {
            var derivedType = new ResourceType(typeof(object), ResourceTypeKind.EntityType, this.entityType, "Fake", "Derived", false);

            derivedType.SetReadOnly();
            var action1 = new ServiceAction("Duplicate", ResourceType.GetPrimitiveResourceType(typeof(string)), OperationParameterBindingKind.Sometimes, new[] { new ServiceActionParameter("p1", this.entityType), new ServiceActionParameter("p2", ResourceType.GetPrimitiveResourceType(typeof(string))) }, null);

            action1.SetReadOnly();
            var action2 = new ServiceAction("Duplicate", ResourceType.GetPrimitiveResourceType(typeof(int)), OperationParameterBindingKind.Sometimes, new[] { new ServiceActionParameter("p1", derivedType) }, null);

            action2.SetReadOnly();
            this.provider.ActionProvider = new TestActionProvider
            {
                GetByBindingTypeCallback = (context, rt) => rt == this.entityType ? new[] { action1 } : new[] { action2 },
            };

            this.provider.GetAllTypesInHierarchyFunc = set => new[] { this.entityType, derivedType };

            this.actionProvider.GetActionsBoundToAnyTypeInHierarchy(this.entityType).Select(wrapper => wrapper.ServiceAction).Should().BeEquivalentTo(action1, action2);
        }
Пример #11
0
        public void DataServiceProviderWrapperShouldFailOnMultipleActionsWithSameNameAndBindingType()
        {
            var entityType = new ResourceType(typeof(object), ResourceTypeKind.EntityType, null, "Fake.NS", "Type", false)
            {
                CanReflectOnInstanceType = false
            };

            entityType.AddProperty(new ResourceProperty("Id", ResourcePropertyKind.Key | ResourcePropertyKind.Primitive, ResourceType.GetPrimitiveResourceType(typeof(int)))
            {
                CanReflectOnInstanceTypeProperty = false
            });
            entityType.SetReadOnly();

            var resourceSet = new ResourceSet("MyEntitySet", entityType);

            resourceSet.SetReadOnly();

            ResourceType stringType       = ResourceType.GetPrimitiveResourceType(typeof(string));
            var          duplicateAction1 = new ServiceAction("Duplicate", stringType, OperationParameterBindingKind.Always, new[] { new ServiceActionParameter("p1", entityType), new ServiceActionParameter("p2", stringType) }, null);

            duplicateAction1.SetReadOnly();
            var duplicateAction2 = new ServiceAction("Duplicate", ResourceType.GetPrimitiveResourceType(typeof(int)), OperationParameterBindingKind.Sometimes, new[] { new ServiceActionParameter("p1", entityType) }, null);

            duplicateAction2.SetReadOnly();

            var actionProvider = new TestActionProvider
            {
                GetServiceActionsCallback = ctx => new[] { duplicateAction1, duplicateAction2 }
            };

            var providerWrapper = CreateProviderWrapper(actionProvider, p => p.AddResourceSet(resourceSet));

            Action getVisibleOperations = () => providerWrapper.GetVisibleOperations().ToList();

            getVisibleOperations.ShouldThrow <DataServiceException>()
            .WithMessage(ErrorStrings.DataServiceActionProviderWrapper_DuplicateAction("Duplicate"))
            .And.StatusCode.Should().Be(500);
        }
Пример #12
0
        public void DataServiceProviderWrapperShouldFailOnMultipleActionsWithSameNameAndNoBindingType()
        {
            ResourceType stringType       = ResourceType.GetPrimitiveResourceType(typeof(string));
            var          duplicateAction1 = new ServiceAction("Duplicate", stringType, OperationParameterBindingKind.Never, new[] { new ServiceActionParameter("p1", stringType) }, null);

            duplicateAction1.SetReadOnly();
            var duplicateAction2 = new ServiceAction("Duplicate", ResourceType.GetPrimitiveResourceType(typeof(int)), OperationParameterBindingKind.Never, new ServiceActionParameter[0], null);

            duplicateAction2.SetReadOnly();

            var actionProvider = new TestActionProvider
            {
                GetServiceActionsCallback = ctx => new[] { duplicateAction1, duplicateAction2 }
            };

            var providerWrapper = CreateProviderWrapper(actionProvider);

            Action getVisibleOperations = () => providerWrapper.GetVisibleOperations().ToList();

            getVisibleOperations.ShouldThrow <DataServiceException>()
            .WithMessage(ErrorStrings.DataServiceActionProviderWrapper_DuplicateAction("Duplicate"))
            .And.StatusCode.Should().Be(500);
        }
Пример #13
0
        protected override IEnumerable <ServiceAction> LoadServiceActions(IDataServiceMetadataProvider dataServiceMetadataProvider)
        {
            ResourceType productType;

            dataServiceMetadataProvider.TryResolveResourceType("Microsoft.Test.OData.Services.AstoriaDefaultService.Product", out productType);

            ResourceType orderLineType;

            dataServiceMetadataProvider.TryResolveResourceType("Microsoft.Test.OData.Services.AstoriaDefaultService.OrderLine", out orderLineType);

            ResourceType personType;

            dataServiceMetadataProvider.TryResolveResourceType("Microsoft.Test.OData.Services.AstoriaDefaultService.Person", out personType);

            ResourceType employeeType;

            dataServiceMetadataProvider.TryResolveResourceType("Microsoft.Test.OData.Services.AstoriaDefaultService.Employee", out employeeType);

            ResourceType specialEmployeeType;

            dataServiceMetadataProvider.TryResolveResourceType("Microsoft.Test.OData.Services.AstoriaDefaultService.SpecialEmployee", out specialEmployeeType);

            ResourceType contractorType;

            dataServiceMetadataProvider.TryResolveResourceType("Microsoft.Test.OData.Services.AstoriaDefaultService.Contractor", out contractorType);

            //
            // actions with the same name and non-related binding types
            //
            var RetrieveProductActionProduct = new ServiceAction(
                "RetrieveProduct",
                ResourceType.GetPrimitiveResourceType(typeof(int)),
                null,
                OperationParameterBindingKind.Sometimes,
                new[]
            {
                new ServiceActionParameter("product", productType),
            });

            RetrieveProductActionProduct.SetReadOnly();
            yield return(RetrieveProductActionProduct);

            var RetrieveProductActionOrderLine = new ServiceAction(
                "RetrieveProduct",
                ResourceType.GetPrimitiveResourceType(typeof(int)),
                null,
                OperationParameterBindingKind.Sometimes,
                new[]
            {
                new ServiceActionParameter("orderLine", orderLineType),
            });

            RetrieveProductActionOrderLine.SetReadOnly();
            yield return(RetrieveProductActionOrderLine);

            //
            // Collection bound actions with the same name
            //
            var increaseSalariesActionEmployee = new ServiceAction(
                "IncreaseSalaries",
                null,
                null,
                OperationParameterBindingKind.Sometimes,
                new[]
            {
                new ServiceActionParameter("employees", ResourceType.GetEntityCollectionResourceType(employeeType)),
                new ServiceActionParameter("n", ResourceType.GetPrimitiveResourceType(typeof(int))),
            });

            increaseSalariesActionEmployee.SetReadOnly();
            yield return(increaseSalariesActionEmployee);

            var increaseSalariesActionSpecialEmployee = new ServiceAction(
                "IncreaseSalaries",
                null,
                null,
                OperationParameterBindingKind.Sometimes,
                new[]
            {
                new ServiceActionParameter("specialEmployees", ResourceType.GetEntityCollectionResourceType(specialEmployeeType)),
                new ServiceActionParameter("n", ResourceType.GetPrimitiveResourceType(typeof(int))),
            });

            increaseSalariesActionSpecialEmployee.SetReadOnly();
            yield return(increaseSalariesActionSpecialEmployee);

            //
            // Actions with the same name and base/derived type binding parameters
            //
            var updatePersonInfoAction = new ServiceAction(
                "UpdatePersonInfo",
                null,
                null,
                OperationParameterBindingKind.Never,
                null);

            updatePersonInfoAction.SetReadOnly();
            yield return(updatePersonInfoAction);

            var updatePersonInfoActionPerson = new ServiceAction(
                "UpdatePersonInfo",
                null,
                null,
                OperationParameterBindingKind.Sometimes,
                new[]
            {
                new ServiceActionParameter("person", personType),
            });

            updatePersonInfoActionPerson.SetReadOnly();
            yield return(updatePersonInfoActionPerson);

            var updatePersonInfoActionEmployee = new ServiceAction(
                "UpdatePersonInfo",
                null,
                null,
                OperationParameterBindingKind.Sometimes,
                new[]
            {
                new ServiceActionParameter("employee", employeeType),
            });

            updatePersonInfoActionEmployee.SetReadOnly();
            yield return(updatePersonInfoActionEmployee);

            var updatePersonInfoActionSpecialEmployee = new ServiceAction(
                "UpdatePersonInfo",
                null,
                null,
                OperationParameterBindingKind.Sometimes,
                new[]
            {
                new ServiceActionParameter("specialEmployee", specialEmployeeType),
            });

            updatePersonInfoActionSpecialEmployee.SetReadOnly();
            yield return(updatePersonInfoActionSpecialEmployee);

            var updatePersonInfoActionContractor = new ServiceAction(
                "UpdatePersonInfo",
                null,
                null,
                OperationParameterBindingKind.Always,
                new[]
            {
                new ServiceActionParameter("contractor", contractorType),
            });

            updatePersonInfoActionContractor.SetReadOnly();
            yield return(updatePersonInfoActionContractor);

            //
            // Actions with the same name, base/derived type binding parameters, different non-binding parameters
            //
            var increaseEmployeeSalaryActionEmployee = new ServiceAction(
                "IncreaseEmployeeSalary",
                ResourceType.GetPrimitiveResourceType(typeof(bool)),
                null,
                OperationParameterBindingKind.Sometimes,
                new[]
            {
                new ServiceActionParameter("employee", employeeType),
                new ServiceActionParameter("n", ResourceType.GetPrimitiveResourceType(typeof(int))),
            });

            increaseEmployeeSalaryActionEmployee.SetReadOnly();
            yield return(increaseEmployeeSalaryActionEmployee);

            var increaseEmployeeSalaryActionSpecialEmployee = new ServiceAction(
                "IncreaseEmployeeSalary",
                ResourceType.GetPrimitiveResourceType(typeof(int)),
                null,
                OperationParameterBindingKind.Sometimes,
                new[]
            {
                new ServiceActionParameter("specialEmployee", specialEmployeeType),
            });

            increaseEmployeeSalaryActionSpecialEmployee.SetReadOnly();
            yield return(increaseEmployeeSalaryActionSpecialEmployee);
        }
        protected override IEnumerable <ServiceAction> LoadServiceActions(IDataServiceMetadataProvider dataServiceMetadataProvider)
        {
            ResourceType employeeType;

            dataServiceMetadataProvider.TryResolveResourceType("Microsoft.Test.OData.Services.AstoriaDefaultService.Employee", out employeeType);
            ResourceType computerDetailType;

            dataServiceMetadataProvider.TryResolveResourceType("Microsoft.Test.OData.Services.AstoriaDefaultService.ComputerDetail", out computerDetailType);
            ResourceType computerType;

            dataServiceMetadataProvider.TryResolveResourceType("Microsoft.Test.OData.Services.AstoriaDefaultService.Computer", out computerType);
            ResourceType customerType;

            dataServiceMetadataProvider.TryResolveResourceType("Microsoft.Test.OData.Services.AstoriaDefaultService.Customer", out customerType);
            ResourceType auditInfoType;

            dataServiceMetadataProvider.TryResolveResourceType("Microsoft.Test.OData.Services.AstoriaDefaultService.AuditInfo", out auditInfoType);
            ResourceSet computerSet;

            dataServiceMetadataProvider.TryResolveResourceSet("Computer", out computerSet);
            var increaseSalaryAction = new ServiceAction(
                "IncreaseSalaries",
                null,
                null,
                OperationParameterBindingKind.Always,
                new[]
            {
                new ServiceActionParameter("employees", ResourceType.GetEntityCollectionResourceType(employeeType)),
                new ServiceActionParameter("n", ResourceType.GetPrimitiveResourceType(typeof(int))),
            });

            increaseSalaryAction.SetReadOnly();

            yield return(increaseSalaryAction);

            var sackEmployeeAction = new ServiceAction(
                "Sack",
                null,
                null,
                OperationParameterBindingKind.Always,
                new[]
            {
                new ServiceActionParameter("employee", employeeType),
            });

            sackEmployeeAction.SetReadOnly();

            yield return(sackEmployeeAction);

            var getComputerAction = new ServiceAction(
                "GetComputer",
                computerType,
                OperationParameterBindingKind.Always,
                new[]
            {
                new ServiceActionParameter("computer", computerType)
            },
                new ResourceSetPathExpression("computer"));

            getComputerAction.SetReadOnly();

            yield return(getComputerAction);

            var changeCustomerAuditInfoAction = new ServiceAction(
                "ChangeCustomerAuditInfo",
                null,
                null,
                OperationParameterBindingKind.Always,
                new[]
            {
                new ServiceActionParameter("customer", customerType),
                new ServiceActionParameter("auditInfo", auditInfoType),
            });

            changeCustomerAuditInfoAction.SetReadOnly();

            yield return(changeCustomerAuditInfoAction);

            var resetComputerDetailsSpecificationsAction = new ServiceAction(
                "ResetComputerDetailsSpecifications",
                null,
                null,
                OperationParameterBindingKind.Always,
                new[]
            {
                new ServiceActionParameter("computerDetail", computerDetailType),
                new ServiceActionParameter("specifications", ResourceType.GetCollectionResourceType(ResourceType.GetPrimitiveResourceType(typeof(string)))),
                new ServiceActionParameter("purchaseTime", ResourceType.GetPrimitiveResourceType(typeof(DateTimeOffset)))
            });

            resetComputerDetailsSpecificationsAction.SetReadOnly();

            yield return(resetComputerDetailsSpecificationsAction);
        }