Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Failed to Clone connection #467

Open
MitchellW-DWL opened this issue Sep 13, 2024 · 3 comments
Open

Failed to Clone connection #467

MitchellW-DWL opened this issue Sep 13, 2024 · 3 comments
Labels
Investigating We are looking into this issue at this time.

Comments

@MitchellW-DWL
Copy link

MitchellW-DWL commented Sep 13, 2024

Hi guys - been seeing a pretty transient error occasionally on any request to Dynamics in asp.net core WebApi

Version: 1.0.39
(Upgraded to 1.1.32 at the time of writing this but dont expect this will have resolved it - will update if i see this come up again)

Code Context

So using .net8 (Only recently moved to net8 from net6 within last couple of weeks but was seeing it in net6 too)

My DI is setup like so:

sc.AddSingleton<IServiceClientFactory, ServiceClientFactory>();
sc.AddScoped<ServiceClient>(sp => sp.GetRequiredService<IServiceClientFactory>().CreateServiceClient());

Then the ServiceClientFactory singleton is just:

public class ServiceClientFactory : IServiceClientFactory
{
    private readonly Lazy<ServiceClient> _serviceClient;

    public ServiceClientFactory(DynamicsConfiguration dynamicsConfiguration, ILogger<ServiceClient> logger)
    {
        _serviceClient = new Lazy<ServiceClient>(() => new ServiceClient(
            new Uri(dynamicsConfiguration.CrmUrl),
            dynamicsConfiguration.ClientId,
            dynamicsConfiguration.AppKey,
            false,
            logger));
    }

    public ServiceClient CreateServiceClient()
        => _serviceClient.Value.Clone();
}

Would appreciate any recommendations on

Here's a trace for the error what I'm seeing:

StackTrace

