PnP Core SDK inside .net core console application, how the date & time format and time zone will be handled for adding and updating Dates Values

I have a SharePoint site with a time zone of UTC+3.

I have 2 hosting servers:

  1. One with UTC+3:

image

  1. And the second with UTC+1:

image

I created 2 SharePoint lists:

  1. SourceD
  2. DestinationD

I have this console application where I am trying to understand how the dates/times & time zone and format will be retrieved and set.

The console application does the following main steps:

Code:

namespace ConsoleApp4
{
    internal class Program
    {
        static async Task Main(string[] args)
        {
            var tenantId = "**";
            var clientId = "**";
            var certificatePath = @"c:\CERT\***.pfx";
            var certificatePassword = "****";

            // Initialize a new service collection
            var serviceCollection = new ServiceCollection();

            // Load the certificate
            var certificate = new X509Certificate2(certificatePath, certificatePassword, X509KeyStorageFlags.Exportable);

            // Configure logging
            serviceCollection.AddLogging(builder =>
            {
                builder.AddConsole();
            });

            // Add and configure PnP Core SDK
            serviceCollection.AddPnPCore(options =>
            {
                options.PnPContext.GraphFirst = true; // Set true if you prefer to use Graph over CSOM when possible
                                                      // options.HttpRequests.UserAgent = "ISV|Contoso|ProductX";
                options.Sites.Add("SiteToWorkWith", new PnPCoreSiteOptions
                {
                    SiteUrl = "https://**.sharepoint.com/sites/PPM",
                    AuthenticationProvider = new X509CertificateAuthenticationProvider(clientId, tenantId, certificate)
                });
            });

            // Build the service provider
            var serviceProvider = serviceCollection.BuildServiceProvider();

            // Use the service provider to get the IPnPContextFactory instance
            var pnpContextFactory = serviceProvider.GetRequiredService<IPnPContextFactory>();

            // Now you can use the IPnPContextFactory to get a PnPContext and perform operations
            var context = await pnpContextFactory.CreateAsync("SiteToWorkWith");

            var destinationList = 
                context.Web.Lists
                       .GetByTitle("DestinationD", 
                                   p => p.Title,
                                   p => p.Fields.QueryProperties(p => p.InternalName,
                                                                 p => p.FieldTypeKind,
                                                                 p => p.TypeAsString,
                                                                 p => p.Title));

            var sourceList = 
                context.Web.Lists
                       .GetByTitle("SourceD", 
                                   p => p.Title,
                                   p => p.Fields.QueryProperties(p => p.InternalName,
                                                                 p => p.FieldTypeKind,
                                                                 p => p.TypeAsString,
                                                                 p => p.Title));

            // Build a query that only returns these fields for the Work Orders
            string viewXml = @"<View Scope='RecursiveAll'>
                    <ViewFields>
                      <FieldRef Name='Title' />
                      <FieldRef Name='Created' />
                      <FieldRef Name='FileLeafRef' />
                        <FieldRef Name='D' />
                        <FieldRef Name='Modified' />
                      
                    </ViewFields>
                                        <Query>
                    </Query>
                   <RowLimit Paged='TRUE'>5000</RowLimit>
                   </View>";

            // Load all the needed data using paged requests
            bool paging = true;
            string nextPage = null;

            while (paging)
            {
                var output = await sourceList.LoadListDataAsStreamAsync(new RenderListDataOptions()
                {
                    ViewXml = viewXml,
                    RenderOptions = RenderListDataOptionsFlags.ListData,
                    Paging = nextPage ?? null,
                }).ConfigureAwait(false);

                if (output.ContainsKey("NextHref"))
                {
                    nextPage = output["NextHref"].ToString().Substring(1);
                }
                else
                {
                    paging = false;
                }
            }

       var sourceitems = sourceList.Items.AsRequested()
       .Select(wo =>
       {

           var createdStr = wo["Created"] != null ? wo["Created"].ToString() : null;
           var modifiedStr = wo["Modified"] != null ? wo["Modified"].ToString() : null;
           var dStr = wo["D"] != null ? wo["D"].ToString() : null;

           return new
           {
               c = createdStr,
               m = modifiedStr,
               dStr = dStr
           };
       }).ToList();

            foreach (var item in sourceitems)
            {
                Console.WriteLine(item.dStr);
                Console.WriteLine(DateTime.Parse(item.dStr.ToString()).ToString("yyyy-MM-ddTHH:mm:ssZ"));
                Dictionary<string, object> logitem = new Dictionary<string, object>() {
                    { "Title", DateTime.Now },{"D",item.dStr}
                    };

                var newlogitem = await destinationList.Items.AddAsync(logitem);
                Console.WriteLine(logitem["D"]);
            }

            Console.ReadLine();

            context.Dispose();
        }
    }

I added a column of type Date/Time named "D" inside both lists. Then I added a list item inside the SourceD with this value:-

enter image description here

Where the console application behave as follow:-

  1. On the hosting server with UTC+3, it showed the Date & Time retrieved as follow (08/10/2024 14:30):- local

and it added a new list item inside the Destination list as follow:- image

  1. On the hosting server with UTC+1, it showed the Date & Time retrieved as follow (08/10/2024 13:40) which is one hour behind the sharepoint site and which matches the local server time zone:- remote and it raised this error when it tried to add the new item, that it can not find a field named "D":- D not found

So i have those questions:-

Q1) So seems the PnP Core SDK will not show the date/times using the SharePoint site timezone and format , but rather the hosting server timezone.. But if this was the case then how adding the new items worked well, i thought it will send the date/time in UTC+3 and sharepoint will assume this is in UTC format.. but PnP core SDK was smart enough to retrieve the Date/Time in local setting but send it to sharepoint after converting ti to UTC.. was this the case?

Q2) Also why i got an error when i tried to save the list item on the second hosting server , that it can not find a field with internal name = "D"?

Any advice please? Thanks

Upvotes: 0

Views: 62

Answers (0)

Related Questions