예제 #1
0
        internal static IEnhancedOrgService GetConnection(string connectionString, bool noCache = false)
        {
            if (noCache)
            {
                ResetCache(connectionString);
            }

            var memKey = $"{ConnCacheMemKey}_{connectionString}";

            lock (lockObj)
            {
                try
                {
                    var service = CacheHelpers.GetFromMemCache <IEnhancedOrgService>(memKey);

                    if (service != null)
                    {
                        return(service);
                    }

                    Status.Update($"Creating connection to CRM ... ");
                    Status.Update($"Connection String:" + $" '{CrmHelpers.SecureConnectionString(connectionString)}'.");

                    service = EnhancedServiceHelper.GetCachingPoolingService(
                        new ServiceParams
                    {
                        ConnectionParams =
                            new ConnectionParams
                        {
                            ConnectionString = connectionString
                        },
                        PoolParams =
                            new PoolParams
                        {
                            PoolSize       = 5,
                            DequeueTimeout = TimeSpan.FromSeconds(20)
                        },
                        CachingParams = new CachingParams {
                            CacheScope = CacheScope.Service
                        },
                        OperationHistoryLimit = 1
                    });
                    CacheHelpers.AddToMemCache(memKey, service, TimeSpan.MaxValue);

                    Status.Update($"Created connection.");

                    return(service);
                }
                catch
                {
                    CacheHelpers.RemoveFromMemCache(memKey);
                    throw;
                }
            }
        }
        protected override void ExecuteLogic()
        {
            codeActivity.CloneTemplateArg.Require(nameof(codeActivity.CloneTemplateArg));

            var templateRef      = executionContext.GetValue(codeActivity.CloneTemplateArg);
            var recordEntityName = executionContext.GetValue(codeActivity.RecordEntityNameArg);
            var recordId         = executionContext.GetValue(codeActivity.RecordIdArg);

            recordEntityName.RequireNotEmpty(nameof(recordEntityName));
            recordId.RequireNotEmpty(nameof(recordId));

            log.Log($"Retrieving the template record '{templateRef.Id}' ...");
            var template =
                service.Retrieve(templateRef.LogicalName, templateRef.Id, new ColumnSet(true)).ToEntity <CloneRecordTemplate>();

            log.Log($"Retrieved the template record '{templateRef.Id}':'{template.Name}'.");
            CrmHelpers.LogAttributeValues(template.Attributes, template, log);

            Entity record = null;

            string[] fields = null;

            if (template.Fields.IsNotEmpty())
            {
                fields = template.Fields.Split(',');
                log.Log($"Retrieving the record '{recordEntityName}':'{recordId}' ...");
                record = service.Retrieve(recordEntityName, Guid.Parse(recordId), new ColumnSet(fields));
                log.Log($"Retrieved the record '{recordEntityName}':'{recordId}'.");
                CrmHelpers.LogAttributeValues(record.Attributes, record, log);
            }

            var clonedRecord = new Entity(recordEntityName);

            if (record != null && fields != null)
            {
                log.Log("Copying field values ...");
                var existingFields = fields.Where(f => record.Attributes.Contains(f)).ToArray();
                log.Log(new LogEntry("Field list ...", information: string.Join(",", existingFields)));
                clonedRecord.Attributes.AddRange(existingFields.ToDictionary(f => f, f => record[f]));
            }

            if (template.CloneFlagField.IsNotEmpty())
            {
                clonedRecord[template.CloneFlagField] = true;
                log.Log($"Set 'cloned' flag in field '{template.CloneFlagField}'.");
            }

            log.Log("Creating clone ...");
            var id = service.Create(clonedRecord);

            log.Log($"Created clone: '{id}'.");

            executionContext.SetValue(codeActivity.ClonedRecordIdArg, id.ToString());
        }
예제 #3
0
        private static void StartExport()
        {
            System.Console.Clear();
            System.Console.WriteLine("Starting Export:");
            System.Console.WriteLine();
            System.Console.Write("Please type the main entity logical name: ");
            var mainEntity = System.Console.ReadLine();

            System.Console.WriteLine();
            var filteredIds = CheckForFiltration(mainEntity);

            System.Console.Write($"Retrieveing {mainEntity} relationships");
            ConsoleHelpers.PlayLoadingAnimation();
            var customRelationships = CrmHelpers.GetCustomRelationships(_orgService, mainEntity,
                                                                        new[] { CrmHelpers.RelationType.ManyToManyRelationships });

            ConsoleHelpers.StopLoadingAnimation();
            ConsoleHelpers.WriteSuccess("Retrieved Relationships");
            System.Console.WriteLine();
            Export(customRelationships, filteredIds, mainEntity);
        }
        public static IOrganizationService CreateCrmService(string connectionString)
        {
            CrmServiceClient service;

            lock (lockObject)
            {
                if (latestStringUsed != connectionString &&
                    !connectionString.ToLower().Contains("requirenewinstance"))
                {
                    latestStringUsed  = connectionString;
                    connectionString  = connectionString.Trim(';', ' ');
                    connectionString += ";RequireNewInstance=true";
                }

                service = new CrmServiceClient(connectionString);
            }

            var escapedString = Regex.Replace(connectionString, @"Password\s*?=.*?(?:;{0,1}$|;)",
                                              "Password=********;");

            try
            {
                if (!string.IsNullOrEmpty(service.LastCrmError) || service.LastCrmException != null)
                {
                    throw new ServiceActivationException(
                              $"Can't create connection to: \"{escapedString}\" due to \"{service.LastCrmError}\"");
                }

                return(service);
            }
            catch (Exception ex)
            {
                var errorMessage = service.LastCrmError
                                   ?? (service.LastCrmException != null ? CrmHelpers.BuildExceptionMessage(service.LastCrmException) : null)
                                   ?? CrmHelpers.BuildExceptionMessage(ex);
                throw new ServiceActivationException($"Can't create connection to: \"{escapedString}\" due to\r\n{errorMessage}");
            }
        }
