diff --git a/global.json b/global.json
index c88d990..a4cba75 100644
--- a/global.json
+++ b/global.json
@@ -1,6 +1,6 @@
{
"sdk": {
- "version": "6.0.202",
+ "version": "6.0.406",
"rollForward": "latestFeature",
"allowPrerelease": false
}
diff --git a/src/Build.Common.core.props b/src/Build.Common.core.props
index 5648a45..8f9bf13 100644
--- a/src/Build.Common.core.props
+++ b/src/Build.Common.core.props
@@ -5,7 +5,7 @@
- net462;net472;net48;netcoreapp3.1;netstandard2.0
+ net462;net472;net48;netcoreapp3.1;netstandard2.0;net6.0
false
diff --git a/src/Build.Shared.props b/src/Build.Shared.props
index 221d137..211c850 100644
--- a/src/Build.Shared.props
+++ b/src/Build.Shared.props
@@ -8,8 +8,8 @@
$(MSBuildAllProjects);$(MSBuildThisFileFullPath)
3.19.8
4.35.1
- 4.7.11043-v9.0-weekly-2209.2
- 4.7.11043-v9.0-weekly-2209.2
+ 4.9.665-v9.0-master
+ 4.9.665-v9.0-master
4.6.6061-weekly-2108.5
13.0.1
2.3.20
@@ -21,10 +21,10 @@
3.1.8
- 17.2.0
+ 17.5.0
2.2.10
4.16.0
- 2.4.1
+ 2.4.2
2.4.5
5.10.3
diff --git a/src/GeneralTools/DataverseClient/Client/ConnectionService.cs b/src/GeneralTools/DataverseClient/Client/ConnectionService.cs
index f785989..9039d50 100644
--- a/src/GeneralTools/DataverseClient/Client/ConnectionService.cs
+++ b/src/GeneralTools/DataverseClient/Client/ConnectionService.cs
@@ -90,6 +90,8 @@ internal sealed class ConnectionService : IConnectionService, IDisposable
private WhoAmIResponse user; // Dataverse user entity that is the service.
private string _hostname; // Host name of the Dataverse server
private string _port; // Port the WebService is on
+ private OrganizationDetail _OrgDetail; // if provided by the calling system, bypasses all discovery server lookup processed.
+ private bool _orgReadingDetails = false;
private string _organization; // Org that is being inquired on..
private AuthenticationType _eAuthType; // Default setting for Auth Cred;
@@ -100,9 +102,6 @@ internal sealed class ConnectionService : IConnectionService, IDisposable
[NonSerializedAttribute]
private string _InternetProtocalToUse = "http"; // Which Internet protocol to use to connect.
- private OrganizationDetail _OrgDetail; // if provided by the calling system, bypasses all discovery server lookup processed.
- //private OrganizationDetail _ActualOrgDetailUsed; // Org Detail that was used by the Auth system when it created the proxy.
-
///
/// This is the actual Dataverse OrgURI used to connect, which could be influenced by the host name given during the connect process.
///
@@ -132,10 +131,10 @@ internal sealed class ConnectionService : IConnectionService, IDisposable
///
private readonly TimeSpan _tokenOffSetTimeSpan = TimeSpan.FromMinutes(2);
- ///
- /// if Set to true then the connection is for one use and should be cleand out of cache when completed.
- ///
- private bool unqueInstance = false;
+ /////
+ ///// if Set to true then the connection is for one use and should be cleand out of cache when completed.
+ /////
+ //private bool unqueInstance = false;
///
/// Client or App Id to use.
@@ -354,6 +353,11 @@ internal bool CalledbyExecuteRequest
set { _isCalledbyExecuteRequest = value; }
}
+ ///
+ /// When set to true, indicates that the organization details have allready been read.
+ ///
+ internal bool OrgDetailsRead = false;
+
///
/// Logging provider for DataverseConnectionServiceobject.
///
@@ -391,7 +395,29 @@ internal System.Net.NetworkCredential DataverseServiceAccessCredential
///
/// returns the connected organization detail object.
///
- internal OrganizationDetail ConnectedOrganizationDetail { get { return _OrgDetail; } }
+ internal OrganizationDetail ConnectedOrganizationDetail
+ {
+ get
+ {
+ if (_OrgDetail == null || !OrgDetailsRead)
+ {
+ lock (lockObject)
+ {
+ _orgReadingDetails = true;
+ IOrganizationService svc = null;
+ if (WebClient != null || OnPremClient != null)
+ {
+ if (WebClient != null) svc = WebClient; else svc = OnPremClient;
+ RefreshInstanceDetails(svc, _targetInstanceUriToConnectTo).ConfigureAwait(false).GetAwaiter().GetResult();
+ }
+ _orgReadingDetails = false;
+ OrgDetailsRead = true;
+ }
+ }
+ return _OrgDetail;
+ }
+ set { _OrgDetail = value; }
+ }
///
///
@@ -452,8 +478,13 @@ internal OrganizationServiceProxyAsync OnPremClient
///
internal string CustomerOrganization
{
- get { return _organization; }
- set { _organization = value; }
+ get
+ {
+ if (_orgReadingDetails)
+ return null;
+ else
+ return ConnectedOrganizationDetail.UniqueName;
+ }
}
///
@@ -503,12 +534,30 @@ internal WhoAmIResponse CurrentUser
///
/// Returns the friendly name of the connected org.
///
- internal string ConnectedOrgFriendlyName { get; private set; }
+ internal string ConnectedOrgFriendlyName
+ {
+ get
+ {
+ if (_orgReadingDetails)
+ return null;
+ else
+ return ConnectedOrganizationDetail.FriendlyName;
+ }
+ }
///
/// Returns the endpoint collection for the connected org.
///
- internal EndpointCollection ConnectedOrgPublishedEndpoints { get; set; }
+ internal EndpointCollection ConnectedOrgPublishedEndpoints
+ {
+ get
+ {
+ if (_orgReadingDetails)
+ return null;
+ else
+ return ConnectedOrganizationDetail.Endpoints;
+ }
+ }
///
/// Version Number of the organization, if null Discovery service process was not run or the value returned was unreadable.
@@ -522,9 +571,9 @@ internal Guid OrganizationId
{
get
{
- if (_OrganizationId == Guid.Empty && _OrgDetail != null)
+ if (_OrganizationId == Guid.Empty && ConnectedOrganizationDetail != null)
{
- _OrganizationId = _OrgDetail.OrganizationId;
+ _OrganizationId = ConnectedOrganizationDetail.OrganizationId;
}
return _OrganizationId;
}
@@ -541,9 +590,9 @@ internal Guid TenantId
{
get
{
- if (_TenantId == Guid.Empty && _OrgDetail != null)
+ if (_TenantId == Guid.Empty && ConnectedOrganizationDetail != null)
{
- Guid.TryParse(_OrgDetail.TenantId, out _TenantId);
+ Guid.TryParse(ConnectedOrganizationDetail.TenantId, out _TenantId);
}
return _TenantId;
}
@@ -560,9 +609,9 @@ internal string EnvironmentId
{
get
{
- if (string.IsNullOrEmpty(_EnvironmentId) && _OrgDetail != null)
+ if (string.IsNullOrEmpty(_EnvironmentId) && ConnectedOrganizationDetail != null)
{
- _EnvironmentId = _OrgDetail.EnvironmentId;
+ _EnvironmentId = ConnectedOrganizationDetail.EnvironmentId;
}
return _EnvironmentId;
}
@@ -634,8 +683,11 @@ internal ConnectionService(IOrganizationService testIOrganziationSvc, string bas
WebApiHttpClient = mockClient;
logEntry = new DataverseTraceLogger(logger);
isLogEntryCreatedLocaly = true;
- ConnectedOrgPublishedEndpoints = new EndpointCollection();
- ConnectedOrgPublishedEndpoints.Add(EndpointType.OrganizationDataService, baseConnectUrl);
+
+ _OrgDetail = new OrganizationDetail();
+ _OrgDetail.Endpoints.Add(EndpointType.OrganizationDataService, baseConnectUrl);
+
+ ConnectedOrganizationDetail = _OrgDetail;
RefreshInstanceDetails(testIOrganziationSvc, null).ConfigureAwait(false).GetAwaiter().GetResult();
}
@@ -711,6 +763,9 @@ internal ConnectionService(
isLogEntryCreatedLocaly = false;
}
+ // Override WebAPI for Login flow.
+ _configuration.Value.UseWebApiLoginFlow = false;
+
UseExternalConnection = false;
_eAuthType = authType;
_hostname = hostName;
@@ -878,7 +933,7 @@ private void GenerateCacheKeys(bool useUniqueCacheName)
// This is to deal with 2 instances of the ConnectionService being created in the Same Running Instance that would need to connect to different Dataverse servers.
if (useUniqueCacheName)
{
- unqueInstance = true; // this instance is unique.
+ //unqueInstance = true; // this instance is unique.
_authority = string.Empty;
_userId = null;
Guid guID = Guid.NewGuid();
@@ -966,7 +1021,6 @@ private IOrganizationService GetCachedService(out ConnectionService ConnectionOb
try
{
// Removed call to WHoAMI as it is amused when picking up cache that the reauth logic will be exercised by the first call to the server.
- ConnectionObject.ResetDisposedState(); // resetting disposed state as this object was pulled from cache.
if (ConnectionObject._svcWebClientProxy != null)
return (IOrganizationService)ConnectionObject._svcWebClientProxy;
else
@@ -1158,7 +1212,10 @@ private async Task InitServiceAsync()
}
}
else
+ {
orgDetail = _OrgDetail; // Assign to passed in value.
+ OrgDetailsRead = true;
+ }
// Try to connect to Dataverse here.
dvService = await ConnectAndInitServiceAsync(orgDetail, true, uUserHomeRealm).ConfigureAwait(false);
@@ -1257,6 +1314,8 @@ private async Task InitServiceAsync()
logEntry.Log(string.Format(CultureInfo.InvariantCulture, "Found {0} Org(s)", orgList.OrgsList.Count), TraceEventType.Information);
if (orgList.OrgsList.Count == 1)
{
+ _OrgDetail = orgList.OrgsList.First().OrgDetail;
+ OrgDetailsRead = true;
dvService = await ConnectAndInitServiceAsync(orgList.OrgsList.First().OrgDetail, false, null).ConfigureAwait(false);
if (dvService != null)
{
@@ -1279,6 +1338,8 @@ private async Task InitServiceAsync()
if (orgDetail != null && !string.IsNullOrEmpty(orgDetail.OrgDetail.UniqueName))
{
// Found it ..
+ _OrgDetail = orgDetail.OrgDetail;
+ OrgDetailsRead = true;
logEntry.Log(string.Format(CultureInfo.InvariantCulture, "found User Org = {0} in results", _organization), TraceEventType.Information);
dvService = await ConnectAndInitServiceAsync(orgDetail.OrgDetail, false, null).ConfigureAwait(false);
if (dvService != null)
@@ -1485,17 +1546,9 @@ private async Task DoDirectLoginAsync(bool IsOnPrem = fals
if (dvService != null)
{
- await RefreshInstanceDetails(dvService, _targetInstanceUriToConnectTo).ConfigureAwait(false);
- if (_OrgDetail != null)
- {
- logEntry.Log(string.Format(CultureInfo.InvariantCulture,
- "Connected to User Organization ({0} version: {1})", _OrgDetail.UniqueName, (_OrgDetail.OrganizationVersion ?? "Unknown").ToString()));
- }
- else
- {
- logEntry.Log("Organization Details Unavailable due to SkipOrgDetails flag set to True, to populate organization details on login, do not set SkipOrgDetails or set it to false.");
- }
-
+ OrganizationVersion = Version.Parse("9.0");
+ //await GetServerVersion(dvService, _targetInstanceUriToConnectTo).ConfigureAwait(false);
+ //await RefreshInstanceDetails(dvService, _targetInstanceUriToConnectTo).ConfigureAwait(false);
// Format the URL for WebAPI service.
if (OrganizationVersion != null && OrganizationVersion.Major >= 8)
{
@@ -1508,6 +1561,85 @@ private async Task DoDirectLoginAsync(bool IsOnPrem = fals
return dvService;
}
+ ///
+ /// Get Organization version Information for Setup.
+ ///
+ ///
+ ///
+ ///
+ ///
+ private async Task GetServerVersion(IOrganizationService dvService, Uri uriOfInstance)
+ {
+ if (dvService != null)
+ {
+ try
+ {
+ Guid trackingID = Guid.NewGuid();
+ logEntry.Log(string.Format("Querying Organization Version. Request ID: {0}", trackingID));
+ Stopwatch dtQueryTimer = new Stopwatch();
+ dtQueryTimer.Restart();
+
+ RetrieveVersionResponse getVersionResp = null;
+ var request = new RetrieveVersionRequest() { RequestId = trackingID };
+ logEntry.Log(string.Format(CultureInfo.InvariantCulture, "Execute Command - RetrieveVersionRequest : RequestId={0}", trackingID));
+ if (_configuration.Value.UseWebApiLoginFlow)
+ {
+ OrganizationResponse orgResp = await Command_WebAPIProcess_ExecuteAsync(
+ request, null, false, null, Guid.Empty, false, _configuration.Value.MaxRetryCount, _configuration.Value.RetryPauseTime, new CancellationToken(), uriOfInstance, true).ConfigureAwait(false);
+ try
+ {
+ getVersionResp = (RetrieveVersionResponse)orgResp;
+ }
+ catch (Exception ex)
+ {
+ dtQueryTimer.Stop();
+ logEntry.Log(string.Format(CultureInfo.InvariantCulture, "Failed to Executed Command - RetrieveVersionRequest : RequestId={1} : total duration: {0}", dtQueryTimer.Elapsed.ToString(), trackingID.ToString()), TraceEventType.Error);
+ logEntry.Log("************ Exception - Failed to lookup current organization version", TraceEventType.Error, ex);
+ throw new DataverseOperationException($"Failure to convert OrganziationResponse to requested type - request was {request.RequestName}", ex);
+ }
+ }
+ else
+ {
+ try
+ {
+ getVersionResp = (RetrieveVersionResponse)dvService.Execute(request);
+ }
+ catch (Exception ex)
+ {
+ dtQueryTimer.Stop();
+ logEntry.Log(string.Format(CultureInfo.InvariantCulture, "Failed to Executed Command - RetrieveVersionRequest : RequestId={1} : total duration: {0}", dtQueryTimer.Elapsed.ToString(), trackingID.ToString()), TraceEventType.Error);
+ logEntry.Log("************ Exception - Failed to lookup current organization version", TraceEventType.Error, ex);
+ throw new DataverseOperationException("Exception - Failed to lookup current organization version", ex);
+ }
+ }
+ dtQueryTimer.Stop();
+ logEntry.Log(string.Format(CultureInfo.InvariantCulture, "Executed Command - RetrieveVersionRequest : RequestId={1} : total duration: {0}", dtQueryTimer.Elapsed.ToString(), trackingID.ToString()));
+
+ if (getVersionResp != null)
+ {
+ OrganizationVersion = new Version("0.0.0.0");
+ try
+ {
+ if (Version.TryParse(getVersionResp.Version, out Version outVer))
+ {
+ OrganizationVersion = outVer;
+ }
+ }
+ catch { };
+ }
+ logEntry.Log("Completed Parsing Organization Instance Version", TraceEventType.Verbose);
+ }
+ catch (Exception ex)
+ {
+ logEntry.Log("************ Exception - Fault While initializing client - RetrieveVersionRequest", TraceEventType.Error, ex);
+ HttpOperationException opEx = Utilities.SeekExceptionOnStack(ex);
+ if (opEx != null)
+ throw DataverseConnectionException.GenerateClientConnectionException(opEx);
+ else
+ throw new DataverseConnectionException("Exception - Fault While initializing client - RetrieveVersionRequest", ex);
+ }
+ }
+ }
///
/// Refresh the organization instance details.
@@ -1564,7 +1696,7 @@ private async Task RefreshInstanceDetails(IOrganizationService dvService, Uri ur
// Left in information mode intentionally
logEntry.Log(string.Format(CultureInfo.InvariantCulture, "Executed Command - RetrieveCurrentOrganizationRequest : RequestId={1} : total duration: {0}", dtQueryTimer.Elapsed.ToString(), trackingID.ToString()));
- if (resp.Detail != null)
+ if (resp?.Detail != null)
{
_OrgDetail = new OrganizationDetail();
//Add Endpoints.
@@ -1594,10 +1726,7 @@ private async Task RefreshInstanceDetails(IOrganizationService dvService, Uri ur
_OrgDetail.UniqueName = resp.Detail.UniqueName;
_OrgDetail.UrlName = resp.Detail.UrlName;
}
-
_organization = _OrgDetail.UniqueName;
- ConnectedOrgFriendlyName = _OrgDetail.FriendlyName;
- ConnectedOrgPublishedEndpoints = _OrgDetail.Endpoints;
// try to create a version number from the org.
OrganizationVersion = new Version("0.0.0.0");
@@ -1609,12 +1738,22 @@ private async Task RefreshInstanceDetails(IOrganizationService dvService, Uri ur
}
}
catch { };
+
+ if (_OrgDetail != null)
+ {
+ logEntry.Log(string.Format(CultureInfo.InvariantCulture,
+ "Read Organization Information ({0} version: {1})", _OrgDetail.UniqueName, (_OrgDetail.OrganizationVersion ?? "Unknown").ToString()));
+ }
logEntry.Log("Completed Parsing Organization Instance Details", TraceEventType.Verbose);
}
catch (Exception ex)
{
logEntry.Log("************ Exception - Fault While initializing client - RefreshInstanceDetails", TraceEventType.Error, ex);
- throw new DataverseConnectionException("Exception - Fault While initializing client - RefreshInstanceDetails", ex);
+ HttpOperationException opEx = Utilities.SeekExceptionOnStack(ex);
+ if ( opEx != null )
+ throw DataverseConnectionException.GenerateClientConnectionException(opEx);
+ else
+ throw new DataverseConnectionException("Exception - Fault While initializing client - RefreshInstanceDetails", ex);
}
}
}
@@ -1691,18 +1830,16 @@ internal void SetClonedProperties(ServiceClient sourceClient)
{
System.Diagnostics.Trace.WriteLine($"Cloning {sourceClient._connectionSvc._ServiceCACHEName} to create {_ServiceCACHEName}");
- user = sourceClient.SystemUser;
+ OrgDetailsRead = sourceClient._connectionSvc.OrgDetailsRead;
debugingCloneStateFilter++;
- OrganizationVersion = sourceClient._connectionSvc.OrganizationVersion;
+ user = sourceClient.SystemUser;
debugingCloneStateFilter++;
- ConnectedOrgPublishedEndpoints = sourceClient.ConnectedOrgPublishedEndpoints;
+ ConnectedOrganizationDetail = sourceClient.OrganizationDetail;
debugingCloneStateFilter++;
- ConnectedOrgFriendlyName = sourceClient.ConnectedOrgFriendlyName;
+ OrganizationVersion = sourceClient._connectionSvc.OrganizationVersion;
debugingCloneStateFilter++;
OrganizationId = sourceClient.ConnectedOrgId;
debugingCloneStateFilter++;
- CustomerOrganization = sourceClient.ConnectedOrgUniqueName;
- debugingCloneStateFilter++;
_ActualDataverseOrgUri = sourceClient.ConnectedOrgUriActual;
debugingCloneStateFilter++;
_MsalAuthClient = sourceClient._connectionSvc._MsalAuthClient;
@@ -1732,7 +1869,7 @@ internal void SetClonedProperties(ServiceClient sourceClient)
}
catch (Exception ex)
{
- throw new InvalidOperationException($"Failed constructing cloned connection. debugstate={debugingCloneStateFilter}", ex);
+ throw new DataverseOperationException($"Failed constructing cloned connection. debugstate={debugingCloneStateFilter}", ex);
}
}
@@ -2022,10 +2159,12 @@ internal async Task Command_WebExecuteAsync(string queryStr
// Default Odata 4.0 headers.
- Dictionary defaultODataHeaders = new Dictionary();
- defaultODataHeaders.Add("Accept", "application/json");
- defaultODataHeaders.Add("OData-MaxVersion", "4.0");
- defaultODataHeaders.Add("OData-Version", "4.0");
+ Dictionary defaultODataHeaders = new Dictionary
+ {
+ { "Accept", "application/json" },
+ { "OData-MaxVersion", "4.0" },
+ { "OData-Version", "4.0" }
+ };
//defaultODataHeaders.Add("If-None-Match", "");
// Supported Version Check.
@@ -2226,6 +2365,7 @@ internal async Task Command_WebExecuteAsync(string queryStr
logEntry.LogRetry(retryCount, null, _retryPauseTimeRunning, true, isThrottled: isThrottled, webUriMessageReq: $"{method} {queryString}");
logEntry.LogException(null, ex, errorStringCheck, webUriMessageReq: $"{method} {queryString}");
logEntry.LogFailure(null, requestTrackingId, SessionTrackingId, disableConnectionLocking, TimeSpan.Zero, logDt, ex, errorStringCheck, true, webUriMessageReq: $"{method} {queryString}");
+ throw;
}
resp = null;
}
@@ -2234,7 +2374,7 @@ internal async Task Command_WebExecuteAsync(string queryStr
retry = false;
logEntry.Log(string.Format(CultureInfo.InvariantCulture, "Failed to Execute Command - {2} {0} : {1}", queryString, requestIdLogSegement, method), TraceEventType.Verbose);
logEntry.Log(string.Format(CultureInfo.InvariantCulture, "************ Exception - {2} : {0} |=> {1}", errorStringCheck, ex.Message, queryString), TraceEventType.Error, ex);
- return null;
+ throw;
}
}
finally
@@ -2278,6 +2418,9 @@ private bool ShouldRetryWebAPI(Exception ex, int retryCount, int maxRetryCount,
if (ex is HttpOperationException httpOperationException)
{
+ if (httpOperationException.Response.StatusCode == HttpStatusCode.Unauthorized)
+ return false;
+
JObject contentBody = JObject.Parse(httpOperationException.Response.Content);
var errorCode = contentBody["error"]["code"].ToString();
var errorMessage = DataverseTraceLogger.GetFirstLineFromString(contentBody["error"]["message"].ToString()).Trim();
@@ -2961,8 +3104,7 @@ private async Task ConnectAndInitServiceAsync(Organization
// Set the Org into system config
_organization = orgdata.UniqueName;
- ConnectedOrgFriendlyName = orgdata.FriendlyName;
- ConnectedOrgPublishedEndpoints = orgdata.Endpoints;
+ ConnectedOrganizationDetail = orgdata;
var logDt = new Stopwatch();
logDt.Start();
@@ -3515,6 +3657,9 @@ private void AddOrgToOrgList(OrganizationDetail organizationDetail, string disco
internal async Task RefreshClientTokenAsync()
{
string clientToken = string.Empty;
+
+ if (disposedValue) { return clientToken; } // abort processing if disposed or dispose is occurring.
+
if (_authenticationResultContainer != null && !string.IsNullOrEmpty(_resource) && !string.IsNullOrEmpty(_clientId))
{
if (_authenticationResultContainer.ExpiresOn.ToUniversalTime() < DateTime.UtcNow.AddMinutes(1))
@@ -3571,14 +3716,14 @@ internal async Task RefreshClientTokenAsync()
}
#region IDisposable Support
- ///
- /// Reset disposed state to handle this object being pulled from cache.
- ///
- private void ResetDisposedState()
- {
- // reset the disposed state to deal with the object being pulled from cache.
- disposedValue = false;
- }
+ /////
+ ///// Reset disposed state to handle this object being pulled from cache.
+ /////
+ //private void ResetDisposedState()
+ //{
+ // // reset the disposed state to deal with the object being pulled from cache.
+ // disposedValue = false;
+ //}
private bool disposedValue = false; // To detect redundant calls
void Dispose(bool disposing)
@@ -3587,27 +3732,24 @@ void Dispose(bool disposing)
{
if (disposing)
{
+ disposedValue = true;
if (isLogEntryCreatedLocaly)
{
- if (logEntry != null)
- logEntry.Dispose();
+ logEntry?.Dispose();
}
- //TODO: REMOVE ONCE MEM TEST COMPELTES CLEAN.
- //if (_authenticationContext != null && _authenticationContext.TokenCache != null)
- //{
- // if (_authenticationContext.TokenCache is CdsServiceClientTokenCache)
- // {
- // ((CdsServiceClientTokenCache)_authenticationContext.TokenCache).Dispose();
- // }
- //}
-
- if (unqueInstance)
+ if (CurrentCookieCollection != null)
{
- // Clean the connect out of memory.
- _clientMemoryCache.Remove(_ServiceCACHEName);
+ CurrentCookieCollection.Clear();
+ CurrentCookieCollection = null;
}
+ //if (unqueInstance)
+ //{
+ // Clean the connect out of memory.
+ _clientMemoryCache.Remove(_ServiceCACHEName);
+ //}
+
try
{
if (_svcWebClientProxy != null)
@@ -3625,12 +3767,12 @@ void Dispose(bool disposing)
_svcWebClientProxy.Endpoint.EndpointBehaviors.Remove(typeof(DataverseTelemetryBehaviors));
}
}
+ _svcWebClientProxy.Dispose();
+ _svcWebClientProxy = null;
}
}
- catch { }; // Failed to dispose.. no way to notifiy this right now.. let it go .
+ catch { }; // Failed to dispose.. no way to notify this right now.. let it go .
}
-
- disposedValue = true;
}
}
@@ -3638,6 +3780,7 @@ void Dispose(bool disposing)
public void Dispose()
{
Dispose(true);
+ GC.SuppressFinalize(this);
}
#endregion
#endregion
diff --git a/src/GeneralTools/DataverseClient/Client/Connector/OnPremises/OrganizationServiceProxyAsync.cs b/src/GeneralTools/DataverseClient/Client/Connector/OnPremises/OrganizationServiceProxyAsync.cs
index 5f39bb1..d4283ce 100644
--- a/src/GeneralTools/DataverseClient/Client/Connector/OnPremises/OrganizationServiceProxyAsync.cs
+++ b/src/GeneralTools/DataverseClient/Client/Connector/OnPremises/OrganizationServiceProxyAsync.cs
@@ -106,9 +106,6 @@ public void EnableProxyTypes(Assembly assembly)
/// For Sdk clients called via the OrganizationServiceProxy this is the version of the local Microsoft.Xrm.Sdk dll used by the Client App.
///
///
- [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Security", "CA2143:TransparentMethodsShouldNotDemandFxCopRule")]
- [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Security", "CA2141:TransparentMethodsMustNotSatisfyLinkDemandsFxCopRule")]
- [PermissionSet(SecurityAction.Demand, Unrestricted = true)]
internal static string GetXrmSdkAssemblyFileVersion()
{
if (string.IsNullOrEmpty(_xrmSdkAssemblyFileVersion))
diff --git a/src/GeneralTools/DataverseClient/Client/Connector/OnPremises/ServiceInformation.cs b/src/GeneralTools/DataverseClient/Client/Connector/OnPremises/ServiceInformation.cs
index 4b0a960..c53c3f4 100644
--- a/src/GeneralTools/DataverseClient/Client/Connector/OnPremises/ServiceInformation.cs
+++ b/src/GeneralTools/DataverseClient/Client/Connector/OnPremises/ServiceInformation.cs
@@ -15,7 +15,6 @@
namespace Microsoft.PowerPlatform.Dataverse.Client.Connector.OnPremises
{
- [SecurityPermission(SecurityAction.Demand, Unrestricted = true)]
[SecuritySafeCritical]
internal sealed partial class ServiceConfiguration
{
diff --git a/src/GeneralTools/DataverseClient/Client/Connector/OrganizationWebProxyClientAsync.cs b/src/GeneralTools/DataverseClient/Client/Connector/OrganizationWebProxyClientAsync.cs
index 654ab46..19b1498 100644
--- a/src/GeneralTools/DataverseClient/Client/Connector/OrganizationWebProxyClientAsync.cs
+++ b/src/GeneralTools/DataverseClient/Client/Connector/OrganizationWebProxyClientAsync.cs
@@ -4,6 +4,7 @@ namespace Microsoft.PowerPlatform.Dataverse.Client.Connector
using System.Diagnostics.CodeAnalysis;
using System.Net;
using System.Reflection;
+ using System.ServiceModel;
using System.ServiceModel.Description;
using System.Threading.Tasks;
using Microsoft.PowerPlatform.Dataverse.Client;
@@ -62,7 +63,8 @@ public void Associate(string entityName, Guid entityId, Relationship relationshi
public Task AssociateAsync(string entityName, Guid entityId, Relationship relationship,
EntityReferenceCollection relatedEntities)
{
- return AssociateAsyncCore(entityName, entityId, relationship, relatedEntities);
+ AssociateAsyncCore(entityName, entityId, relationship, relatedEntities);
+ return Task.CompletedTask;
}
public Guid Create(Entity entity)
@@ -73,6 +75,7 @@ public Guid Create(Entity entity)
public Task CreateAsync(Entity entity)
{
return CreateAsyncCore(entity);
+
}
public void Delete(string entityName, Guid id)
@@ -82,7 +85,8 @@ public void Delete(string entityName, Guid id)
public Task DeleteAsync(string entityName, Guid id)
{
- return DeleteAsyncCore(entityName, id);
+ DeleteAsyncCore(entityName, id);
+ return Task.CompletedTask;
}
public void Disassociate(string entityName, Guid entityId, Relationship relationship,
@@ -94,7 +98,8 @@ public void Disassociate(string entityName, Guid entityId, Relationship relation
public Task DisassociateAsync(string entityName, Guid entityId, Relationship relationship,
EntityReferenceCollection relatedEntities)
{
- return DisassociateAsyncCore(entityName, entityId, relationship, relatedEntities);
+ DisassociateAsyncCore(entityName, entityId, relationship, relatedEntities);
+ return Task.CompletedTask;
}
public OrganizationResponse Execute(OrganizationRequest request)
@@ -134,7 +139,8 @@ public void Update(Entity entity)
public Task UpdateAsync(Entity entity)
{
- return UpdateAsyncCore(entity);
+ UpdateAsyncCore(entity);
+ return Task.CompletedTask;
}
#endregion
@@ -148,7 +154,7 @@ protected internal virtual Guid CreateCore(Entity entity)
protected Task CreateAsyncCore(Entity entity)
{
- return ExecuteAction(() => Channel.CreateAsync(entity));
+ return ExecuteOperation(() => Channel.CreateAsync(entity));
}
protected internal virtual Entity RetrieveCore(string entityName, Guid id, ColumnSet columnSet)
@@ -158,7 +164,7 @@ protected internal virtual Entity RetrieveCore(string entityName, Guid id, Colum
protected internal virtual Task RetrieveAsyncCore(string entityName, Guid id, ColumnSet columnSet)
{
- return ExecuteAction(() => Channel.RetrieveAsync(entityName, id, columnSet));
+ return ExecuteOperation(() => Channel.RetrieveAsync(entityName, id, columnSet));
}
protected internal virtual void UpdateCore(Entity entity)
@@ -168,7 +174,7 @@ protected internal virtual void UpdateCore(Entity entity)
protected internal virtual Task UpdateAsyncCore(Entity entity)
{
- return ExecuteAction(() => Channel.UpdateAsync(entity));
+ return ExecuteOperation(() => {Channel.UpdateAsync(entity); return (Task)Task.CompletedTask;});
}
protected internal virtual void DeleteCore(string entityName, Guid id)
@@ -178,7 +184,7 @@ protected internal virtual void DeleteCore(string entityName, Guid id)
protected internal virtual Task DeleteAsyncCore(string entityName, Guid id)
{
- return ExecuteAction(() => Channel.DeleteAsync(entityName, id));
+ return ExecuteOperation(() => { Channel.DeleteAsync(entityName, id); return (Task)Task.CompletedTask; });
}
protected internal virtual OrganizationResponse ExecuteCore(OrganizationRequest request)
@@ -188,7 +194,7 @@ protected internal virtual OrganizationResponse ExecuteCore(OrganizationRequest
protected internal virtual Task ExecuteAsyncCore(OrganizationRequest request)
{
- return ExecuteAction(() => Channel.ExecuteAsync(request));
+ return ExecuteOperation(() => Channel.ExecuteAsync(request));
}
protected internal virtual void AssociateCore(string entityName, Guid entityId, Relationship relationship,
@@ -200,7 +206,7 @@ protected internal virtual void AssociateCore(string entityName, Guid entityId,
protected internal virtual Task AssociateAsyncCore(string entityName, Guid entityId, Relationship relationship,
EntityReferenceCollection relatedEntities)
{
- return ExecuteAction(() => Channel.AssociateAsync(entityName, entityId, relationship, relatedEntities));
+ return ExecuteOperation(() => { Channel.AssociateAsync(entityName, entityId, relationship, relatedEntities); return (Task)Task.CompletedTask; });
}
protected internal virtual void DisassociateCore(string entityName, Guid entityId, Relationship relationship,
@@ -212,7 +218,7 @@ protected internal virtual void DisassociateCore(string entityName, Guid entityI
protected internal virtual Task DisassociateAsyncCore(string entityName, Guid entityId, Relationship relationship,
EntityReferenceCollection relatedEntities)
{
- return ExecuteAction(() => Channel.DisassociateAsync(entityName, entityId, relationship, relatedEntities));
+ return ExecuteOperation(() => { Channel.DisassociateAsync(entityName, entityId, relationship, relatedEntities); return (Task)Task.CompletedTask; });
}
protected internal virtual EntityCollection RetrieveMultipleCore(QueryBase query)
@@ -222,7 +228,7 @@ protected internal virtual EntityCollection RetrieveMultipleCore(QueryBase query
protected internal virtual Task RetrieveMultipleAsyncCore(QueryBase query)
{
- return ExecuteAction(() => Channel.RetrieveMultipleAsync(query));
+ return ExecuteOperation(() => Channel.RetrieveMultipleAsync(query));
}
#endregion Protected Members
diff --git a/src/GeneralTools/DataverseClient/Client/Connector/WebProxyClient.cs b/src/GeneralTools/DataverseClient/Client/Connector/WebProxyClient.cs
index 5a34895..5916b33 100644
--- a/src/GeneralTools/DataverseClient/Client/Connector/WebProxyClient.cs
+++ b/src/GeneralTools/DataverseClient/Client/Connector/WebProxyClient.cs
@@ -1,15 +1,14 @@
using System;
-using System.Diagnostics;
using System.Reflection;
using System.Security.Permissions;
using System.ServiceModel;
using System.ServiceModel.Channels;
using System.ServiceModel.Description;
+using System.Threading.Tasks;
using Microsoft.Xrm.Sdk.Client;
namespace Microsoft.PowerPlatform.Dataverse.Client.Connector
{
- [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.CodeQuality.Analyzers", "CA1063: Implement IDisposable correctly", Justification = "FxCop Bankruptcy")]
internal abstract class WebProxyClientAsync : ClientBase, IDisposable
where TService : class
{
@@ -83,6 +82,33 @@ internal TResult ExecuteAction(Func action)
}
}
+#if NETCOREAPP
+ protected async internal Task ExecuteOperation(Func> asyncAction)
+ {
+ if (asyncAction == null)
+ {
+ throw new ArgumentNullException(nameof(asyncAction));
+ }
+
+ using (CreateNewInitializer())
+ {
+ return await asyncAction().ConfigureAwait(continueOnCapturedContext: true);
+ }
+ }
+#else
+ protected internal Task ExecuteOperation(Func> asyncAction)
+ {
+ if (asyncAction == null)
+ {
+ throw new ArgumentNullException(nameof(asyncAction));
+ }
+
+ using (CreateNewInitializer())
+ {
+ return asyncAction();
+ }
+ }
+#endif
protected static ServiceEndpoint CreateServiceEndpoint(Uri serviceUrl, bool useStrongTypes, TimeSpan timeout,
Assembly strongTypeAssembly)
{
@@ -162,9 +188,6 @@ protected static Binding GetBinding(Uri serviceUrl, TimeSpan timeout)
/// by the Client App.
///
///
- [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Security", "CA2143:TransparentMethodsShouldNotDemandFxCopRule")]
- [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Security", "CA2141:TransparentMethodsMustNotSatisfyLinkDemandsFxCopRule")]
- [PermissionSet(SecurityAction.Demand, Unrestricted = true)]
internal string GetXrmSdkAssemblyFileVersion()
{
if (string.IsNullOrEmpty(_xrmSdkAssemblyFileVersion))
@@ -181,7 +204,7 @@ internal string GetXrmSdkAssemblyFileVersion()
return _xrmSdkAssemblyFileVersion;
}
- #region IDisposable implementation
+#region IDisposable implementation
public void Dispose()
{
@@ -189,19 +212,19 @@ public void Dispose()
GC.SuppressFinalize(this);
}
- #region Protected Methods
+#region Protected Methods
protected virtual void Dispose(bool disposing)
{
}
- #endregion
+#endregion
~WebProxyClientAsync()
{
Dispose(false);
}
- #endregion
+#endregion
}
}
diff --git a/src/GeneralTools/DataverseClient/Client/DataverseTraceLogger.cs b/src/GeneralTools/DataverseClient/Client/DataverseTraceLogger.cs
index 650840a..2dfae38 100644
--- a/src/GeneralTools/DataverseClient/Client/DataverseTraceLogger.cs
+++ b/src/GeneralTools/DataverseClient/Client/DataverseTraceLogger.cs
@@ -169,8 +169,14 @@ public override void Log(string message, TraceEventType eventType, Exception exc
// check and or alter the exception is its and HTTPOperationExecption.
if (exception is HttpOperationException httpOperationException)
{
- JObject contentBody = JObject.Parse(httpOperationException.Response.Content);
- Utils.DataverseOperationException webApiExcept = new Utils.DataverseOperationException(string.IsNullOrEmpty(contentBody["error"]["message"]?.ToString()) ? "Not Provided" : GetFirstLineFromString(contentBody["error"]["message"]?.ToString()).Trim(), httpOperationException);
+ string errorMessage = "Not Provided";
+ if (!string.IsNullOrWhiteSpace(httpOperationException.Response.Content))
+ {
+ JObject contentBody = JObject.Parse(httpOperationException.Response.Content);
+ errorMessage = string.IsNullOrEmpty(contentBody["error"]["message"]?.ToString()) ? "Not Provided" : GetFirstLineFromString(contentBody["error"]["message"]?.ToString()).Trim();
+ }
+
+ Utils.DataverseOperationException webApiExcept = new Utils.DataverseOperationException(errorMessage, httpOperationException);
LastException = webApiExcept;
}
else
@@ -249,9 +255,19 @@ public void LogException(OrganizationRequest req, Exception ex, string errorStri
}
else if (ex is HttpOperationException httpOperationException)
{
- JObject contentBody = JObject.Parse(httpOperationException.Response.Content);
+ string errorMessage;
+ if (!string.IsNullOrWhiteSpace(httpOperationException.Response.Content))
+ {
+ JObject contentBody = JObject.Parse(httpOperationException.Response.Content);
+ errorMessage = DataverseTraceLogger.GetFirstLineFromString(contentBody["error"]["message"].ToString()).Trim();
+ }
+ else
+ {
+ errorMessage = httpOperationException.Response.StatusCode.ToString();
+ }
+
DataverseOperationException ex01 = DataverseOperationException.GenerateClientOperationException(httpOperationException);
- Log(string.Format(CultureInfo.InvariantCulture, "************ {3} - {2} : {0} |=> {1}", errorStringCheck, DataverseTraceLogger.GetFirstLineFromString(contentBody["error"]["message"].ToString()).Trim(), webUriMessageReq, ex.GetType().Name), TraceEventType.Error, ex01);
+ Log(string.Format(CultureInfo.InvariantCulture, "************ {3} - {2} : {0} |=> {1}", errorStringCheck, errorMessage, webUriMessageReq, ex.GetType().Name), TraceEventType.Error, ex01);
}
else
{
@@ -294,8 +310,15 @@ public void LogFailure(OrganizationRequest req, Guid requestTrackingId, Guid? se
DataverseOperationException ex01 = DataverseOperationException.GenerateClientOperationException(httpOperationException);
try
{
- JObject contentBody = JObject.Parse(httpOperationException.Response.Content);
- errorMessage = DataverseTraceLogger.GetFirstLineFromString(contentBody["error"]["message"].ToString()).Trim();
+ if (!string.IsNullOrWhiteSpace(httpOperationException.Response.Content))
+ {
+ JObject contentBody = JObject.Parse(httpOperationException.Response.Content);
+ errorMessage = DataverseTraceLogger.GetFirstLineFromString(contentBody["error"]["message"].ToString()).Trim();
+ }
+ else
+ {
+ errorMessage = httpOperationException.Response.StatusCode.ToString();
+ }
}
catch (Exception)
{
diff --git a/src/GeneralTools/DataverseClient/Client/Microsoft.PowerPlatform.Dataverse.Client.csproj b/src/GeneralTools/DataverseClient/Client/Microsoft.PowerPlatform.Dataverse.Client.csproj
index 1104511..6ef91aa 100644
--- a/src/GeneralTools/DataverseClient/Client/Microsoft.PowerPlatform.Dataverse.Client.csproj
+++ b/src/GeneralTools/DataverseClient/Client/Microsoft.PowerPlatform.Dataverse.Client.csproj
@@ -1,4 +1,4 @@
-
+
Microsoft.PowerPlatform.Dataverse.Client
@@ -11,6 +11,7 @@
false
$(OutDir)\Microsoft.PowerPlatform.Dataverse.Client.xml
+ 6.0
@@ -38,12 +39,12 @@
-
-
+
+
-
+
diff --git a/src/GeneralTools/DataverseClient/Client/Model/ConfigurationOptions.cs b/src/GeneralTools/DataverseClient/Client/Model/ConfigurationOptions.cs
index 1ad1a39..8a439ac 100644
--- a/src/GeneralTools/DataverseClient/Client/Model/ConfigurationOptions.cs
+++ b/src/GeneralTools/DataverseClient/Client/Model/ConfigurationOptions.cs
@@ -71,7 +71,7 @@ public bool UseWebApi
set => _useWebApi = value;
}
- private bool _useWebApiLoginFlow = Utils.AppSettingsHelper.GetAppSetting("UseWebApiLoginFlow", false);
+ private bool _useWebApiLoginFlow = Utils.AppSettingsHelper.GetAppSetting("UseWebApiLoginFlow", true);
///
/// Use Web API instead of org service for logging into and getting boot up data.
///
diff --git a/src/GeneralTools/DataverseClient/Client/Model/DiscoveryServers.cs b/src/GeneralTools/DataverseClient/Client/Model/DiscoveryServers.cs
index d42df69..4bd9054 100644
--- a/src/GeneralTools/DataverseClient/Client/Model/DiscoveryServers.cs
+++ b/src/GeneralTools/DataverseClient/Client/Model/DiscoveryServers.cs
@@ -55,6 +55,7 @@ public DiscoveryServers()
_OSDPServers.Add(new DiscoveryServer() { DiscoveryServerUri = new Uri("https://disco.crm.dynamics.com/XRMServices/2011/Discovery.svc"), DisplayName = "North America", ShortName = "NorthAmerica" }); // Do not add Geo code to NAM or GCC, as they use the same server level GEO code.
_OSDPServers.Add(new DiscoveryServer() { DiscoveryServerUri = new Uri("https://disco.crm9.dynamics.com/XRMServices/2011/Discovery.svc"), DisplayName = "North America 2", ShortName = "NorthAmerica2", RequiresRegionalDiscovery = true, RegionalGlobalDiscoveryServer = new Uri("https://globaldisco.crm9.dynamics.com") });
_OSDPServers.Add(new DiscoveryServer() { DiscoveryServerUri = new Uri("https://disco.crm19.dynamics.com/XRMServices/2011/Discovery.svc"), DisplayName = "Norway", ShortName = "NOR", GeoCode = "NOR" });
+ _OSDPServers.Add(new DiscoveryServer() { DiscoveryServerUri = new Uri("https://disco.crm20.dynamics.com/XRMServices/2011/Discovery.svc"), DisplayName = "Singapore", ShortName = "SGP", GeoCode = "SGP" });
_OSDPServers.Add(new DiscoveryServer() { DiscoveryServerUri = new Uri("https://disco.crm6.dynamics.com/XRMServices/2011/Discovery.svc"), DisplayName = "Oceania", ShortName = "Oceania", GeoCode = "OCE" });
_OSDPServers.Add(new DiscoveryServer() { DiscoveryServerUri = new Uri("https://disco.crm14.dynamics.com/XRMServices/2011/Discovery.svc"), DisplayName = "South Africa", ShortName = "ZAF", GeoCode = "ZAF" });
_OSDPServers.Add(new DiscoveryServer() { DiscoveryServerUri = new Uri("https://disco.crm2.dynamics.com/XRMServices/2011/Discovery.svc"), DisplayName = "South America", ShortName = "SouthAmerica", GeoCode = "LATAM" });
diff --git a/src/GeneralTools/DataverseClient/Client/ServiceClient.cs b/src/GeneralTools/DataverseClient/Client/ServiceClient.cs
index e843083..945077d 100644
--- a/src/GeneralTools/DataverseClient/Client/ServiceClient.cs
+++ b/src/GeneralTools/DataverseClient/Client/ServiceClient.cs
@@ -1286,9 +1286,12 @@ internal void CreateServiceConnection(
catch (Exception ex)
{
if (_logEntry != null)
- _logEntry.Dispose();
+ _logEntry.Dispose();
- throw new DataverseConnectionException("Failed to connect to Dataverse", ex);
+ if (ex is AggregateException)
+ throw new DataverseConnectionException(ex.Message, ex);
+ else
+ throw new DataverseConnectionException("Failed to connect to Dataverse", ex);
}
}
}
@@ -2287,18 +2290,30 @@ public async Task CreateAsync(Entity entity, CancellationToken cancellatio
/// entity to create
/// Propagates notification that operations should be canceled.
/// Returns the newly created record
- public Task CreateAndReturnAsync(Entity entity, CancellationToken cancellationToken)
+ public async Task CreateAndReturnAsync(Entity entity, CancellationToken cancellationToken)
{
- throw new NotImplementedException();
+ CreateResponse resp = (CreateResponse)await ExecuteOrganizationRequestAsyncImpl(
+ new CreateRequest()
+ {
+ Target = entity
+ }
+ , cancellationToken
+ , "Create To Dataverse via IOrganizationService"
+ , useWebAPI: true).ConfigureAwait(false);
+
+ if (resp == null) throw LastException;
+
+ // Get the Response and query the entity with all fields.
+ return await RetrieveAsync(entity.LogicalName, resp.id, new ColumnSet(true)).ConfigureAwait(false);
}
///
/// Create an entity and process any related entities
///
/// entity to create
/// Returns the newly created record
- public Task CreateAndReturnAsync(Entity entity)
+ public async Task CreateAndReturnAsync(Entity entity)
{
- throw new NotImplementedException();
+ return await CreateAndReturnAsync(entity, CancellationToken.None).ConfigureAwait(false);
}
///
@@ -2442,12 +2457,6 @@ private void Dispose(bool disposing)
if (_connectionSvc != null)
{
- try
- {
- if (_connectionSvc.WebClient != null)
- _connectionSvc.WebClient.Dispose();
- }
- catch { }
_connectionSvc.Dispose();
}
@@ -2466,6 +2475,7 @@ private void Dispose(bool disposing)
public void Dispose()
{
Dispose(true);
+ GC.SuppressFinalize(this);
}
#endregion
}
diff --git a/src/GeneralTools/DataverseClient/Client/TestingHelper.cs b/src/GeneralTools/DataverseClient/Client/TestingHelper.cs
index 33978ea..7f7f0d6 100644
--- a/src/GeneralTools/DataverseClient/Client/TestingHelper.cs
+++ b/src/GeneralTools/DataverseClient/Client/TestingHelper.cs
@@ -251,10 +251,12 @@ public ServerInfo DataverseInternalTest
{
_dvInternalTest = new ServerInfo()
{
- DiscoveryServer = "https://disco.crm.crmtest.com/XRMServices/2011/Discovery.svc",
+ DiscoveryServer = "https://disco.crm.crmtest.dynamics.com/XRMServices/2011/Discovery.svc",
DisplayName = "Internal TEST",
ShortName = "TST",
- GeoCode="TST"
+ RequiresRegionalDiscovery = true,
+ RegionalGlobalDiscoveryUri = new Uri("https://globaldisco.crmtest.dynamics.com"),
+ GeoCode = "TST"
};
}
diff --git a/src/GeneralTools/DataverseClient/Client/Utils/DataverseConnectionException.cs b/src/GeneralTools/DataverseClient/Client/Utils/DataverseConnectionException.cs
index d084cf9..6acbc90 100644
--- a/src/GeneralTools/DataverseClient/Client/Utils/DataverseConnectionException.cs
+++ b/src/GeneralTools/DataverseClient/Client/Utils/DataverseConnectionException.cs
@@ -1,4 +1,8 @@
-using System;
+using Microsoft.Rest;
+using Newtonsoft.Json.Linq;
+using System;
+using System.Collections.Generic;
+using System.Linq;
using System.Runtime.Serialization;
namespace Microsoft.PowerPlatform.Dataverse.Client.Utils
@@ -10,7 +14,7 @@ namespace Microsoft.PowerPlatform.Dataverse.Client.Utils
public class DataverseConnectionException : Exception
{
///
- /// Creates a CdsService Client Exception
+ /// Creates a dataverse connection Exception
///
/// Error Message
public DataverseConnectionException(string message)
@@ -19,17 +23,18 @@ public DataverseConnectionException(string message)
}
///
- /// Creates a CdsService Client Exception
+ /// Creates a dataverse connection Exception
///
/// Error Message
/// Supporting Exception
public DataverseConnectionException(string message, Exception innerException)
: base(message, innerException)
{
+ this.HResult = innerException.HResult;
}
///
- /// Creates a CdsService Client Exception
+ /// Creates a dataverse connection Exception
///
///
///
@@ -37,5 +42,67 @@ protected DataverseConnectionException(SerializationInfo serializationInfo, Stre
: base(serializationInfo, streamingContext)
{
}
+
+ ///
+ /// Creates a dataverse connection Exception
+ ///
+ /// Error Message
+ /// Error code
+ /// Data Properties
+ /// Help Link
+ ///
+ public DataverseConnectionException(string message, int errorCode, string helpLink, IDictionary data, HttpOperationException httpOperationException = null)
+ : base(message, httpOperationException)
+ {
+ HResult = errorCode;
+ HelpLink = helpLink;
+ Source = "Dataverse Server API";
+ foreach (var itm in data)
+ {
+ this.Data.Add(itm.Key, itm.Value);
+ }
+ }
+
+ ///
+ /// Creates a Dataverse Connection Exception from an httpOperationError
+ ///
+ ///
+ ///
+ public static DataverseConnectionException GenerateClientConnectionException(HttpOperationException httpOperationException)
+ {
+ string errorDetailPrefixString = "@Microsoft.PowerApps.CDS.ErrorDetails.";
+ Dictionary cdsErrorData = new Dictionary();
+
+ JToken ErrorBlock = null;
+ try
+ {
+ if (!string.IsNullOrWhiteSpace(httpOperationException.Response.Content))
+ {
+ JObject contentBody = JObject.Parse(httpOperationException.Response.Content);
+ ErrorBlock = contentBody["error"];
+ }
+ }
+ catch { }
+
+ if (ErrorBlock != null)
+ {
+ string errorMessage = DataverseTraceLogger.GetFirstLineFromString(ErrorBlock["message"]?.ToString()).Trim();
+ var code = ErrorBlock["code"];
+ int HResult = code != null && !string.IsNullOrWhiteSpace(code.ToString()) ? Convert.ToInt32(code.ToString(), 16) : -1;
+
+ string HelpLink = ErrorBlock["@Microsoft.PowerApps.CDS.HelpLink"]?.ToString();
+
+ foreach (var node in ErrorBlock.ToArray())
+ {
+ if (node.Path.Contains(errorDetailPrefixString))
+ {
+ cdsErrorData.Add(node.Value().Name.ToString().Replace(errorDetailPrefixString, string.Empty), node.HasValues ? node.Value().Value.ToString() : string.Empty);
+ }
+ }
+ return new DataverseConnectionException(errorMessage, HResult, HelpLink, cdsErrorData, httpOperationException);
+ }
+ else
+ return new DataverseConnectionException("Server Error, no error report generated from server", -1, string.Empty, cdsErrorData, httpOperationException);
+ }
}
}
diff --git a/src/GeneralTools/DataverseClient/Client/Utils/DataverseOperationException.cs b/src/GeneralTools/DataverseClient/Client/Utils/DataverseOperationException.cs
index ef70c3c..b6f0f57 100644
--- a/src/GeneralTools/DataverseClient/Client/Utils/DataverseOperationException.cs
+++ b/src/GeneralTools/DataverseClient/Client/Utils/DataverseOperationException.cs
@@ -1,4 +1,4 @@
-using Microsoft.Rest;
+using Microsoft.Rest;
using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
@@ -56,8 +56,11 @@ public static DataverseOperationException GenerateClientOperationException(HttpO
JToken ErrorBlock = null;
try
{
- JObject contentBody = JObject.Parse(httpOperationException.Response.Content);
- ErrorBlock = contentBody["error"];
+ if (!string.IsNullOrWhiteSpace(httpOperationException.Response.Content))
+ {
+ JObject contentBody = JObject.Parse(httpOperationException.Response.Content);
+ ErrorBlock = contentBody["error"];
+ }
}
catch { }
diff --git a/src/GeneralTools/DataverseClient/Client/Utils/ServiceProviders.cs b/src/GeneralTools/DataverseClient/Client/Utils/ServiceProviders.cs
index 635a8b4..43b4a7f 100644
--- a/src/GeneralTools/DataverseClient/Client/Utils/ServiceProviders.cs
+++ b/src/GeneralTools/DataverseClient/Client/Utils/ServiceProviders.cs
@@ -1,4 +1,4 @@
-using Microsoft.Extensions.DependencyInjection;
+using Microsoft.Extensions.DependencyInjection;
using Microsoft.PowerPlatform.Dataverse.Client.Model;
using System;
using Microsoft.PowerPlatform.Dataverse.Client.Auth;
@@ -43,7 +43,7 @@ private static void BindServiceProviders()
var hander = new HttpClientHandler
{
UseCookies = false,
- //SslProtocols = System.Security.Authentication.SslProtocols.Tls12
+ AutomaticDecompression = System.Net.DecompressionMethods.Deflate | System.Net.DecompressionMethods.GZip
};
return hander;
});
@@ -51,6 +51,14 @@ private static void BindServiceProviders()
{
client.Timeout = sp.GetService>().Value.MSALRequestTimeout;
})
+ .ConfigurePrimaryHttpMessageHandler(() =>
+ {
+ var hander = new HttpClientHandler
+ {
+ AutomaticDecompression = System.Net.DecompressionMethods.Deflate | System.Net.DecompressionMethods.GZip
+ };
+ return hander;
+ })
.AddHttpMessageHandler(); // Adding on board retry hander for MSAL.
_instance = services.BuildServiceProvider();
}
diff --git a/src/GeneralTools/DataverseClient/Client/Utils/Utils.cs b/src/GeneralTools/DataverseClient/Client/Utils/Utils.cs
index f75baa1..c24fbad 100644
--- a/src/GeneralTools/DataverseClient/Client/Utils/Utils.cs
+++ b/src/GeneralTools/DataverseClient/Client/Utils/Utils.cs
@@ -3,9 +3,11 @@
using Microsoft.Extensions.Options;
using Microsoft.PowerPlatform.Dataverse.Client.Model;
using Microsoft.PowerPlatform.Dataverse.Client.Utils;
+using Microsoft.Rest;
using Microsoft.Xrm.Sdk;
using Microsoft.Xrm.Sdk.Discovery;
using Microsoft.Xrm.Sdk.Metadata;
+using Newtonsoft.Json.Linq;
using System;
using System.Collections;
using System.Collections.Concurrent;
@@ -834,7 +836,7 @@ internal static string ParseAltKeyCollection(KeyAttributeCollection keyValues)
keycollection += $"{itm.Key}={dtValue.ToUniversalTime().ToString("yyyy-MM-ddTHH:mm:ssZ", CultureInfo.InvariantCulture)},";
}
else
- keycollection += $"{itm.Key}='{itm.Value.ToString().Replace("'", "''")}',";
+ keycollection += $"{itm.Key}='{itm.Value?.ToString().Replace("'", "''")}',";
}
}
return keycollection.Remove(keycollection.Length - 1); // remove trailing ,
@@ -1235,5 +1237,38 @@ internal static void CleanUpHeaderKeys(WebHeaderCollection headerCollection)
}
#endregion
+ ///
+ /// Identity a given Child Exception on the exception stack
+ ///
+ ///
+ ///
+ ///
+ internal static T SeekExceptionOnStack(Exception e) where T : Exception
+ {
+ if ( e != null )
+ {
+ bool moreInnerRecords = true;
+ Exception exHold = e;
+ while (moreInnerRecords)
+ {
+ if (exHold is T)
+ {
+ return exHold as T;
+ }
+ else
+ {
+ if (exHold.InnerException != null)
+ {
+ moreInnerRecords = true;
+ exHold = e.InnerException;
+ }
+ else
+ moreInnerRecords = false;
+ }
+ }
+ }
+ return null;
+ }
+
}
}
diff --git a/src/GeneralTools/DataverseClient/Client/app.config b/src/GeneralTools/DataverseClient/Client/app.config
index 0e6e9fd..7572771 100644
--- a/src/GeneralTools/DataverseClient/Client/app.config
+++ b/src/GeneralTools/DataverseClient/Client/app.config
@@ -6,7 +6,7 @@
-
+
diff --git a/src/GeneralTools/DataverseClient/ConnectControl/Model/OnlineDiscoveryServers.cs b/src/GeneralTools/DataverseClient/ConnectControl/Model/OnlineDiscoveryServers.cs
index d6124dd..64b51c5 100644
--- a/src/GeneralTools/DataverseClient/ConnectControl/Model/OnlineDiscoveryServers.cs
+++ b/src/GeneralTools/DataverseClient/ConnectControl/Model/OnlineDiscoveryServers.cs
@@ -89,7 +89,8 @@ public OnlineDiscoveryServers()
RegionalServers.Add(new OnlineDiscoveryServer() { DiscoveryServer = new Uri("https://disco.crm.dynamics.com/XRMServices/2011/Discovery.svc"), DisplayName = "North America", ShortName = "NorthAmerica" }); // Do not add Geo code to NAM or GCC, as they use the same server level GEO code.
RegionalServers.Add(new OnlineDiscoveryServer() { DiscoveryServer = new Uri("https://disco.crm9.dynamics.com/XRMServices/2011/Discovery.svc"), DisplayName = "North America 2 (GCC)", ShortName = "NorthAmerica2", RequiresRegionalDiscovery = true, RegionalGlobalDiscoveryServer = new Uri("https://globaldisco.crm9.dynamics.com") });
RegionalServers.Add(new OnlineDiscoveryServer() { DiscoveryServer = new Uri("https://disco.crm19.dynamics.com/XRMServices/2011/Discovery.svc"), DisplayName = "Norway", ShortName = "NOR", GeoCode = "NOR" });
- RegionalServers.Add(new OnlineDiscoveryServer() { DiscoveryServer = new Uri("https://disco.crm6.dynamics.com/XRMServices/2011/Discovery.svc"), DisplayName = "Oceania", ShortName = "Oceania", GeoCode = "OCE" });
+ RegionalServers.Add(new OnlineDiscoveryServer() { DiscoveryServer = new Uri("https://disco.crm20.dynamics.com/XRMServices/2011/Discovery.svc"), DisplayName = "Singapore", ShortName = "SGP", GeoCode = "SGP" });
+ RegionalServers.Add(new OnlineDiscoveryServer() { DiscoveryServer = new Uri("https://disco.crm6.dynamics.com/XRMServices/2011/Discovery.svc"), DisplayName = "Oceania", ShortName = "Oceania", GeoCode = "OCE" });
RegionalServers.Add(new OnlineDiscoveryServer() { DiscoveryServer = new Uri("https://disco.crm14.dynamics.com/XRMServices/2011/Discovery.svc"), DisplayName = "South Africa", ShortName = "ZAF", GeoCode = "ZAF" });
RegionalServers.Add(new OnlineDiscoveryServer() { DiscoveryServer = new Uri("https://disco.crm2.dynamics.com/XRMServices/2011/Discovery.svc"), DisplayName = "South America", ShortName = "SouthAmerica", GeoCode = "LATAM" });
RegionalServers.Add(new OnlineDiscoveryServer() { DiscoveryServer = new Uri("https://disco.crm17.dynamics.com/XRMServices/2011/Discovery.svc"), DisplayName = "Switzerland", ShortName = "Switzerland", GeoCode = "CHE" });
@@ -110,7 +111,8 @@ public OnlineDiscoveryServers()
_OSDPServers.Add(new OnlineDiscoveryServer() { DiscoveryServer = new Uri("https://disco.crm.dynamics.com/XRMServices/2011/Discovery.svc"), DisplayName = "North America", ShortName = "NorthAmerica" }); // Do not add Geo code to NAM or GCC, as they use the same server level GEO code.
_OSDPServers.Add(new OnlineDiscoveryServer() { DiscoveryServer = new Uri("https://disco.crm9.dynamics.com/XRMServices/2011/Discovery.svc"), DisplayName = "North America 2 (GCC)", ShortName = "NorthAmerica2", RequiresRegionalDiscovery = true, RegionalGlobalDiscoveryServer = new Uri("https://globaldisco.crm9.dynamics.com") });
_OSDPServers.Add(new OnlineDiscoveryServer() { DiscoveryServer = new Uri("https://disco.crm19.dynamics.com/XRMServices/2011/Discovery.svc"), DisplayName = "Norway", ShortName = "NOR", GeoCode = "NOR" });
- _OSDPServers.Add(new OnlineDiscoveryServer() { DiscoveryServer = new Uri("https://disco.crm6.dynamics.com/XRMServices/2011/Discovery.svc"), DisplayName = "Oceania", ShortName = "Oceania", GeoCode = "OCE" });
+ _OSDPServers.Add(new OnlineDiscoveryServer() { DiscoveryServer = new Uri("https://disco.crm20.dynamics.com/XRMServices/2011/Discovery.svc"), DisplayName = "Singapore", ShortName = "SGP", GeoCode = "SGP" });
+ _OSDPServers.Add(new OnlineDiscoveryServer() { DiscoveryServer = new Uri("https://disco.crm6.dynamics.com/XRMServices/2011/Discovery.svc"), DisplayName = "Oceania", ShortName = "Oceania", GeoCode = "OCE" });
_OSDPServers.Add(new OnlineDiscoveryServer() { DiscoveryServer = new Uri("https://disco.crm14.dynamics.com/XRMServices/2011/Discovery.svc"), DisplayName = "South Africa", ShortName = "ZAF", GeoCode = "ZAF" });
_OSDPServers.Add(new OnlineDiscoveryServer() { DiscoveryServer = new Uri("https://disco.crm2.dynamics.com/XRMServices/2011/Discovery.svc"), DisplayName = "South America", ShortName = "SouthAmerica", GeoCode = "LATAM" });
_OSDPServers.Add(new OnlineDiscoveryServer() { DiscoveryServer = new Uri("https://disco.crm17.dynamics.com/XRMServices/2011/Discovery.svc"), DisplayName = "Switzerland", ShortName = "Switzerland", GeoCode = "CHE" });
diff --git a/src/GeneralTools/DataverseClient/ConnectControl/Properties/Messages.Designer.cs b/src/GeneralTools/DataverseClient/ConnectControl/Properties/Messages.Designer.cs
index 7735d40..932296a 100644
--- a/src/GeneralTools/DataverseClient/ConnectControl/Properties/Messages.Designer.cs
+++ b/src/GeneralTools/DataverseClient/ConnectControl/Properties/Messages.Designer.cs
@@ -338,5 +338,14 @@ internal static string CRMCONNECT_SERVER_CONNECT_GOOD {
return ResourceManager.GetString("CRMCONNECT_SERVER_CONNECT_GOOD", resourceCulture);
}
}
+
+ ///
+ /// Looks up a localized string similar to Dataverse Login Control.
+ ///
+ internal static string SERVER_LOGINCONTROL_LOCALIZEDCONTROLTYPE {
+ get {
+ return ResourceManager.GetString("SERVER_LOGINCONTROL_LOCALIZEDCONTROLTYPE", resourceCulture);
+ }
+ }
}
}
diff --git a/src/GeneralTools/DataverseClient/ConnectControl/Properties/Messages.resx b/src/GeneralTools/DataverseClient/ConnectControl/Properties/Messages.resx
index 9924dbd..8ba8dd7 100644
--- a/src/GeneralTools/DataverseClient/ConnectControl/Properties/Messages.resx
+++ b/src/GeneralTools/DataverseClient/ConnectControl/Properties/Messages.resx
@@ -213,4 +213,7 @@
Connection to Microsoft Dataverse Complete
+
+ Dataverse Login Control
+
\ No newline at end of file
diff --git a/src/GeneralTools/DataverseClient/ConnectControl/ServerLoginControl.xaml.cs b/src/GeneralTools/DataverseClient/ConnectControl/ServerLoginControl.xaml.cs
index 2e71f26..9136121 100644
--- a/src/GeneralTools/DataverseClient/ConnectControl/ServerLoginControl.xaml.cs
+++ b/src/GeneralTools/DataverseClient/ConnectControl/ServerLoginControl.xaml.cs
@@ -21,6 +21,8 @@
using System.Configuration;
using Microsoft.PowerPlatform.Dataverse.Client.Model;
using System.Media;
+using System.Windows.Automation.Peers;
+
#endregion
namespace Microsoft.PowerPlatform.Dataverse.ConnectControl
@@ -1341,13 +1343,48 @@ private void ddlAuthSource_SelectionChanged(object sender, SelectionChangedEvent
private void cbUseSSL_Click(object sender, RoutedEventArgs e)
{
- //if ((ddlAuthSource.SelectedIndex == 1 && cbUseSSL.IsChecked == true) || (ddlAuthSource.SelectedIndex == 2 && cbUseSSL.IsChecked == true))
- //{
- // cbAskforOrg.IsChecked = false;
- // cbAskforOrg.Visibility = Visibility.Visible;
- //}
- //else
- // cbAskforOrg.Visibility = Visibility.Visible;
- }
- }
+ //if ((ddlAuthSource.SelectedIndex == 1 && cbUseSSL.IsChecked == true) || (ddlAuthSource.SelectedIndex == 2 && cbUseSSL.IsChecked == true))
+ //{
+ // cbAskforOrg.IsChecked = false;
+ // cbAskforOrg.Visibility = Visibility.Visible;
+ //}
+ //else
+ // cbAskforOrg.Visibility = Visibility.Visible;
+ }
+
+ ///
+ /// Creates Automation Peer for accessibility needs of custom controls.
+ ///
+ /// AutomationPeer
+ protected override AutomationPeer OnCreateAutomationPeer()
+ {
+ return new ServerLoginControlAutomationPeer(this);
+ }
+ }
+
+
+ ///
+ /// Creates localizedcontroltype for ServerLoginControl
+ /// Refer https://learn.microsoft.com/en-us/accessibility-tools-docs/items/wpf/customcontrol_localizedcontroltype
+ ///
+ public class ServerLoginControlAutomationPeer : UserControlAutomationPeer
+ {
+ ///
+ /// default constructor
+ ///
+ ///
+ public ServerLoginControlAutomationPeer(ServerLoginControl owner) :
+ base(owner)
+ {
+ }
+
+ ///
+ /// localizedcontroltype for ServerLoginControl
+ ///
+ /// localized controltype for ServerLoginControl
+ protected override string GetLocalizedControlTypeCore()
+ {
+ return uiMessages.SERVER_LOGINCONTROL_LOCALIZEDCONTROLTYPE;
+ }
+ }
}
\ No newline at end of file
diff --git a/src/GeneralTools/DataverseClient/ConnectControl/app.config b/src/GeneralTools/DataverseClient/ConnectControl/app.config
index 2bbe771..a0cefc2 100644
--- a/src/GeneralTools/DataverseClient/ConnectControl/app.config
+++ b/src/GeneralTools/DataverseClient/ConnectControl/app.config
@@ -4,7 +4,7 @@
-
+
diff --git a/src/GeneralTools/DataverseClient/Testers/LoginControlTester/app.config b/src/GeneralTools/DataverseClient/Testers/LoginControlTester/app.config
index 3e7b3f2..06ecd74 100644
--- a/src/GeneralTools/DataverseClient/Testers/LoginControlTester/app.config
+++ b/src/GeneralTools/DataverseClient/Testers/LoginControlTester/app.config
@@ -91,7 +91,7 @@
-
+
diff --git a/src/GeneralTools/DataverseClient/UnitTests/CdsClient_Core_Tests/AuthResolverTests.cs b/src/GeneralTools/DataverseClient/UnitTests/CdsClient_Core_Tests/AuthResolverTests.cs
index 426c373..ea09a86 100644
--- a/src/GeneralTools/DataverseClient/UnitTests/CdsClient_Core_Tests/AuthResolverTests.cs
+++ b/src/GeneralTools/DataverseClient/UnitTests/CdsClient_Core_Tests/AuthResolverTests.cs
@@ -41,7 +41,7 @@ public async Task ProbeSuccessful(string expectedAuthority, string expectedResou
_msgHandler.ResponseHeader = responseHeader;
_msgHandler.ResponseStatus = expectedStatus;
- var details = await resolver.ProbeForExpectedAuthentication(endpoint);
+ var details = await resolver.ProbeForExpectedAuthentication(endpoint).ConfigureAwait(false);
details.Success.Should().Be(success);
if (success)
@@ -67,7 +67,7 @@ public async void DnsErrorsHandled()
});
_msgHandler.ErrorOnSend = true;
- var details = await resolver.ProbeForExpectedAuthentication(endpoint);
+ var details = await resolver.ProbeForExpectedAuthentication(endpoint).ConfigureAwait(false);
details.Success.Should().BeFalse();
log.Count.Should().BeGreaterOrEqualTo(1);
}
diff --git a/src/GeneralTools/DataverseClient/UnitTests/CdsClient_Core_Tests/DataverseClient_Core_UnitTests.csproj b/src/GeneralTools/DataverseClient/UnitTests/CdsClient_Core_Tests/DataverseClient_Core_UnitTests.csproj
index 09247a6..ca10adc 100644
--- a/src/GeneralTools/DataverseClient/UnitTests/CdsClient_Core_Tests/DataverseClient_Core_UnitTests.csproj
+++ b/src/GeneralTools/DataverseClient/UnitTests/CdsClient_Core_Tests/DataverseClient_Core_UnitTests.csproj
@@ -3,7 +3,7 @@
true
- net462;netcoreapp3.1
+ net462;net6.0
true
DataverseClient-Tests
false
diff --git a/src/GeneralTools/DataverseClient/UnitTests/CdsClient_Core_Tests/ServiceClientTests.cs b/src/GeneralTools/DataverseClient/UnitTests/CdsClient_Core_Tests/ServiceClientTests.cs
index 686557c..b7be126 100644
--- a/src/GeneralTools/DataverseClient/UnitTests/CdsClient_Core_Tests/ServiceClientTests.cs
+++ b/src/GeneralTools/DataverseClient/UnitTests/CdsClient_Core_Tests/ServiceClientTests.cs
@@ -92,7 +92,7 @@ public void TestThrowDisposedOperationCheck()
Assert.ThrowsAsync(async () =>
{
cli.Dispose();
- _ = (WhoAmIResponse) await cli.ExecuteAsync(new WhoAmIRequest());
+ _ = (WhoAmIResponse) await cli.ExecuteAsync(new WhoAmIRequest()).ConfigureAwait(false);
});
}
diff --git a/src/GeneralTools/DataverseClient/UnitTests/CdsClient_Core_Tests/UtilsTests.cs b/src/GeneralTools/DataverseClient/UnitTests/CdsClient_Core_Tests/UtilsTests.cs
index 35b8eee..c32ad20 100644
--- a/src/GeneralTools/DataverseClient/UnitTests/CdsClient_Core_Tests/UtilsTests.cs
+++ b/src/GeneralTools/DataverseClient/UnitTests/CdsClient_Core_Tests/UtilsTests.cs
@@ -1,8 +1,10 @@
#region using
using FluentAssertions;
using Microsoft.Crm.Sdk.Messages;
+using Microsoft.PowerPlatform.Dataverse.Client;
using Microsoft.PowerPlatform.Dataverse.Client.InternalExtensions;
using Microsoft.PowerPlatform.Dataverse.Client.Utils;
+using Microsoft.Xrm.Sdk;
using System;
using System.Collections.Generic;
using System.Linq;
@@ -26,5 +28,21 @@ public void SerializationTest()
json.Should().Contain("\"SolutionName\":\"SerializationTest\"");
json.Should().Contain("\"Managed\":false");
}
+
+ [Fact]
+ public void ParseAltKeyCollection_WithNulls_Test()
+ {
+ var keyValuePairs = new KeyAttributeCollection
+ {
+ { "NotNull", "TestValue" },
+ { "NullValue", null }
+ };
+
+ var result = Utilities.ParseAltKeyCollection(keyValuePairs);
+
+ result.Should().NotBeNullOrWhiteSpace();
+ result.Should().Contain("NotNull='TestValue'");
+ result.Should().Contain("NullValue=''");
+ }
}
}
diff --git a/src/GeneralTools/DataverseClient/UnitTests/LivePackageRunUnitTests/LivePackageRunUnitTests.csproj b/src/GeneralTools/DataverseClient/UnitTests/LivePackageRunUnitTests/LivePackageRunUnitTests.csproj
index a30ebb5..d85efa8 100644
--- a/src/GeneralTools/DataverseClient/UnitTests/LivePackageRunUnitTests/LivePackageRunUnitTests.csproj
+++ b/src/GeneralTools/DataverseClient/UnitTests/LivePackageRunUnitTests/LivePackageRunUnitTests.csproj
@@ -3,7 +3,8 @@
true
- net462;net472;net48;netcoreapp3.1;net5.0
+ false
+ net462;net472;net48;netcoreapp3.1;net6.0
true
DataverseClient-Tests-Package
false
diff --git a/src/GeneralTools/DataverseClient/UnitTests/LivePackageTestsConsole/LivePackageTestsConsole.csproj b/src/GeneralTools/DataverseClient/UnitTests/LivePackageTestsConsole/LivePackageTestsConsole.csproj
index e3bc026..6de87de 100644
--- a/src/GeneralTools/DataverseClient/UnitTests/LivePackageTestsConsole/LivePackageTestsConsole.csproj
+++ b/src/GeneralTools/DataverseClient/UnitTests/LivePackageTestsConsole/LivePackageTestsConsole.csproj
@@ -16,7 +16,8 @@
$(RepoRoot)\binSigned\$(Configuration)\packages
- 0.5.9
+ false
+ 1.0.26
$(MSBuildThisFileDirectory)..\.packages
@@ -29,6 +30,7 @@
+
diff --git a/src/GeneralTools/DataverseClient/WebResourceUtility/app.config b/src/GeneralTools/DataverseClient/WebResourceUtility/app.config
index 2bbe771..a0cefc2 100644
--- a/src/GeneralTools/DataverseClient/WebResourceUtility/app.config
+++ b/src/GeneralTools/DataverseClient/WebResourceUtility/app.config
@@ -4,7 +4,7 @@
-
+
diff --git a/src/nuspecs/Microsoft.PowerPlatform.Dataverse.Client.Dynamics.nuspec b/src/nuspecs/Microsoft.PowerPlatform.Dataverse.Client.Dynamics.nuspec
index bdba207..8ce8b0f 100644
--- a/src/nuspecs/Microsoft.PowerPlatform.Dataverse.Client.Dynamics.nuspec
+++ b/src/nuspecs/Microsoft.PowerPlatform.Dataverse.Client.Dynamics.nuspec
@@ -26,6 +26,9 @@
+
+
+
@@ -44,6 +47,8 @@
+
+
diff --git a/src/nuspecs/Microsoft.PowerPlatform.Dataverse.Client.ReleaseNotes.txt b/src/nuspecs/Microsoft.PowerPlatform.Dataverse.Client.ReleaseNotes.txt
index 444cb51..1bb0a88 100644
--- a/src/nuspecs/Microsoft.PowerPlatform.Dataverse.Client.ReleaseNotes.txt
+++ b/src/nuspecs/Microsoft.PowerPlatform.Dataverse.Client.ReleaseNotes.txt
@@ -7,6 +7,21 @@ Notice:
Note: Only AD on FullFramework, OAuth, Certificate, ClientSecret Authentication types are supported at this time.
++CURRENTRELEASEID++
+Added .net 6.0 Target for the Client.
+Added implementation for CreateAndReturnAsync variations.
+Updated Default Login flow to use WebAPI to allow for detecting Admin Mode on server during login.
+ A Environment in Admin mode will now throw DataverseConnectionException an error with the text "One or more errors occurred. (User does not have required privileges (or role membership) to access the org when it is in Admin Only mode.)"
+Updated Improved error reporting of standard HTTP status codes
+Updated ServiceClient Bootstrap to improve startup time.
+Fix (Speculative) for Memory Leak in Retrieve Multiple
+Fix for issue with cross thread calls and dispose were External authentication is used.
+Fix for inappropriate retry operations. Unauthorized errors are no longer retried during WebAPI calls
+Fix to enabled GZip Compression for WebAPI requests.
+Dependency changes:
+ System.Text.Json moved to 6.0.7 min dependency (transient dependency is vulnerable to CVE-2022-34716).
+ System.ServiceModel.Http moved to 4.10.0 due min dependency (transient dependency is vulnerable to CVE-2021-24112).
+
+1.0.26:
Fix by Git user matkov accepted for crash during create when an invalid timespan is passed from a configuration file to the ServiceClient Constructor. See https://github.com/microsoft/PowerPlatform-DataverseServiceClient/issues/326 for details.
Fix by GIT user 0xced accepted for bug in Integrated user security setting, Code will now properly honor integrated security when attempting to authenticate. See https://github.com/microsoft/PowerPlatform-DataverseServiceClient/pull/324 for details.
Fixed a number of places where Async Calls did not have a .ConfigureAwait specification. Thanks to user 0xced for prompting this fix.
@@ -17,7 +32,7 @@ Fixed issue where calling the IOrganizationService* interfaces after the client
Removed a set of exception catch and rethrows to preserve the full callstack to caller. Thanks to Git user 0xceed for prompting ( and sticking with getting us to ) this fix. See: https://github.com/microsoft/PowerPlatform-DataverseServiceClient/pull/248 for details.
-1.0.23
+1.0.23:
Added Async version of ExecuteOrganizationRequest to allow for requests to be made bounded with a custom logging message.
Update Default settings for "UseWebAPI" in preparation for future work.
Note: for Create or Update operations that make extensive use of related entities you may need to reconfigure UseWebAPI to "true".
diff --git a/src/nuspecs/Microsoft.PowerPlatform.Dataverse.Client.nuspec b/src/nuspecs/Microsoft.PowerPlatform.Dataverse.Client.nuspec
index e1744b0..4915fd4 100644
--- a/src/nuspecs/Microsoft.PowerPlatform.Dataverse.Client.nuspec
+++ b/src/nuspecs/Microsoft.PowerPlatform.Dataverse.Client.nuspec
@@ -23,7 +23,7 @@
-
+
@@ -34,7 +34,7 @@
-
+
@@ -45,7 +45,7 @@
-
+
@@ -59,10 +59,8 @@
-
-
-
-
+
+
@@ -76,7 +74,39 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -95,21 +125,40 @@
-
+
+
+
+
+
+
+
+
+
+
+
-
+
+
+
+
-
+
+
+
+
-
+
+
+
+