Modernization: SharePoint 2010 Transform via CSOM

Created on 11 Jun 2019  Â·  15Comments  Â·  Source: pnp/modernization

Category

[ ] Bug
[X] Enhancement

Expected or Desired Behavior

Transform SharePoint 2010 to SharePoint Online - Thread for notes, thoughts and POC.

enhancement PageTransformationEngine

Most helpful comment

Current findings, initial transform failed with multiple exceptions. The CSOM API lacks the following properties:

  • Web.URL (Source of majority of the faults) - have a plan to work around this
  • Web.GetLists - doesn't exist, had to fall back to Web.Lists.GetByTitle
  • Web.WebTemplate - bypassed

Currently, I have had to bypass a few methods, multi-lingual support for the "pages" name, the ability to check web template and asset transfer not working (possibly due to bypasses).

2010 CSOM Reference: https://docs.microsoft.com/en-us/previous-versions/office/developer/sharepoint-2010/ee544361%28v%3doffice.14%29

However, despite this and a few hacks managed to get something transformed using a super basic example:

2010 Example Transform

All 15 comments

Current findings, initial transform failed with multiple exceptions. The CSOM API lacks the following properties:

  • Web.URL (Source of majority of the faults) - have a plan to work around this
  • Web.GetLists - doesn't exist, had to fall back to Web.Lists.GetByTitle
  • Web.WebTemplate - bypassed

Currently, I have had to bypass a few methods, multi-lingual support for the "pages" name, the ability to check web template and asset transfer not working (possibly due to bypasses).

2010 CSOM Reference: https://docs.microsoft.com/en-us/previous-versions/office/developer/sharepoint-2010/ee544361%28v%3doffice.14%29

However, despite this and a few hacks managed to get something transformed using a super basic example:

2010 Example Transform

Nice!!

You can reuse code from the below method to detect the version and if needed use alternative code paths.

public static bool HasMinimalServerLibraryVersion(this ClientRuntimeContext clientContext, Version minimallyRequiredVersion)
        {
            bool hasMinimalVersion = false;
#if !ONPREMISES
            try
            {
                clientContext.ExecuteQueryRetry();
                hasMinimalVersion = clientContext.ServerLibraryVersion.CompareTo(minimallyRequiredVersion) >= 0;
            }
            catch (PropertyOrFieldNotInitializedException)
            {
                // swallow the exception.
            }
#else
            try
            {
                Uri urlUri = new Uri(clientContext.Url);
                HttpWebRequest request = (HttpWebRequest)WebRequest.Create($"{urlUri.Scheme}://{urlUri.DnsSafeHost}:{urlUri.Port}/_vti_pvt/service.cnf");
                request.UseDefaultCredentials = true;

                var response = request.GetResponse();

                using (var dataStream = response.GetResponseStream())
                {
                    // Open the stream using a StreamReader for easy access.
                    using (System.IO.StreamReader reader = new System.IO.StreamReader(dataStream))
                    {
                        // Read the content.Will be in this format
                        // vti_encoding:SR|utf8-nl
                        // vti_extenderversion: SR | 15.0.0.4505

                        string version = reader.ReadToEnd().Split('|')[2].Trim();

                        // Only compare the first three digits
                        var compareToVersion = new Version(minimallyRequiredVersion.Major, minimallyRequiredVersion.Minor, minimallyRequiredVersion.Build, 0);
                        hasMinimalVersion = new Version(version.Split('.')[0].ToInt32(), 0, version.Split('.')[3].ToInt32(), 0).CompareTo(compareToVersion) >= 0;
                    }
                }
            }
            catch (WebException ex)
            {
                Log.Warning(Constants.LOGGING_SOURCE, CoreResources.ClientContextExtensions_HasMinimalServerLibraryVersion_Error, ex.ToDetailedString(clientContext));
            }
#endif
            return hasMinimalVersion;
        }

lol I just wrote extension method:

```c#
public static bool IsSharePoint2010(this Web web)
{
// Use the missing URL property from CSOM to determine if this is SharePoint 2010s
try
{
web.EnsureProperty(p => p.Url);
return false;

        }catch(Exception ex)
        {
            return true;
        }
    }

```
cool, thanks.

@pkbullock : I've added some properties to the BaseTransformationInformation to help understand the source/target setup better. You can reuse these if you need them to differentiate 2010.

        /// <summary>
        /// Indicates if this transformation spans farms (on-prem to online tenant, online tenant A to online tenant B)
        /// </summary>
        internal bool IsCrossFarmTransformation { get; set; }

        /// <summary>
        /// SharePoint version of the source 
        /// </summary>
        internal SPVersion SourceVersion { get; set; }

        /// <summary>
        /// SharePoint version of the target 
        /// </summary>
        internal SPVersion TargetVersion { get; set; }


public enum SPVersion
    {
        SPO = 0,
        SP2019 = 1,
        SP2016 = 2,
        SP2013 = 3, 
        SP2010 = 4
    }

Ok cool, I’ll merge those into my fork on way home.

Thanks, one question do you have to hand or know of a reference for the minimum versions of SharePoint with the above code couple blocks above?

Get Outlook for iOShttps://aka.ms/o0ukef