예제 #5
0
        public IOrganizationService CreateCrmService()
        {
            var service       = new CrmServiceClient(parameters.ConnectionString);
            var escapedString = Regex.Replace(parameters.ConnectionString, @"Password\s*?=.*?(?:;{0,1}$|;)",
                                              "Password=********;");

            try
            {
                if (!string.IsNullOrEmpty(service.LastCrmError) || service.LastCrmException != null)
                {
                    throw new ServiceActivationException(
                              $"Can't create connection to: \"{escapedString}\" due to \"{service.LastCrmError}\"");
                }

                return(service);
            }
            catch (Exception ex)
            {
                var errorMessage = service.LastCrmError
                                   ?? (service.LastCrmException != null ? CrmHelpers.BuildExceptionMessage(service.LastCrmException) : null)
                                   ?? CrmHelpers.BuildExceptionMessage(ex);
                throw new ServiceActivationException($"Can't create connection to: \"{escapedString}\" due to\r\n{errorMessage}");
            }
        }
예제 #6
0
        protected override void ExecuteLogic()
        {
            var xrmContext = new XrmServiceContext(Service)
            {
                MergeOption = MergeOption.NoTracking
            };

            // get the triggering record
            var target = (Entity)Context.InputParameters["Target"];

            Log.SetRegarding(Context.PrimaryEntityName, target.Id);

            var config = CrmHelpers.GetGenericConfig(Service, Context.OrganizationId.ToString()).ToEntity <CommonConfiguration>();

            if (config.JobsPlatform != CommonConfiguration.JobsPlatformEnum.CRM)
            {
                throw new InvalidPluginExecutionException($"Cannot queue the job because target platform is not set to CRM"
                                                          + $" (current: {config.JobsPlatform}).");
            }

            Log.Log("Fetching job records ...");
            var jobRecordsQuery =
                from job in xrmContext.CustomJobSet
                where ((job.TargetDate == null || job.TargetDate < DateTime.UtcNow) &&
                       (job.StatusReason == CustomJob.StatusReasonEnum.Waiting ||
                        job.StatusReason == CustomJob.StatusReasonEnum.Retry)) ||
                (job.ModifiedOn < DateTime.UtcNow.AddMinutes(-config.JobTimeout.GetValueOrDefault(20)) &&
                 (job.StatusReason == CustomJob.StatusReasonEnum.Running ||
                  job.StatusReason == CustomJob.StatusReasonEnum.Queued))
                select new
            {
                job.CustomJobId,
                job.StatusReason
            };

            var maxJobsPerRun = xrmContext.CustomJobEngineSet.Select(engine => engine.MaxJobsPerRun).FirstOrDefault();

            if (maxJobsPerRun > 0)
            {
                jobRecordsQuery = jobRecordsQuery.Take(maxJobsPerRun.Value);
            }

            var jobRecords = jobRecordsQuery.ToList();

            Log.Log($"Fetched job records '{jobRecords.Count}'.");

            Log.Log("Fetching parent job records ...");

            var parentQuery = new FetchExpression(
                $@"
<fetch no-lock='true'>
  <entity name='ldv_customjob'>
    <attribute name='ldv_customjobid' />
    <attribute name='statuscode' />
    <filter>
      <condition attribute='statuscode' operator='eq' value='{CustomJob.StatusReasonEnum.WaitingOnSubJobs}' />
      <condition entityname='subjob' attribute='ldv_customjobid' operator='null' />
    </filter>
    <link-entity name='ldv_customjob' from='ldv_parentjobid' to='ldv_customjobid' link-type='outer' alias='subjob' >
      <filter>
        <condition attribute='statecode' operator='eq' value='0' />
      </filter>
    </link-entity>
  </entity>
</fetch>");
            var parentJobs = Service.RetrieveMultiple(parentQuery).Entities;

            Log.Log($"Fetched parent job records '{jobRecords.Count}'.");

            jobRecords = jobRecords
                         .Union(parentJobs
                                .Select(j => j.ToEntity <CustomJob>())
                                .Select(j => new { j.CustomJobId, j.StatusReason }))
                         .Where(j => j.CustomJobId.HasValue).ToList();

            Log.Log($"Fetched" +
                    $" {jobRecords.Count(job => new [] { CustomJob.StatusReasonEnum.Queued, CustomJob.StatusReasonEnum.Running, CustomJob.StatusReasonEnum.WaitingOnSubJobs }.Contains(job.StatusReason.GetValueOrDefault()))}"
                    + $" stalled job records.");

            if (jobRecords.Any())
            {
                foreach (var jobRecord in jobRecords)
                {
                    Service.Update(
                        new CustomJob
                    {
                        Id           = jobRecord.CustomJobId.GetValueOrDefault(),
                        StatusReason = CustomJob.StatusReasonEnum.Queued,
                        RunTrigger   = new Random().Next(11111, 999999).ToString()
                    });
                }

                Log.Log(new LogEntry("Queue Information",
                                     information: jobRecords.Select(record => record.ToString()).Aggregate((r1, r2) => r1 + "\r\n" + r2)));
            }

            Log.Log("Fetching date-corrupted records ...");
            var corruptJobs =
                (from job in xrmContext.CustomJobSet
                 where job.TargetDate > new DateTime(2099, 1, 1) && job.StatusReason == CustomJob.StatusReasonEnum.Waiting &&
                 job.RecurrentJob == true
                 select job.CustomJobId).ToArray().Where(id => id.HasValue).Select(id => id.GetValueOrDefault()).ToArray();

            Log.Log($"Fetched {corruptJobs.Length} date-corrupted records.");

            if (corruptJobs.Any())
            {
                Log.Log("Triggering recurrence recalculation of records ...");
                foreach (var jobId in corruptJobs)
                {
                    Service.Update(
                        new CustomJob
                    {
                        Id = jobId,
                        RecurrenceUpdatedTrigger = new Random().Next(111111, 99999999).ToString()
                    });
                    Log.Log($"Triggered recurrence recalculation of '{jobId}'.");
                }
                Log.Log("Finished triggering recurrence recalculation of records.");
            }
        }
예제 #7
0
        protected override void ExecuteLogic()
        {
            // get the triggering record
            var target = Target;
            NotificationMessage message = null;

            var isEnabled = CrmHelpers
                            .GetGenericConfig(Service, Context.OrganizationId).ToEntity <CommonConfiguration>()?
                            .NotificationsCentreEnabled == true;

            if (!isEnabled)
            {
                return;
            }

            switch (target.LogicalName)
            {
            case Email.EntityLogicalName:
                var email = target.ToEntity <Email>();
                var body  = email.Description;

                // no message
                if (string.IsNullOrEmpty(body))
                {
                    return;
                }

                if (body.Contains("<html>"))
                {
                    var doc = new XmlDocument();
                    doc.LoadXml(body);
                    body = doc.SelectSingleNode("body")?.InnerXml;
                }

                // html has no body to display
                if (string.IsNullOrEmpty(body))
                {
                    return;
                }

                var users = email.To
                            .Select(e => e.Party)
                            .Where(a => a.LogicalName == User.EntityLogicalName)
                            .Select(a =>
                                    new NotificationMessageUser
                {
                    User = a.Id
                }).ToArray();

                // no users to notify
                if (!users.Any())
                {
                    return;
                }

                message =
                    new NotificationMessage
                {
                    Title              = email.Subject,
                    Message            = body,
                    RegardingTypeCode  = Email.EntityTypeCode,
                    RegardingID        = target.Id.ToString(),
                    MessageUsers       = users,
                    NotificationSource = GlobalEnums.NotificationSource.Email
                };

                break;

            case Task.EntityLogicalName:
                var task = target.ToEntity <Task>();
                message =
                    new NotificationMessage
                {
                    Title             = task.Subject,
                    Message           = task.Description,
                    RegardingTypeCode = Task.EntityTypeCode,
                    RegardingID       = target.Id.ToString()
                };

                var owner = task.Owner;

                switch (owner.LogicalName)
                {
                case User.EntityLogicalName:
                    message.MessageUsers =
                        new[]
                    {
                        new NotificationMessageUser
                        {
                            User = owner.Id
                        }
                    };
                    break;

                case Team.EntityLogicalName:
                    message.MessageTeams =
                        new[]
                    {
                        new NotificationMessageTeam
                        {
                            Team = owner.Id
                        }
                    };
                    break;
                }

                message.NotificationSource = GlobalEnums.NotificationSource.Task;

                break;
            }

            if (message != null)
            {
                message.StatusReason = NotificationMessage.StatusReasonEnum.Open;
                Service.Create(message);
            }
        }