pnp / pnpcore

The PnP Core SDK is a modern .NET SDK designed to work for Microsoft 365. It provides a unified object model for working with SharePoint Online and Teams which is agnostic to the underlying API's being called
https://aka.ms/pnp/coresdk/docs
MIT License
306 stars 192 forks source link

Console App Automatically crashes when running some functions. However in single step movement using debug, it works #478

Closed gopaldahal closed 3 years ago

gopaldahal commented 3 years ago

Category

Describe the bug

The application automatically shutdowns with the incomplete operation.

Steps to reproduce

        var host = Host.CreateDefaultBuilder()
       .ConfigureServices((hostingContext, services) =>
        {
            services.AddPnPCore(options =>
                                        {
                                            options.PnPContext.GraphFirst = true;
                                            options.PnPContext.GraphCanUseBeta = true;
                                            options.PnPContext.GraphAlwaysUseBeta = false;
                                            options.HttpRequests.UserAgent = "ISV|Contoso|ABC";
                                            options.HttpRequests.MicrosoftGraph = new PnPCoreHttpRequestsGraphOptions
                                            {
                                                UseRetryAfterHeader = true,
                                                MaxRetries = 10,
                                                DelayInSeconds = 3,
                                                UseIncrementalDelay = true,
                                            };
                                            options.HttpRequests.SharePointRest = new PnPCoreHttpRequestsSharePointRestOptions
                                            {
                                                UseRetryAfterHeader = true,
                                                MaxRetries = 10,
                                                DelayInSeconds = 3,
                                                UseIncrementalDelay = true,
                                            };
                                            options.DefaultAuthenticationProvider = new InteractiveAuthenticationProvider(
                                                "XXX", // Client Id
                                                "YYY", // Tenant Id
                                                new Uri("https://login.microsoftonline.com/common/oauth2/nativeclient"));  // Redirect Id
                                        });
        })
        .Build();

        // Start console host
        await host.StartAsync();

        try
        {
            // Connect to SharePoint
            using (var scope = host.Services.CreateScope())
            {
                // Obtain a PnP Context factory
                var pnpContextFactory = scope.ServiceProvider.GetRequiredService<IPnPContextFactory>();

                // Use the PnP Context factory to get a PnPContext for the given configuration
                using (var context =  pnpContextFactory.Create(new Uri(ClientUrl)))
                {
                                    //GetListItems(context);
                    Console.ForegroundColor = ConsoleColor.Yellow;
                    Console.WriteLine("===ADD/UPDATE/DELETE: create/delete list and add 20 items in batch===");
                    Console.ResetColor();

                    var webDetail = await context.Web.GetAsync(s => s.Language, s => s.RegionalSettings);
                    var userLRS = true;

                    var parentList = await context.Web.Lists.GetByTitleAsync("AddTest", l => l.EnableModeration, l => l.TemplateType, l => l.EnableVersioning, l => l.Title, l => l.Fields, l => l.ContentTypes);
                    var parentWeb = await context.Web.GetAsync(s => s.Language, s => s.RegionalSettings, s=>s.Url);
                    var timeZone = await parentWeb.RegionalSettings.GetAsync(d => d.TimeZone);
                    var parentFields = parentList.Fields.ToList();
                }
            }
        }
        catch(Exception ex)
        {
        }

Expected behavior

It should be working with a charm on a straight run. Running only in debug mode.

Environment details (development & target environment)

Additional context

Thanks for your contribution! Sharing is caring.

jansenbe commented 3 years ago

@gopaldahal : code that works when the debugger is attached and fails otherwise is not something I would expect as we don't do anything specific when a debugger is attached. Can you provide a stacktrace of the failing call?

Also note that regionalsettings are always loaded by default, see https://pnp.github.io/pnpcore/using-the-sdk/basics-context.html#loading-additional-iweb-and-isite-properties-when-creating-a-pnpcontext for some more context

gopaldahal commented 3 years ago

@jansenbe , Thank you for the quick response. Unfortunately, Crash is not getting intercepted by try-catch. Neither there is any log on the windows event log. I will share soon with the sample application.

gopaldahal commented 3 years ago

@jansenbe This is the sample Code I am running under Console application.

using System; using System.Collections.Generic; using System.Threading.Tasks; using Microsoft.Extensions.Hosting; using PnP.Core.Model.SharePoint; using PnP.Core.Services; using Microsoft.Extensions.DependencyInjection; using PnP.Core.Auth; using PnP.Core.QueryModel; using System.Linq; using PnP.Core.Services.Builder.Configuration; //using Microsoft.SharePoint;

