示例#1
0
        /// <summary>
        /// Maps a classic Web Part into a modern Web Part
        /// </summary>
        /// <param name="input">The input for the mapping activity</param>
        /// <param name="token">The cancellation token to use, if any</param>
        /// <returns>The output of the mapping activity</returns>
#pragma warning disable CS1998 // Async method lacks 'await' operators and will run synchronously
        public async Task <WebPartMappingProviderOutput> MapWebPartAsync(WebPartMappingProviderInput input, CancellationToken token = default)
#pragma warning restore CS1998 // Async method lacks 'await' operators and will run synchronously
        {
            // Check that we have input data
            if (input == null)
            {
                throw new ArgumentNullException(nameof(input));
            }

            this.taskId = input.Context.Task.Id;

            // Try to convert the mapping provider input into a typed version
            var specializedInput = input as SharePointWebPartMappingProviderInput;

            if (specializedInput == null)
            {
                throw new ArgumentException(SharePointTransformationResources.Error_InvalidWebPartMappingProviderInput);
            }

            // Configure the SharePoint Function service instance
            this.functionProcessor.Init(specializedInput.Context, specializedInput.SourceContext);

            // Define the variable holding the input web part
            var webPart = input.WebPart;

            // Prepare the output object
            var result = new WebPartMappingProviderOutput();

            logger.LogInformation(
                $"Invoked: {this.GetType().Namespace}.{this.GetType().Name}.MapWebPartAsync"
                .CorrelateString(this.taskId));
            logger.LogInformation(
                SharePointTransformationResources.Info_ContentWebPartBeingTransformed
                .CorrelateString(this.taskId),
                webPart.Title, webPart.TypeShort());

            // Title bar will never be migrated
            if (input.WebPart.Type == WebParts.TitleBar)
            {
                logger.LogInformation(
                    SharePointTransformationResources.Info_NotTransformingTitleBar
                    .CorrelateString(this.taskId));
                return(result);
            }

            // Load the mapping configuration
            WebPartMapping mappingFile = LoadMappingFile(this.spOptions.Value.WebPartMappingFile);

            var sourceItem = input.Context.SourceItem as SharePointSourceItem;

            if (sourceItem == null)
            {
                throw new ApplicationException(SharePointTransformationResources.Error_MissiningSharePointInputItem);
            }

            // Find the default mapping, will be used for webparts for which the model does not contain a mapping
            var defaultMapping = mappingFile.BaseWebPart.Mappings.Mapping.FirstOrDefault(p => p.Default == true);

            if (defaultMapping == null)
            {
                logger.LogError(
                    SharePointTransformationResources.Error_NoDefaultMappingFound
                    .CorrelateString(this.taskId));
                throw new Exception(SharePointTransformationResources.Error_NoDefaultMappingFound);
            }

            // Assign the default mapping, if we've a more specific mapping than that will overwrite this mapping
            Mapping mapping = defaultMapping;

            // Does the web part have a mapping defined?
            var webPartData = mappingFile.WebParts.FirstOrDefault(p => p.Type.GetTypeShort() == webPart.Type.GetTypeShort());

            // Check for cross site transfer support
            if (webPartData != null && input.IsCrossSiteTransformation)
            {
                if (!webPartData.CrossSiteTransformationSupported)
                {
                    logger.LogWarning(
                        SharePointTransformationResources.Warning_CrossSiteNotSupported
                        .CorrelateString(this.taskId));
                    return(result);
                }
            }

            var globalTokens = PrepareGlobalTokens();

            if (webPartData != null && webPartData.Mappings != null)
            {
                // Add site level (e.g. site) tokens to the web part properties and model so they can be used in the same manner as a web part property
                UpdateWebPartDataProperties(webPart, webPartData, mappingFile, globalTokens);

                string selectorResult = null;
                try
                {
                    // The mapping can have a selector function defined, if so it will be executed.
                    // If a selector was executed the selectorResult will contain the name of the mapping to use
                    logger.LogDebug(
                        SharePointTransformationResources.Debug_ProcessingSelectorFunctions
                        .CorrelateString(this.taskId));
                    selectorResult = this.functionProcessor.Process(ref webPartData, webPart);
                }
                catch (Exception ex)
                {
                    // NotAvailableAtTargetException is used to "skip" a web part since it's not valid for the target site collection (only applies to cross site collection transfers)
                    if (ex.InnerException is NotAvailableAtTargetException)
                    {
                        logger.LogError(
                            SharePointTransformationResources.Error_NotValidForTargetSiteCollection
                            .CorrelateString(this.taskId));
                    }

                    if (ex.InnerException is MediaWebpartConfigurationException)
                    {
                        logger.LogError(
                            SharePointTransformationResources.Error_MediaWebpartConfiguration
                            .CorrelateString(this.taskId));
                    }

                    logger.LogError(
                        $"{SharePointTransformationResources.Error_AnErrorOccurredFunctions} - {ex.Message}"
                        .CorrelateString(this.taskId));
                    throw;
                }

                Mapping webPartMapping = null;
                // Get the needed mapping:
                // - use the mapping returned by the selector
                // - if no selector then take the default mapping
                // - if no mapping found we'll fall back to the default web part mapping
                if (!string.IsNullOrEmpty(selectorResult))
                {
                    webPartMapping = webPartData.Mappings.Mapping.Where(p => p.Name.Equals(selectorResult, StringComparison.InvariantCultureIgnoreCase)).FirstOrDefault();
                }
                else
                {
                    // If there's only one mapping let's take that one, even if not specified as default
                    if (webPartData.Mappings.Mapping.Length == 1)
                    {
                        webPartMapping = webPartData.Mappings.Mapping[0];
                    }
                    else
                    {
                        webPartMapping = webPartData.Mappings.Mapping.FirstOrDefault(p => p.Default == true);
                    }
                }

                if (webPartMapping != null)
                {
                    mapping = webPartMapping;
                }
                else
                {
                    logger.LogWarning(
                        SharePointTransformationResources.Warning_ContentWebPartMappingNotFound
                        .CorrelateString(this.taskId));
                }

                // Process mapping specific functions (if any)
                if (!String.IsNullOrEmpty(mapping.Functions))
                {
                    try
                    {
                        logger.LogInformation(
                            SharePointTransformationResources.Info_ProcessingMappingFunctions
                            .CorrelateString(this.taskId));
                        functionProcessor.ProcessMappingFunctions(ref webPartData, webPart, mapping);
                    }
                    catch (Exception ex)
                    {
                        // NotAvailableAtTargetException is used to "skip" a web part since it's not valid for the target site collection (only applies to cross site collection transfers)
                        if (ex.InnerException is NotAvailableAtTargetException)
                        {
                            logger.LogError(
                                SharePointTransformationResources.Error_NotValidForTargetSiteCollection
                                .CorrelateString(this.taskId));
                        }

                        logger.LogError(
                            $"{SharePointTransformationResources.Error_AnErrorOccurredFunctions} - {ex.Message}"
                            .CorrelateString(this.taskId));
                        throw;
                    }
                }
            }

            return(new SharePointWebPartMappingProviderOutput(mapping));
        }