Microsoft.PowerPlatform.Dataverse.Client.Utils.DataverseConnectionException: Failed to Clone Connection
    ---> Microsoft.PowerPlatform.Dataverse.Client.Utils.DataverseOperationException: Failed constructing cloned connection. debugstate=1
    ---> System.AggregateException: One or more errors occurred. (Exception - Failed to lookup current user)
    ---> Microsoft.PowerPlatform.Dataverse.Client.Utils.DataverseOperationException: Exception - Failed to lookup current user
    ---> System.NullReferenceException: Object reference not set to an instance of an object.
      at Microsoft.PowerPlatform.Dataverse.Client.ConnectionService.Command_WebExecuteAsync(String queryString, String body, HttpMethod method, Dictionary`2 customHeaders, String contentType, String errorStringCheck, Guid callerId, Boolean disableConnectionLocking, Int32 maxRetryCount, TimeSpan retryPauseTime, Uri uriOfInstance, Guid requestTrackingId, CancellationToken cancellationToken)
      at Microsoft.PowerPlatform.Dataverse.Client.ConnectionService.Command_WebAPIProcess_ExecuteAsync(OrganizationRequest req, String logMessageTag, Boolean bypassPluginExecution, MetadataUtility metadataUtlity, Guid callerId, Boolean disableConnectionLocking, Int32 maxRetryCount, TimeSpan retryPauseTime, CancellationToken cancellationToken, Uri uriOfInstance, Boolean inLoginFlow)
      at Microsoft.PowerPlatform.Dataverse.Client.ConnectionService.GetWhoAmIDetails(IOrganizationService dvService, Guid trackingID)
      --- End of inner exception stack trace ---
      at Microsoft.PowerPlatform.Dataverse.Client.ConnectionService.GetWhoAmIDetails(IOrganizationService dvService, Guid trackingID)
      at Microsoft.PowerPlatform.Dataverse.Client.ServiceClient.<get_SystemUser>b__62_0()
      --- End of inner exception stack trace ---
      at System.Threading.Tasks.Task.ThrowIfExceptional(Boolean includeTaskCanceledExceptions)
      at System.Threading.Tasks.Task`1.GetResultCore(Boolean waitCompletionNotification)
      at Microsoft.PowerPlatform.Dataverse.Client.ServiceClient.get_SystemUser()
      at Microsoft.PowerPlatform.Dataverse.Client.ConnectionService.SetClonedProperties(ServiceClient sourceClient)
      --- End of inner exception stack trace ---
      at Microsoft.PowerPlatform.Dataverse.Client.ConnectionService.SetClonedProperties(ServiceClient sourceClient)
      at Microsoft.PowerPlatform.Dataverse.Client.ServiceClient.Clone(Assembly strongTypeAsm, ILogger logger)
      --- End of inner exception stack trace ---
      at Microsoft.PowerPlatform.Dataverse.Client.ServiceClient.Clone(Assembly strongTypeAsm, ILogger logger)
      at Microsoft.PowerPlatform.Dataverse.Client.ServiceClient.Clone(ILogger logger)
      at DWL.Lib.Dynamics.Services.ServiceClientFactory.CreateServiceClient()
      at DWL.Lib.Dynamics.Extensions.ServiceCollectionExtensions.<>c.<AddDwlDynamicsServices>b__0_0(IServiceProvider sp)
      at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor`2.VisitCallSiteMain(ServiceCallSite callSite, TArgument argument)
      at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitCache(ServiceCallSite callSite, RuntimeResolverContext context, ServiceProviderEngineScope serviceProviderEngine, RuntimeResolverLock lockType)
      at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitScopeCache(ServiceCallSite callSite, RuntimeResolverContext context)
      at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor`2.VisitCallSite(ServiceCallSite callSite, TArgument argument)
      at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitConstructor(ConstructorCallSite constructorCallSite, RuntimeResolverContext context)
      at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor`2.VisitCallSiteMain(ServiceCallSite callSite, TArgument argument)
      at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitCache(ServiceCallSite callSite, RuntimeResolverContext context, ServiceProviderEngineScope serviceProviderEngine, RuntimeResolverLock lockType)
      at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitScopeCache(ServiceCallSite callSite, RuntimeResolverContext context)
      at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor`2.VisitCallSite(ServiceCallSite callSite, TArgument argument)
      at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitConstructor(ConstructorCallSite constructorCallSite, RuntimeResolverContext context)
      at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor`2.VisitCallSiteMain(ServiceCallSite callSite, TArgument argument)
      at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitDisposeCache(ServiceCallSite transientCallSite, RuntimeResolverContext context)
      at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor`2.VisitCallSite(ServiceCallSite callSite, TArgument argument)
      at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.Resolve(ServiceCallSite callSite, ServiceProviderEngineScope scope)
      at Microsoft.Extensions.DependencyInjection.ServiceLookup.DynamicServiceProviderEngine.<>c__DisplayClass2_0.<RealizeService>b__0(ServiceProviderEngineScope scope)
      at Microsoft.Extensions.DependencyInjection.ServiceProvider.GetService(ServiceIdentifier serviceIdentifier, ServiceProviderEngineScope serviceProviderEngineScope)
      at Microsoft.Extensions.DependencyInjection.ServiceLookup.ServiceProviderEngineScope.GetService(Type serviceType)
      at Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService(IServiceProvider provider, Type serviceType)
      at Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService[T](IServiceProvider provider)
      at MediatR.Wrappers.RequestHandlerWrapperImpl`2.<>c__DisplayClass1_0.<Handle>g__Handler|0()

Looking through some other issues I've noticed #362 seems to be throwing the same error albeit in a different context, but is also making use of .Clone()

@MattB-msft
Copy link
Member

Thanks for reporting this and the stack trace, this helps.
We will have a look.

In general though we have altered our guidance away from using clone on Azure Functions or Azure WebAps and instead to use the Async methods of the clients.

@MattB-msft MattB-msft added the Investigating We are looking into this issue at this time. label Sep 29, 2024
@MitchellW-DWL
Copy link
Author

Thanks for reporting this and the stack trace, this helps. We will have a look.

In general though we have altered our guidance away from using clone on Azure Functions or Azure WebAps and instead to use the Async methods of the clients.

We're hosting in an azure WebApp, in this instance would this mean creating a new ServiceClient instance for every request? I believe per my previous testing this took about 10s to initialise a new instance given the secret and whatnot.

Or would there be a singleton instance shared across all requests coming in? In which case how would the impersonation logic look? At current I'm just doing:

        _serviceClient.CallerAADObjectId = impersonateAs;
        _ = await _serviceClient.ExecuteAsync(executeMultipleRequest, cancellationToken);

But would be concerned about potentially wrong impersonations with a shared singleton instance?

Thanks for investigating too btw :)

@FarmerenHE
Copy link

But would be concerned about potentially wrong impersonations with a shared singleton instance?

You should save it in a shared instance, you could have a Dictonary<Guid, ServiceClient> where you create a connection pr. impersonateAs (you need to test it to validate its not one of the shared properties between instances of the serviceclient).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Investigating We are looking into this issue at this time.
Projects
None yet
Development

No branches or pull requests

3 participants