示例#1
0
        public static void RemoveImpersonation(this ConnectionDetail connectionDetail)
        {
            connectionDetail.ImpersonatedUserId   = Guid.Empty;
            connectionDetail.ImpersonatedUserName = null;

            connectionDetail.GetServiceClient().CallerId = Guid.Empty;

            OnImpersonate?.Invoke(connectionDetail, new ImpersonationEventArgs(connectionDetail.ImpersonatedUserId, connectionDetail.ImpersonatedUserName));
        }
示例#2
0
        public static void Impersonate(this ConnectionDetail connectionDetail, Guid userId, string username = null)
        {
            connectionDetail.ImpersonatedUserId   = userId;
            connectionDetail.ImpersonatedUserName = username;

            connectionDetail.GetServiceClient().CallerId = userId;

            OnImpersonate?.Invoke(connectionDetail, new ImpersonationEventArgs(connectionDetail.ImpersonatedUserId, connectionDetail.ImpersonatedUserName));
        }
示例#3
0
        /// <summary>
        /// Updates the <see cref="MetadataCache"/>
        /// </summary>
        /// <param name="flush">Indicates if the existing cache should be flushed and a full new copy of the metadata should be retrieved</param>
        public static Task UpdateMetadataCache(this ConnectionDetail connectionDetail, bool flush)
        {
            if (connectionDetail.OrganizationMajorVersion < 8)
            {
                throw new NotSupportedException("Metadata cache is only supported on Dynamics CRM 2016 or later");
            }

            // If there's already an update in progress, don't start a new one
            if (!MetadataCacheLoader.IsCompleted)
            {
                return(MetadataCacheLoader);
            }

            // Load the metadata in a background task
            var task = new Task <MetadataCache>(() =>
            {
                // Load & update metadata cache
                var metadataCachePath = Path.Combine(Path.GetDirectoryName(ConnectionsList.ConnectionsListFilePath), "..", "Metadata", connectionDetail.ConnectionId + ".xml.gz");
                metadataCachePath     = Path.IsPathRooted(metadataCachePath) ? metadataCachePath : Path.Combine(new FileInfo(Assembly.GetExecutingAssembly().Location).DirectoryName, metadataCachePath);

                var metadataSerializer = new DataContractSerializer(typeof(MetadataCache));
                var metadataCache      = _metadataCache;

                if (metadataCache == null && File.Exists(metadataCachePath) && !flush)
                {
                    try
                    {
                        using (var stream = File.OpenRead(metadataCachePath))
                            using (var gz = new GZipStream(stream, CompressionMode.Decompress))
                            {
                                metadataCache = (MetadataCache)metadataSerializer.ReadObject(gz);
                            }
                    }
                    catch
                    {
                        // If the cache file isn't readable for any reason, throw it away and download a new copy
                    }
                }

                // Get all the metadata that's changed since the last connection
                // If this query changes, increment the version number to ensure any previously cached versions are flushed
                const int queryVersion = 2;

                var metadataQuery = new RetrieveMetadataChangesRequest
                {
                    ClientVersionStamp = !flush && metadataCache?.MetadataQueryVersion == queryVersion ? metadataCache?.ClientVersionStamp : null,
                    Query = new EntityQueryExpression
                    {
                        Properties = new MetadataPropertiesExpression {
                            AllProperties = true
                        },
                        AttributeQuery = new AttributeQueryExpression
                        {
                            Properties = new MetadataPropertiesExpression {
                                AllProperties = true
                            }
                        },
                        RelationshipQuery = new RelationshipQueryExpression
                        {
                            Properties = new MetadataPropertiesExpression {
                                AllProperties = true
                            }
                        }
                    },
                    DeletedMetadataFilters = DeletedMetadataFilters.All
                };

                RetrieveMetadataChangesResponse metadataUpdate;

                try
                {
                    metadataUpdate = (RetrieveMetadataChangesResponse)connectionDetail.GetServiceClient().Execute(metadataQuery);
                }
                catch (FaultException <Microsoft.Xrm.Sdk.OrganizationServiceFault> ex)
                {
                    // If the last connection was too long ago, we need to request all the metadata, not just the changes
                    if (ex.Detail.ErrorCode == unchecked ((int)0x80044352))
                    {
                        _metadataCache = null;
                        metadataQuery.ClientVersionStamp = null;
                        metadataUpdate = (RetrieveMetadataChangesResponse)connectionDetail.GetServiceClient().Execute(metadataQuery);
                    }
                    else
                    {
                        throw;
                    }
                }

                if (metadataCache == null || flush)
                {
                    // If we didn't have a previous cache, just start a fresh one
                    metadataCache = new MetadataCache();
                    metadataCache.EntityMetadata       = metadataUpdate.EntityMetadata.ToArray();
                    metadataCache.MetadataQueryVersion = queryVersion;
                }
                else
                {
                    // We had a cached version of the metadata before, so now we need to merge in the changes
                    var deletedIds = metadataUpdate.DeletedMetadata == null ? new List <Guid>() : metadataUpdate.DeletedMetadata.SelectMany(kvp => kvp.Value).Distinct().ToList();

                    connectionDetail.CopyChanges(metadataCache, typeof(MetadataCache).GetProperty(nameof(Utils.MetadataCache.EntityMetadata)), metadataUpdate.EntityMetadata.ToArray(), deletedIds);
                }

                _metadataCache = metadataCache;

                // Save the latest metadata cache
                if (metadataCache.ClientVersionStamp != metadataUpdate.ServerVersionStamp ||
                    metadataCache.MetadataQueryVersion != queryVersion)
                {
                    metadataCache.ClientVersionStamp   = metadataUpdate.ServerVersionStamp;
                    metadataCache.MetadataQueryVersion = queryVersion;

                    Directory.CreateDirectory(Path.GetDirectoryName(metadataCachePath));

                    using (var stream = File.Create(metadataCachePath))
                        using (var gz = new GZipStream(stream, CompressionLevel.Optimal))
                        {
                            metadataSerializer.WriteObject(gz, metadataCache);
                        }
                }

                return(metadataCache);
            });

            task.ConfigureAwait(false);

            // Store the current metadata loading task and run it
            MetadataCacheLoader = task;
            task.Start();
            return(task);
        }