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)); }
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)); }
/// <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); }