示例#2
0
        private static Dictionary <string, string> ExtractProperties(WebPartMappingProviderInput input, WebPartMapping mapping)
        {
            // Storage for properties to keep
            Dictionary <string, string> propertiesToKeep = new Dictionary <string, string>();

            // List of properties to retrieve
            List <Property> propertiesToRetrieve = mapping.BaseWebPart.Properties.ToList <Property>();

            // For older versions of SharePoint the type in the mapping would not match. Use the TypeShort Comparison.
            var webPartProperties = mapping.WebParts.FirstOrDefault(p => p.Type.GetTypeShort().Equals(input.SourceComponentType.GetTypeShort(), StringComparison.InvariantCultureIgnoreCase));

            if (webPartProperties != null && webPartProperties.Properties != null)
            {
                foreach (var p in webPartProperties.Properties.ToList <Property>())
                {
                    if (!propertiesToRetrieve.Contains(p))
                    {
                        propertiesToRetrieve.Add(p);
                    }
                }
            }

            // If we don't have the raw content
            if (string.IsNullOrEmpty(input.SourceComponentRawContent))
            {
                if (input.SourceComponentType.GetTypeShort() == WebParts.Client.GetTypeShort())
                {
                    // Special case since we don't know upfront which properties are relevant here...so let's take them all
                    foreach (var p in input.SourceProperties)
                    {
                        if (!propertiesToKeep.ContainsKey(p.Key))
                        {
                            propertiesToKeep.Add(p.Key, p.Value != null ? p.Value.ToString() : string.Empty);
                        }
                    }
                }
                else
                {
                    // Special case where we did not have export rights for the web part XML, assume this is a V3 web part
                    foreach (var p in propertiesToRetrieve)
                    {
                        if (!string.IsNullOrEmpty(p.Name) &&
                            input.SourceProperties.ContainsKey(p.Name) &&
                            !propertiesToKeep.ContainsKey(p.Name))
                        {
                            propertiesToKeep.Add(p.Name, input.SourceProperties[p.Name] != null ?
                                                 input.SourceProperties[p.Name].ToString() : string.Empty);
                        }
                    }
                }
            }
            else
            {
                var xml   = XElement.Parse(input.SourceComponentRawContent);
                var xmlns = xml.XPathSelectElement("*").GetDefaultNamespace();
                if (xmlns.NamespaceName.Equals("http://schemas.microsoft.com/WebPart/v3",
                                               StringComparison.InvariantCultureIgnoreCase))
                {
                    if (input.SourceComponentType.GetTypeShort() == WebParts.Client.GetTypeShort())
                    {
                        // Special case since we don't know upfront which properties are relevant here...so let's take them all
                        foreach (var p in input.SourceProperties)
                        {
                            if (!propertiesToKeep.ContainsKey(p.Key))
                            {
                                propertiesToKeep.Add(p.Key, p.Value != null ? p.Value.ToString() : string.Empty);
                            }
                        }
                    }
                    else
                    {
                        // the retrieved properties are sufficient
                        foreach (var p in propertiesToRetrieve)
                        {
                            if (!string.IsNullOrEmpty(p.Name) &&
                                input.SourceProperties.ContainsKey(p.Name) &&
                                !propertiesToKeep.ContainsKey(p.Name))
                            {
                                propertiesToKeep.Add(p.Name, input.SourceProperties[p.Name] != null ?
                                                     input.SourceProperties[p.Name].ToString() : string.Empty);
                            }
                        }
                    }
                }
                else if (xmlns.NamespaceName.Equals("http://schemas.microsoft.com/WebPart/v2",
                                                    StringComparison.InvariantCultureIgnoreCase))
                {
                    foreach (var p in propertiesToRetrieve)
                    {
                        if (!string.IsNullOrEmpty(p.Name))
                        {
                            if (input.SourceProperties.ContainsKey(p.Name))
                            {
                                if (!propertiesToKeep.ContainsKey(p.Name))
                                {
                                    propertiesToKeep.Add(p.Name, input.SourceProperties[p.Name] != null ?
                                                         input.SourceProperties[p.Name].ToString() : "");
                                }
                            }
                            else
                            {
                                // check XMl for property
                                var v2Element = xml.Descendants(xmlns + p.Name).FirstOrDefault();
                                if (v2Element != null)
                                {
                                    if (!propertiesToKeep.ContainsKey(p.Name))
                                    {
                                        propertiesToKeep.Add(p.Name, v2Element.Value);
                                    }
                                }

                                // Some properties do have their own namespace defined
                                if (input.SourceComponentType.GetTypeShort() == WebParts.SimpleForm.GetTypeShort() &&
                                    p.Name.Equals("Content", StringComparison.InvariantCultureIgnoreCase))
                                {
                                    // Load using the http://schemas.microsoft.com/WebPart/v2/SimpleForm namespace
                                    XNamespace xmlcontentns = "http://schemas.microsoft.com/WebPart/v2/SimpleForm";
                                    v2Element = xml.Descendants(xmlcontentns + p.Name).FirstOrDefault();
                                    if (v2Element != null)
                                    {
                                        if (!propertiesToKeep.ContainsKey(p.Name))
                                        {
                                            propertiesToKeep.Add(p.Name, v2Element.Value);
                                        }
                                    }
                                }
                                else if (input.SourceComponentType.GetTypeShort() == WebParts.ContentEditor.GetTypeShort())
                                {
                                    if (p.Name.Equals("ContentLink", StringComparison.InvariantCultureIgnoreCase) ||
                                        p.Name.Equals("Content", StringComparison.InvariantCultureIgnoreCase) ||
                                        p.Name.Equals("PartStorage", StringComparison.InvariantCultureIgnoreCase))
                                    {
                                        XNamespace xmlcontentns = "http://schemas.microsoft.com/WebPart/v2/ContentEditor";
                                        v2Element = xml.Descendants(xmlcontentns + p.Name).FirstOrDefault();
                                        if (v2Element != null)
                                        {
                                            if (!propertiesToKeep.ContainsKey(p.Name))
                                            {
                                                propertiesToKeep.Add(p.Name, v2Element.Value);
                                            }
                                        }
                                    }
                                }
                                else if (input.SourceComponentType.GetTypeShort() == WebParts.Xml.GetTypeShort())
                                {
                                    if (p.Name.Equals("XMLLink", StringComparison.InvariantCultureIgnoreCase) ||
                                        p.Name.Equals("XML", StringComparison.InvariantCultureIgnoreCase) ||
                                        p.Name.Equals("XSLLink", StringComparison.InvariantCultureIgnoreCase) ||
                                        p.Name.Equals("XSL", StringComparison.InvariantCultureIgnoreCase) ||
                                        p.Name.Equals("PartStorage", StringComparison.InvariantCultureIgnoreCase))
                                    {
                                        XNamespace xmlcontentns = "http://schemas.microsoft.com/WebPart/v2/Xml";
                                        v2Element = xml.Descendants(xmlcontentns + p.Name).FirstOrDefault();
                                        if (v2Element != null)
                                        {
                                            if (!propertiesToKeep.ContainsKey(p.Name))
                                            {
                                                propertiesToKeep.Add(p.Name, v2Element.Value);
                                            }
                                        }
                                    }
                                }
                                else if (input.SourceComponentType.GetTypeShort() == WebParts.SiteDocuments.GetTypeShort())
                                {
                                    if (p.Name.Equals("UserControlledNavigation", StringComparison.InvariantCultureIgnoreCase) ||
                                        p.Name.Equals("ShowMemberships", StringComparison.InvariantCultureIgnoreCase) ||
                                        p.Name.Equals("UserTabs", StringComparison.InvariantCultureIgnoreCase))
                                    {
                                        XNamespace xmlcontentns = "urn:schemas-microsoft-com:sharepoint:portal:sitedocumentswebpart";
                                        v2Element = xml.Descendants(xmlcontentns + p.Name).FirstOrDefault();
                                        if (v2Element != null)
                                        {
                                            if (!propertiesToKeep.ContainsKey(p.Name))
                                            {
                                                propertiesToKeep.Add(p.Name, v2Element.Value);
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }

            return(propertiesToKeep);
        }