/// <summary>
        /// Validates the state transition.
        /// <para>
        /// For more information look at https://msdn.microsoft.com/en-us/library/microsoft.crm.sdk.messages.isvalidstatetransitionrequest(v=crm.8).aspx
        /// </para>
        /// </summary>
        /// <param name="recordId">Record Id</param>
        /// <param name="entityLogicalName">Record's entity logical name</param>
        /// <param name="newStateCode"></param>
        /// <param name="newStatusCode"></param>
        /// <returns>
        /// Returns <c>true</c> if is valid. (<see cref="IsValidStateTransitionResponse.IsValid"/>)
        /// </returns>
        public bool Validate(Guid recordId, string entityLogicalName, string newStateCode, int newStatusCode)
        {
            ExceptionThrow.IfGuidEmpty(recordId, "id");
            ExceptionThrow.IfNullOrEmpty(entityLogicalName, "entityLogicalName");

            List <string> supportedEntityList = new List <string>()
            {
                "incident",
                "msdyn_postalbum",
                "msdyn_postconfig",
                "msdyn_postruleconfig",
                "msdyn_wallsavedquery",
                "msdyn_wallsavedqueryusersettings",
                "opportunity"
            };

            if (!supportedEntityList.Contains(entityLogicalName.ToLower().Trim()))
            {
                ExceptionThrow.IfNotExpectedValue(entityLogicalName, "entityLogicalName", "", string.Format("{0} is not supported for this operation. For more information look at https://msdn.microsoft.com/en-us/library/microsoft.crm.sdk.messages.isvalidstatetransitionrequest(v=crm.8).aspx", entityLogicalName));
            }

            IsValidStateTransitionRequest request = new IsValidStateTransitionRequest()
            {
                Entity    = new EntityReference(entityLogicalName, recordId),
                NewState  = newStateCode.Trim(),
                NewStatus = newStatusCode
            };

            IsValidStateTransitionResponse response = (IsValidStateTransitionResponse)this.OrganizationService.Execute(request);

            return(response.IsValid);
        }
        internal override OrganizationResponse Execute(OrganizationRequest orgRequest, EntityReference userRef)
        {
            var request = MakeRequest <IsValidStateTransitionRequest>(orgRequest);

            if (request.Entity == null)
            {
                throw new FaultException("Required field 'Entity' is missing");
            }
            if (request.NewState == null)
            {
                throw new FaultException("Required field 'NewState' is missing");
            }

            var entityMetadata = metadata.EntityMetadata.GetMetadata(request.Entity.LogicalName);

            var row = db.GetDbRowOrNull(request.Entity);

            if (row == null)
            {
                throw new FaultException($"{request.Entity.LogicalName} With Id = {request.Entity.Id} Does Not Exist");
            }

            var prevStatusCode = row.GetColumn <int>("statuscode");
            var prevStateCode  = row.GetColumn <int>("statecode");

            var stateOption = Utility.GetStateOptionMetadataFromInvariantName(request.NewState, entityMetadata);

            CheckEnforceStateTransitions(request, entityMetadata, stateOption);
            var statusOptionMeta = Utility.GetStatusOptionMetadata(entityMetadata);

            if (!statusOptionMeta.Any(o => (o as StatusOptionMetadata).State == prevStateCode &&
                                      o.Value == prevStatusCode &&
                                      stateOption.Value != prevStateCode))
            {
                throw new FaultException($"{request.NewStatus} is not a valid status code on {request.Entity.LogicalName} with Id {request.Entity.Id}.");
            }

            var prevValueOptionMeta = statusOptionMeta.FirstOrDefault(o => o.Value == prevStatusCode) as StatusOptionMetadata;

            var transitions = prevValueOptionMeta.TransitionData;
            var resp        = new IsValidStateTransitionResponse();

            if (transitions != null && transitions != "")
            {
                if (Utility.IsValidStatusTransition(transitions, request.NewStatus))
                {
                    resp.Results["IsValid"] = true;
                }
                else
                {
                    throw new FaultException($"{request.NewStatus} is not a valid status code for state code {request.Entity.LogicalName}State.{request.NewState} on {request.Entity.LogicalName} with Id {request.Entity.Id}.");
                }
            }
            else
            {
                resp.Results["IsValid"] = null;
            }
            return(resp);
        }
Example #3
0
        /// <summary>
        /// This method first connects to the Organization service. Afterwards, a
        /// case is created. The IsValidStateTransition is used to test if a state change
        /// is valid. The case is closed, re-opened and then closed with SetState.
        /// </summary>
        /// <param name="serverConfig">Contains server connection information.</param>
        /// <param name="promptforDelete">When True, the user will be prompted to delete all
        /// created entities.</param>
        public void Run(ServerConnection.Configuration serverConfig,
                        bool promptForDelete)
        {
            using (_serviceProxy = new OrganizationServiceProxy(serverConfig.OrganizationUri, serverConfig.HomeRealmUri, serverConfig.Credentials, serverConfig.DeviceCredentials))
            {
                // This statement is required to enable early-bound type support.
                _serviceProxy.EnableProxyTypes();

                //Create the Contact and Incident required for this sample.
                CreateRequiredRecords();

                //<snippetIsValidStateTransition>
                // Create an EntityReference to represent an open case
                EntityReference caseReference = new EntityReference()
                {
                    LogicalName = Incident.EntityLogicalName,
                    Id          = _caseIncidentId
                };

                IsValidStateTransitionRequest checkState =
                    new IsValidStateTransitionRequest();

                // Set the transition request to an open case
                checkState.Entity = caseReference;

                // Check to see if a new state of "resolved" and
                // a new status of "problem solved" are valid
                checkState.NewState  = IncidentState.Resolved.ToString();
                checkState.NewStatus = (int)incident_statuscode.ProblemSolved;

                // Execute the request
                IsValidStateTransitionResponse checkStateResponse =
                    (IsValidStateTransitionResponse)_serviceProxy.Execute(checkState);
                //</snippetIsValidStateTransition>

                // Handle the response
                if (checkStateResponse.IsValid)
                {
                    String changeAnswer = "y"; // default to "y" unless prompting for delete
                    if (promptForDelete)
                    {
                        // The case can be closed
                        Console.WriteLine("Validate State Request returned that the case " +
                                          "can be closed.");
                        Console.Write("\nDo you want to change the record state? " +
                                      "(y/n) [y]: ");
                        changeAnswer = Console.ReadLine();
                        Console.WriteLine();
                    }

                    if (changeAnswer.StartsWith("y") || changeAnswer.StartsWith("Y") ||
                        changeAnswer == String.Empty)
                    {
                        // Call function to change the incident to the closed state
                        CloseIncident(caseReference);
                        // Re-open the incident and change its state
                        SetState(caseReference);
                    }
                }
                else
                {
                    // The case cannot be closed
                    Console.WriteLine("Validate State Request returned that the " +
                                      "change is not valid.");
                }

                DeleteRequiredRecords(promptForDelete);
            }
        }