namespace PnP.Core.SDK { class Program { public static string ClientUrl = "https://abcsharepoint.com/sites/abc"; public static string ClientId = "XXX"; public static string TenantId = "YYY"; public const string ManagerLog = "PnPCoreHandler"; static void Main(string[] args) { TestBatch(); }

    static async Task TestBatch()
    {
        var host = Host.CreateDefaultBuilder()
        .ConfigureServices((hostingContext, services) =>
        {
            services.AddPnPCore(options =>
                                        {
                                            options.PnPContext.GraphFirst = true;
                                            options.PnPContext.GraphCanUseBeta = true;
                                            options.PnPContext.GraphAlwaysUseBeta = false;
                                            options.HttpRequests.UserAgent = "ISV|Contoso|ABC";
                                            options.HttpRequests.MicrosoftGraph = new PnPCoreHttpRequestsGraphOptions
                                            { #
                                                UseRetryAfterHeader = true,
                                                MaxRetries = 10,
                                                DelayInSeconds = 3,
                                                UseIncrementalDelay = true,
                                            };
                                            options.HttpRequests.SharePointRest = new PnPCoreHttpRequestsSharePointRestOptions
                                            {
                                                UseRetryAfterHeader = true,
                                                MaxRetries = 10,
                                                DelayInSeconds = 3,
                                                UseIncrementalDelay = true,
                                            };
                                            options.DefaultAuthenticationProvider = new InteractiveAuthenticationProvider(
                                                ClientId, // Client Id
                                               TenantId, // Tenant Id
                                                new Uri("https://login.microsoftonline.com/common/oauth2/nativeclient"));  // Redirect Id
                                        });
        })
        .Build();

        await host.StartAsync();
        try
        {
            using (var scope = host.Services.CreateScope())
            {
                var pnpContextFactory = scope.ServiceProvider.GetRequiredService<IPnPContextFactory>();
                using (var context =  pnpContextFactory.Create(new Uri(ClientUrl)))
                {
                    //await UploadFiles(context);
                    //var accessToken = await context.AuthenticationProvider.GetAccessTokenAsync(context.Uri);
                    //SharepointTest.AzureAppAuthentication.GetAuthenticatedClientContextFromToken(ClientUrl, accessToken);
                    await AddUpdateDeleteBatch(context);
                }
            }
        }
        catch (Exception ex)
        {

        }
        // Cleanup console host
        host.Dispose();
    }

    private static async Task AddUpdateDeleteBatch(PnPContext context)
    {
        try
        {
            //Code runs over here
            //If I start with single step debugging it works with charm
            // But as I run with out setting any debugging point it crash in the middle
            //not able to catch by exception handler
            //nor the log available on Windown event viewer'
            Console.ForegroundColor = ConsoleColor.Yellow;
            Console.WriteLine("===ADD/UPDATE/DELETE: create/delete list and add 20 items in batch===");
            Console.ResetColor();

            var parentList = await context.Web.Lists.GetByTitleAsync("AddTest", l => l.EnableModeration, l => l.TemplateType, l => l.EnableVersioning, l => l.Title, l => l.Fields, l => l.ContentTypes);
            var parentWeb = await context.Web.GetAsync(s => s.Language, s=>s.Url);
            var parentFields = parentList.Fields.ToList();

            List<Dictionary<string, object>> propertiesToUpdate = new List<Dictionary<string, object>>();
            var prop = new Dictionary<string, object>();
            prop.Add("Title", "My title 1");
            prop.Add("Created", DateTime.Now.AddDays(-600));
            propertiesToUpdate.Add(prop);
            var prop2 = new Dictionary<string, object>();
            prop2.Add("Title", "My title 2");
            propertiesToUpdate.Add(prop2);

            var uploadedListItems = new List<IListItem>();
            foreach (var propItem in propertiesToUpdate)
            {     
                try
                {
                    var item = await parentList.Items.AddBatchAsync(propItem);
                    uploadedListItems.Add(item);
                }
                catch(Exception ex)
                {
                }
            }
            var batchResponses = await context.ExecuteAsync(false);

            await uploadedListItems.First().LoadAsync(d => d.All);

            foreach (var batchResponse in batchResponses)
            {

            }

        }
        catch(Exception ex)
        {
            // Not able to catch here
        }
    }

}

}

jansenbe commented 3 years ago

@gopaldahal : please use the updated code snippet I've shared when answering your previous question, think that should also solve this problem

gopaldahal commented 3 years ago

@jansenbe, I removed the duplicate load of items as you mentioned. But, there is still a problem of crashes. However, after removing the async of my method and using ".Result" instead of await, it worked without a crash. Modified code is as below