From: Bert Jansen notifications@github.com
Sent: Wednesday, June 12, 2019 1:13 pm
To: SharePoint/sp-dev-modernization
Cc: Paul Bullock; Mention
Subject: Re: [SharePoint/sp-dev-modernization] SharePoint 2010 Transform via CSOM (#183)

@pkbullockhttps://eur02.safelinks.protection.outlook.com/?url=https%3A%2F%2Fgithub.com%2Fpkbullock&data=02%7C01%7Cpaul.bullock%40capacreative.co.uk%7C6c34bddd8f5b4cf496d108d6ef2f5d5d%7Cb65b38dfdc4640ca92b9547172742753%7C0%7C0%7C636959384050244164&sdata=qXoA9Nl6EU6JhSlVfnfEX8E7Te07fBZngjJG3jwHzZ8%3D&reserved=0 : I've added some properties to the BaseTransformationInformation to help understand the source/target setup better. You can reuse these if you need them to differentiate 2010.

    /// <summary>
    /// Indicates if this transformation spans farms (on-prem to online tenant, online tenant A to online tenant B)
    /// </summary>
    internal bool IsCrossFarmTransformation { get; set; }

    /// <summary>
    /// SharePoint version of the source
    /// </summary>
    internal SPVersion SourceVersion { get; set; }

    /// <summary>
    /// SharePoint version of the target
    /// </summary>
    internal SPVersion TargetVersion { get; set; }

public enum SPVersion
{
SPO = 0,
SP2019 = 1,
SP2016 = 2,
SP2013 = 3,
SP2010 = 4
}

—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHubhttps://eur02.safelinks.protection.outlook.com/?url=https%3A%2F%2Fgithub.com%2FSharePoint%2Fsp-dev-modernization%2Fissues%2F183%3Femail_source%3Dnotifications%26email_token%3DACC7Z4L6E4YNC3S5TSRVN63P2DR6DA5CNFSM4HXDHQO2YY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGODXQGRTQ%23issuecomment-501246158&data=02%7C01%7Cpaul.bullock%40capacreative.co.uk%7C6c34bddd8f5b4cf496d108d6ef2f5d5d%7Cb65b38dfdc4640ca92b9547172742753%7C0%7C0%7C636959384050254172&sdata=9%2BuXezmnXf5PMAQOQdf%2BRJYvtGvaf8qivFjvAo3MA%2BA%3D&reserved=0, or mute the threadhttps://eur02.safelinks.protection.outlook.com/?url=https%3A%2F%2Fgithub.com%2Fnotifications%2Funsubscribe-auth%2FACC7Z4NM7BGALJV4G7KRXMTP2DR6DANCNFSM4HXDHQOQ&data=02%7C01%7Cpaul.bullock%40capacreative.co.uk%7C6c34bddd8f5b4cf496d108d6ef2f5d5d%7Cb65b38dfdc4640ca92b9547172742753%7C0%7C0%7C636959384050254172&sdata=5mNjkqd5JhAdeepfoY4OecAR8viqpRcX5PB1kr2A5l8%3D&reserved=0.

I don't see anything more specific inside a given SP version...so for now let's stick with checking the base version as set with the SPVersion enum.

Just an update - in testing the asset transfer doesn't work because the OpenBinaryStream method does not exist on the API. I will be in the next few days creating extension methods for calls that need work arounds and use the above to switch between them :)

Let's hope we don't hit any roadblocks. As plan B we could as well fall back to some of the classic asmx endpoints in case there's no CSOM option available.

Status:

  • Had to do some changes to SPVersion to make it more global to the app + caching.
  • Got asset transfer and page layout analyser working.
  • Next Challange: ZoneId and Export Mode for webparts are not available as properties, this is used in PublishingPage analyser. We may need to implement #167 with some tweaks. I cannot see a simple way to solve this with CSOM, WebServices. Also this may affect SP2013, partially on SP2016, since it looks like these properties were added earlier this year. Continuing to investigate. @jansenbe have you encountered this or does PnP-SItes-Core have anything that we can use.

I think we can live without ZoneId, I'll need to investigate the export mode

@jansenbe this affects the ability to link the page layout mapping and the location of the web part in client side page. Code affected: (https://github.com/SharePoint/sp-dev-modernization/blob/5035f031c8e24eba6d6e3b0df61ec2c1fb85bcd4/Tools/SharePoint.Modernization/SharePointPnP.Modernization.Framework/Pages/PublishingPage.cs#L298)[https://github.com/SharePoint/sp-dev-modernization/blob/5035f031c8e24eba6d6e3b0df61ec2c1fb85bcd4/Tools/SharePoint.Modernization/SharePointPnP.Modernization.Framework/Pages/PublishingPage.cs#L298] also export in that region of code.

Slowly moving forward... managed to get ZoneID and some export data from Web Service calls.

  • Need to validate export property if they are the same as it returned something similar.
  • Still need to parse the WS responses and extract the relevant metadata to preserve web part locations.
  • Lots more testing needed - realised my on-prem testing is too narrow in its cases.
    😊

@pkbullock : July release will be released on July 1st / 2nd which implies that possible PR's you want to be included should get in by end of next week. If you feel you need more time than you simply wait for the August release window.

Just an update, workaround web part retrieval with web service calls and updated codebase to the latest as this branch is falling far behind.

Closing this issue now that the preview support has been merged. Thx @pkbullock :-)

Was this page helpful?
0 / 5 - 0 ratings