/// <summary>
        /// Migrates the web.config to a settings file in the blazor server project.
        /// </summary>
        /// <param name="webFormProjectData">Data from the web forms project already loaded and provided in a list.</param>
        /// <param name="webFormProject">The web forms project that we are migrating data from.</param>
        /// <param name="blazorServerProject">The blazor server project this is being migrated to.</param>
        public async Task MigrateConfig(IReadOnlyList <VsModel> webFormProjectData, VsProject webFormProject, VsProject blazorServerProject)
        {
            try
            {
                //Informing the dialog the migration step has started.
                await _statusTracking.UpdateStepStatusAsync(MigrationStepEnum.Config, MigrationStatusEnum.Running);

                //Get the web.config file from the source project;
                if (!(webFormProjectData.FirstOrDefault(c =>
                                                        c.ModelType == VisualStudioModelType.Document &
                                                        c.Name.ToLower().Equals("web.config")) is VsDocument configDocument))
                {
                    //No web.config was found.
                    //Sending a status update to the dialog
                    await _statusTracking.UpdateCurrentStatusAsync(MigrationStepEnum.Config, MessageTypeEnum.Error,
                                                                   $"No web.config file was found in the web forms project {webFormProject.Name}. Cannot migrate the configuration.");

                    //Informing the dialog the migration step has failed.
                    await _statusTracking.UpdateStepStatusAsync(MigrationStepEnum.Config, MigrationStatusEnum.Running);

                    return;
                }
                else
                {
                    XmlDocument xmlDoc = new XmlDocument();
                    xmlDoc.LoadXml(await configDocument.GetDocumentContentAsStringAsync());

                    var jsonConverted = JsonConvert.SerializeXmlNode(xmlDoc);

                    //Add converted web.config to a file in the target solution.  this will be named webconfig.json
                    var thing = await blazorServerProject.AddDocumentAsync("webconfig.json", jsonConverted);

                    //Sending a status update to the dialog
                    await _statusTracking.UpdateCurrentStatusAsync(MigrationStepEnum.Config, MessageTypeEnum.Information,
                                                                   $"The web.config file has been moved to the root directory of {blazorServerProject.Name} and converted to 'webconfig.json'.");

                    await _statusTracking.UpdateCurrentStatusAsync(MigrationStepEnum.Config, MessageTypeEnum.Information,
                                                                   $"** Please review the webconfig.json file and make sure that it meets the needs of the converted Blazor app.");
                }

                //Completed the migration step informing the dialog.
                await _statusTracking.UpdateStepStatusAsync(MigrationStepEnum.Config, MigrationStatusEnum.Passed);
            }
Exemple #2
0
        /// <summary>
        /// Clones the bundleconfig.json into the blazer server project.
        /// </summary>
        /// <param name="webFormProjectData">Pre cached project data about the web forms project.</param>
        /// <param name="webFormProject">The web forms project that we are migrating data from.</param>
        /// <param name="blazorServerProject">The blazor server project this is being migrated to.</param>
        public async Task MigrateBundling(IReadOnlyList <VsModel> webFormProjectData, VsProject webFormProject, VsProject blazorServerProject)
        {
            try
            {
                //Letting the dialog know the migration step has started.
                await _statusTracking.UpdateStepStatusAsync(MigrationStepEnum.Bundling, MigrationStatusEnum.Running);

                //Finding the bundlconfig.json file.
                if (webFormProjectData.FirstOrDefault(p => p.Name.ToLower().Equals("bundleconfig.json")) is VsDocument bundleConfig)
                {
                    //Found the config file. loading its content.
                    var bundleText = await bundleConfig.GetDocumentContentAsStringAsync();

                    //Creating the bundleconfig.json in the blazor server project, and injecting the content.
                    var thing = await blazorServerProject.AddDocumentAsync("bundleconfig.json", bundleText);

                    //Sending a status to the dialog
                    await _statusTracking.UpdateCurrentStatusAsync(MigrationStepEnum.Bundling, MessageTypeEnum.Information,
                                                                   $"The bundleconfig.json file has been copied to the root directory of {blazorServerProject.Name}.");
                }
                else
                {
                    //No bundle configuration was found. No additional actions need to be taken.
                    //Sending a status to the dialog
                    await _statusTracking.UpdateCurrentStatusAsync(MigrationStepEnum.Bundling, MessageTypeEnum.Information,
                                                                   $"There was no 'bundleconfig.json' file found in the root of the source project {webFormProject.Name}.  No files were copied.");
                }

                //Completed the migration step informing the dialog.
                await _statusTracking.UpdateStepStatusAsync(MigrationStepEnum.Bundling, MigrationStatusEnum.Passed);
            }
            catch (Exception unhandledError)
            {
                //Dumping the exception that occured directly into the status so the user can see what happened.
                await _statusTracking.UpdateCurrentStatusAsync(MigrationStepEnum.Bundling, MessageTypeEnum.Error, $"The following unhandled error occured. '{unhandledError.Message}'");

                //Updating the status that the step failed
                await _statusTracking.UpdateStepStatusAsync(MigrationStepEnum.Bundling, MigrationStatusEnum.Failed);
            }
        }
Exemple #3
0
        /// <summary>
        /// Migrates logic class files over to the blazor server project.
        /// </summary>
        /// <param name="webFormProjectData">List of pre cached models for from the web form project.</param>
        /// <param name="webFormProject">The web forms project that we are migrating data from.</param>
        /// <param name="blazorServerProject">The blazor server project this is being migrated to.</param>
        public async Task MigrateLogic(IReadOnlyList <VsModel> webFormProjectData, VsProject webFormProject, VsProject blazorServerProject)
        {
            try
            {
                //Informing the dialog the migration step has started.
                await _statusTracking.UpdateStepStatusAsync(MigrationStepEnum.AppLogic, MigrationStatusEnum.Running);

                var childFiles = webFormProjectData.GetSourceCodeDocumentsAsync(true);

                //we don't want any known aspx/ascx files hitching a ride.  just plain vanilla *.cs files should qualify.
                var logicFiles = childFiles.Where(p => (!p.Name.ToLower().Contains("aspx.") && !p.Name.ToLower().Contains("ascx.") && !p.Name.ToLower().Contains("asax."))).ToList();

                //put logic files (using the file system into the target under the project root)
                foreach (VsCSharpSource sourceDocument in logicFiles)
                {
                    //look for specific files that are native to a WebForm app and skip them. ** TODO: move this to a config setting maybe?
                    if (sourceDocument.Name.ToLower().Contains("bundleconfig"))
                    {
                        continue;
                    }
                    if (sourceDocument.Name.ToLower().Contains("assemblyinfo"))
                    {
                        continue;
                    }
                    if (sourceDocument.Name.ToLower().Contains("startup"))
                    {
                        continue;
                    }
                    if (sourceDocument.Name.ToLower().Contains(".master"))
                    {
                        continue;
                    }

                    var logicDocument = await sourceDocument.LoadDocumentModelAsync();

                    var parentFolders = await logicDocument.GetParentFolders();

                    var source  = sourceDocument.SourceCode;
                    var docText = await logicDocument.GetDocumentContentAsStringAsync();

                    if (parentFolders.Count >= 1)
                    {
                        parentFolders.Reverse(); //The folders are returned in leaf-to-trunk so need to reverse the order for the next step.
                        VsProjectFolder createdFolder = null;

                        //deal with source folder hierarchy
                        for (int i = 0; i < parentFolders.Count; i++)
                        {
                            if (i > 0)
                            {
                                createdFolder = await createdFolder.CheckAddFolder(parentFolders[i].Name);
                            }
                            else
                            {
                                createdFolder = await blazorServerProject.CheckAddFolder(parentFolders[i].Name);
                            }
                        }

                        //copy the file.  We only really care about the most leaf/edge subfolder so its safe to use the creatdFolder variable here.
                        docText = docText.Replace(source.Classes.First().Namespace, $"{blazorServerProject.Name}.{createdFolder.Name}");

                        var targetFolderFiles = await createdFolder.GetChildrenAsync(false);

                        if (!targetFolderFiles.Any(c => c.Name.ToLower().Equals(logicDocument.Name.ToLower())))
                        {
                            await createdFolder.AddDocumentAsync(logicDocument.Name, docText);

                            //Updating the dialog with a status
                            await _statusTracking.UpdateCurrentStatusAsync(MigrationStepEnum.AppLogic, MessageTypeEnum.Information,
                                                                           $"Copied logic file: {logicDocument.Name} to project {blazorServerProject.Name} location: {Path.Combine(createdFolder.Path, logicDocument.Name)}");
                        }
                        else
                        {
                            await _statusTracking.UpdateCurrentStatusAsync(MigrationStepEnum.AppLogic, MessageTypeEnum.Warning,
                                                                           $"Logic file: {logicDocument.Name} already exists in target folder location: {Path.Combine(createdFolder.Path, logicDocument.Name)} and was skipped.");
                        }
                    }
                    else
                    {
                        var projFiles = await blazorServerProject.GetChildrenAsync(false);

                        if (!projFiles.Any(c => c.Name.ToLower().Equals(logicDocument.Name.ToLower())))
                        {
                            docText = docText.Replace(source.Classes.First().Namespace, $"{blazorServerProject.Name}");

                            var thing = await blazorServerProject.AddDocumentAsync(logicDocument.Name, docText);

                            //Updating the dialog with a status
                            await _statusTracking.UpdateCurrentStatusAsync(MigrationStepEnum.AppLogic, MessageTypeEnum.Information,
                                                                           $"Copied static file: {logicDocument.Name} to project {blazorServerProject.Name} location: {Path.Combine(blazorServerProject.Path, logicDocument.Name)}");
                        }
                        else
                        {
                            //Updating the dialog with a status
                            await _statusTracking.UpdateCurrentStatusAsync(MigrationStepEnum.AppLogic, MessageTypeEnum.Warning,
                                                                           $"Static file: {logicDocument.Name} already exists in project {blazorServerProject.Name} location: {Path.Combine(blazorServerProject.Path, logicDocument.Name)} and was skipped.");
                        }
                    }
                }

                //Completed the migration step informing the dialog.
                await _statusTracking.UpdateStepStatusAsync(MigrationStepEnum.AppLogic, MigrationStatusEnum.Passed);
            }
            catch (Exception unhandledError)
            {
                //Dumping the exception that occured directly into the status so the user can see what happened.
                await _statusTracking.UpdateCurrentStatusAsync(MigrationStepEnum.AppLogic, MessageTypeEnum.Error, $"The following unhandled error occured. '{unhandledError.Message}'");

                //Updating the status that the step failed
                await _statusTracking.UpdateStepStatusAsync(MigrationStepEnum.AppLogic, MigrationStatusEnum.Failed);
            }
        }
Exemple #4
0
        /// <summary>
        /// Searches the root of a project for the dependency injection registration class. If it is not found will generate a new service registration class.
        /// </summary>
        /// <param name="source">The source project to load the registration class from.</param>
        /// <param name="className">The name of the class that is used for service registration. This will be set to the constant <see cref="NetConstants.DefaultDependencyInjectionClassName"/> this can be overwritten with a custom class name.</param>
        /// <param name="automatedRegistrationMethodName">The name of the automatic transient class registration method. This will be set to the constant <see cref="NetConstants.DefaultAutomaticTransientClassRegistrationMethodName"/> this can be overwritten with a custom method name. </param>
        /// <returns>The source code model for the registration class.</returns>
        public static async Task <CsSource> GetRegistrationClassAsync(VsProject source, string className     = NetConstants.DefaultDependencyInjectionClassName,
                                                                      string automatedRegistrationMethodName = NetConstants.DefaultAutomaticTransientClassRegistrationMethodName)
        {
            if (source == null)
            {
                throw new ArgumentNullException(nameof(source));
            }
            if (!source.IsLoaded)
            {
                throw new CodeFactoryException("Project model was not loaded cannot load or create the registration class.");
            }
            if (string.IsNullOrEmpty(className))
            {
                throw new ArgumentNullException(nameof(className));
            }

            var projectFiles = await source.GetChildrenAsync(false, true);

            CsSource registrationSource = null;

            try
            {
                //Searching the projects root directory code files for the registration class
                if (projectFiles.Any())
                {
                    registrationSource = projectFiles.Where(f => f.ModelType == VisualStudioModelType.CSharpSource)
                                         .Cast <VsCSharpSource>().FirstOrDefault(s => s.SourceCode.Classes.Any(c => c.Name == className))
                                         ?.SourceCode;
                }

                //If no registration source code file was found then create a new registration class from scratch.
                if (registrationSource == null)
                {
                    var registrationClassCode = BuildNewRegistrationClass(source, className, automatedRegistrationMethodName);
                    if (registrationClassCode == null)
                    {
                        throw new CodeFactoryException("Could not generate the dependency injection registration source code");
                    }
                    string registrationClassFileName = $"{className}.cs";

                    var document = await source.AddDocumentAsync(registrationClassFileName, registrationClassCode);

                    registrationSource = await document.GetCSharpSourceModelAsync();
                }

                if (registrationSource == null)
                {
                    throw new CodeFactoryException("Cannot load the source code for the registration class.");
                }
            }
            catch (CodeFactoryException)
            {
                throw;
            }
            catch (Exception unhandledException)
            {
                throw new CodeFactoryException("An error occured while loading the registration class source code, cannot continue.", unhandledException);
            }

            return(registrationSource);
        }