using System; using System.Collections.Generic; using System.Threading.Tasks; using Microsoft.Extensions.Hosting; using PnP.Core.Model.SharePoint; using PnP.Core.Services; using Microsoft.Extensions.DependencyInjection; using PnP.Core.Auth; using PnP.Core.QueryModel; using System.Linq; using PnP.Core.Services.Builder.Configuration; //using Microsoft.SharePoint;

namespace PnP.Core.SDK { class Program { public static string ClientUrl = "https://abcsharepoint.com/sites/abc"; public static string ClientId = "XXX"; public static string TenantId = "YYY"; public const string ManagerLog = "PnPCoreHandler"; static void Main(string[] args) { TestBatch(); }

static async Task TestBatch()
{
    var host = Host.CreateDefaultBuilder()
    .ConfigureServices((hostingContext, services) =>
    {
        services.AddPnPCore(options =>
                                    {
                                        options.PnPContext.GraphFirst = true;
                                        options.PnPContext.GraphCanUseBeta = true;
                                        options.PnPContext.GraphAlwaysUseBeta = false;
                                        options.HttpRequests.UserAgent = "ISV|Contoso|ABC";
                                        options.HttpRequests.MicrosoftGraph = new PnPCoreHttpRequestsGraphOptions
                                        { #
                                            UseRetryAfterHeader = true,
                                            MaxRetries = 10,
                                            DelayInSeconds = 3,
                                            UseIncrementalDelay = true,
                                        };
                                        options.HttpRequests.SharePointRest = new PnPCoreHttpRequestsSharePointRestOptions
                                        {
                                            UseRetryAfterHeader = true,
                                            MaxRetries = 10,
                                            DelayInSeconds = 3,
                                            UseIncrementalDelay = true,
                                        };
                                        options.DefaultAuthenticationProvider = new InteractiveAuthenticationProvider(
                                            ClientId, // Client Id
                                           TenantId, // Tenant Id
                                            new Uri("https://login.microsoftonline.com/common/oauth2/nativeclient"));  // Redirect Id
                                    });
    })
    .Build();

    await host.StartAsync();
    try
    {
        using (var scope = host.Services.CreateScope())
        {
            var pnpContextFactory = scope.ServiceProvider.GetRequiredService<IPnPContextFactory>();
            using (var context =  pnpContextFactory.Create(new Uri(ClientUrl)))
            {
                //await UploadFiles(context);
                //var accessToken = await context.AuthenticationProvider.GetAccessTokenAsync(context.Uri);
                //SharepointTest.AzureAppAuthentication.GetAuthenticatedClientContextFromToken(ClientUrl, accessToken);
                AddUpdateDeleteBatch(context);
            }
        }
    }
    catch (Exception ex)
    {

    }
    // Cleanup console host
    host.Dispose();
}

private static void AddUpdateDeleteBatch(PnPContext context)
{
    try
    {
        //Code runs over here
        //If I start with single step debugging it works with charm
        // But as I run with out setting any debugging point it crash in the middle
        //not able to catch by exception handler
        //nor the log available on Windown event viewer'
        Console.ForegroundColor = ConsoleColor.Yellow;
        Console.WriteLine("===ADD/UPDATE/DELETE: create/delete list and add 20 items in batch===");
        Console.ResetColor();

        var parentList = context.Web.Lists.GetByTitleAsync("AddTest", l => l.EnableModeration, l => l.TemplateType, l => l.EnableVersioning, l => l.Title, l => l.Fields, l => l.ContentTypes).Result;
        var parentWeb = context.Web;
        var parentFields = parentList.Fields.ToList();

        List<Dictionary<string, object>> propertiesToUpdate = new List<Dictionary<string, object>>();
        var prop = new Dictionary<string, object>();
        prop.Add("Title", "My title 1");
        prop.Add("Created", DateTime.Now.AddDays(-600));
        propertiesToUpdate.Add(prop);
        var prop2 = new Dictionary<string, object>();
        prop2.Add("Title", "My title 2");
        propertiesToUpdate.Add(prop2);

        var uploadedListItems = new List<IListItem>();
        foreach (var propItem in propertiesToUpdate)
        {     
            try
            {
                var item = parentList.Items.AddBatchAsync(propItem).Result
                uploadedListItems.Add(item);
            }
            catch(Exception ex)
            {
            }
        }
        var batchResponses = context.ExecuteAsync(false).Result;

        uploadedListItems.First().LoadAsync(d => d.All).Wait();

        foreach (var batchResponse in batchResponses)
        {

        }

    }
    catch(Exception ex)
    {
        // Not able to catch here
    }
}

}

jansenbe commented 3 years ago

Good to see it works. If you don't like to use an async methods then do know there are sync equivalents from all public methods, so you can call for example context.Execute(false); and uploadedListItems.First().Load(d => d.All).

As the issue is fixed, I'm gonna close this issue. Thanks for reporting back on the progress.