/// <summary> /// Generates the source code from the T4 code factory. /// </summary> /// <param name="modelStore">The C# model storage that contains all the models to be used with the T4 factory.</param> /// <param name="modelData">Model data object used by the T4 factory.</param> /// <returns>The generated source code.</returns> public static string GenerateSource(CsModelStore modelStore, object modelData) { var factory = new MiddlewareConversion { CsModels = modelStore, ModelData = modelData }; return(factory.TransformText()); }
/// <summary> /// Generates the source code from the T4 code factory. /// </summary> /// <param name="modelStore">The C# model storage that contains all the models to be used with the T4 factory.</param> /// <param name="modelData">Model data object used by the T4 factory.</param> /// <returns>The generated source code.</returns> public static string GenerateSource(CsModelStore modelStore, object modelData) { var factory = new AddMemberMethod { CsModels = modelStore, ModelData = modelData }; return(factory.TransformText()); }
/// <summary> /// Generates the source code from the T4 code factory. /// </summary> /// <param name="modelStore">The C# model storage that contains all the models to be used with the T4 factory.</param> /// <param name="modelData">Model data object used by the T4 factory.</param> /// <returns>The generated source code.</returns> public static string GenerateSource(CsModelStore modelStore, object modelData) { var factory = new PageCodeBehind { CsModels = modelStore, ModelData = modelData }; return(factory.TransformText()); }
/// <summary> /// Generates the source code from the T4 code factory. /// </summary> /// <param name="modelStore">The C# model storage that contains all the models to be used with the T4 factory.</param> /// <returns>The generated source code.</returns> public static string GenerateSource(CsModelStore modelStore) { var factory = new ModuleFactory { CsModels = modelStore, ModelData = null }; return(factory.TransformText()); }
/// <summary> /// Generates the source code from the T4 code factory. /// </summary> /// <param name="modelStore">The C# model storage that contains all the models to be used with the T4 factory.</param> /// <param name="modelData">Model data object used by the T4 factory.</param> /// <returns>The generated source code.</returns> public static string GenerateSource(CsModelStore modelStore, object modelData) { var factory = new BundleConfigFactory { CsModels = modelStore, ModelData = modelData }; return(factory.TransformText()); }
/// <summary> /// Migrates the definition of existing Http Modules that were used in the web forms project into the blazor 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 MigrateHttpModulesAsync(IReadOnlyList <VsModel> webFormProjectData, VsProject webFormProject, VsProject blazorServerProject) { try { //Letting the dialog know the http modules migration has started. await _statusTracking.UpdateStepStatusAsync(MigrationStepEnum.HttpModules, MigrationStatusEnum.Running); //find class(es) that inherit HttpApplication var handlerClasses = webFormProjectData.GetClassesThatImplementInterface("IHttpHandler"); var moduleClasses = webFormProjectData.GetClassesThatImplementInterface("IHttpModule"); if (!handlerClasses.Any() && !moduleClasses.Any()) { //No handler classes or modules were found updating the status and exiting this step. await _statusTracking.UpdateCurrentStatusAsync(MigrationStepEnum.Startup, MessageTypeEnum.Error, $"No classes were found in {webFormProject.Name} that inherit from either 'IHttpHandler' or 'IHttpModule'"); //Setting the status to passed wasn't a failure and the solution will not require these to be added. await _statusTracking.UpdateStepStatusAsync(MigrationStepEnum.HttpModules, MigrationStatusEnum.Passed); return; } //Making sure a modules folder exists, if it does not create it in the blazor server project. var modulesFolder = await blazorServerProject.CheckAddFolder("Modules"); //Creating a dictionary that holds the target namespace for modules. var conversionData = new Dictionary <string, string> { { "Namespace", $"{blazorServerProject.DefaultNamespace}.Modules" } }; CsModelStore store = null; //Create a class file in the Modules folder from a T4 Template for each handler class foreach (CsSource source in handlerClasses) { //Setting up the model data to pass off to a T4 Factory store = new CsModelStore(); store.SetModel(source); //Calling the T4 factory and getting back the formatted file content. var fileContent = ModuleFactory.GenerateSource(store, conversionData); //Calling CodeFactory project system API to add a new document to the project folder, also injecting the new file content into the file. await modulesFolder.AddDocumentAsync($"{Path.GetFileNameWithoutExtension(source.SourceDocument)}Handler.cs", fileContent); //Clearing model store for the next call store = null; } //Create a class file in the Modules folder from a T4 Template for each model class foreach (CsSource source in moduleClasses) { store = new CsModelStore(); store.SetModel(source); await _visualStudioActions.ProjectFolderActions.AddDocumentAsync(modulesFolder, $"{Path.GetFileNameWithoutExtension(source.SourceDocument)}Handler.cs", ModuleFactory.GenerateSource(store, conversionData)); store = null; } //Completed process the modules informing the dialog it has passed. await _statusTracking.UpdateStepStatusAsync(MigrationStepEnum.HttpModules, 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.HttpModules, MessageTypeEnum.Error, $"The following unhandled error occured. '{unhandledError.Message}'"); //Updating the status that the step failed await _statusTracking.UpdateStepStatusAsync(MigrationStepEnum.HttpModules, MigrationStatusEnum.Failed); } }
/// <summary> /// Migrates the site.master layout files from the source WebForms project into the \Shared folder /// in the Blazor target application project. /// </summary> /// <param name="webFormSiteMasterFiles">The flattened list of WebForms project objects/files</param> /// <param name="blazorServerProject">The target Blazor project object</param> /// <returns></returns> /// private async Task ConvertAspxPage(VsDocument sourcePage, VsProject targetProject, VsProjectFolder targetPagesFolder, VsCSharpSource sourceCodeBehind = null) private async Task <string> ConvertLayoutFiles(IEnumerable <VsModel> webFormSiteMasterFiles, VsProject blazorServerProject) { string headerData = null; //put the files in the target project var targetFolder = await blazorServerProject.CheckAddFolder("Shared"); try { foreach (var layoutFile in webFormSiteMasterFiles) { //We don't want to touch/migrate any of the *.designer files if (layoutFile.Name.ToLower().Contains("designer")) { continue; } String targetFileName = layoutFile.Name.Replace(".", ""); //Get any existing children in the targetFolder that match. var existingBlazorMatches = await targetFolder.GetChildrenAsync(true, false); var docMatches = existingBlazorMatches.Where(p => p.Name.ToLower().Contains(targetFileName.ToLower())).Cast <VsDocument>(); foreach (VsDocument matchFile in docMatches) { //delete each matched file in the target folder. await matchFile.DeleteAsync(); } //work on just the Site.Master file which is basically a specialized *.aspx file. if (!layoutFile.Name.ToLower().Contains(".cs")) { var docObj = layoutFile as VsDocument; var textFromResult = await docObj.GetDocumentContentAsStringAsync(); //grab the <%Page element from the source and pull it from the text. Its meta data anyway and just screws up the conversion down the line. var pageHeaderData = System.Text.RegularExpressions.Regex.Match(textFromResult, @"<%@\s*[^%>]*(.*?)\s*%>").Value; if (pageHeaderData.Length > 0) { textFromResult = Regex.Replace(textFromResult, @"<%@\s*[^%>]*(.*?)\s*%>", string.Empty); } //Swap ASP.NET string tokens for Razor syntax (<%, <%@, <%:, <%#:, etc var targetText = RemoveASPNETSyntax(textFromResult); //Convert Site.Master file into razor syntax, specifically the asp:controls that might be used there. var conversionData = await ReplaceAspControls(targetText); //Drop the pageHeaderData into the Dictionary for later processing by any downstream T4 factories conversionData.Add("HeaderData", pageHeaderData); //Setup Page directives, using statements etc var targetWithMeta = await SetRazorPageDirectives(targetFileName, conversionData); VsDocument success = await _visualStudioActions.ProjectFolderActions.AddDocumentAsync(targetFolder, $"{targetFileName}.razor", targetWithMeta); //Updating the dialog await _statusTracking.UpdateCurrentStatusAsync(MigrationStepEnum.AspxPages, MessageTypeEnum.Information, $"The file {targetFileName}.razor was copied to {targetFolder.Name}."); } //Get sibling/named code-behind file //1. Get the children of this *.aspx file //2. Grab the doc that has the same name with a ".cs" extension on the end of it if (layoutFile.Name.Contains(".cs")) { targetFileName = layoutFile.Name.Replace(".cs", ""); targetFileName = targetFileName.Replace(".", ""); var sourceObj = layoutFile as VsCSharpSource; var codeSource = sourceObj.SourceCode; var metaDataDictionary = new Dictionary <string, string>(); metaDataDictionary.Add("Namespace", $"{blazorServerProject.Name}.Pages"); //Setup Page directives, using statements etc //var targetWithMeta = await SetRazorPageDirectives(targetFileName, conversionData); CsModelStore modelStore = new CsModelStore(); modelStore.SetModel(codeSource.Classes.FirstOrDefault()); var codebehind = await _visualStudioActions.ProjectFolderActions.AddDocumentAsync(targetFolder, $"{targetFileName}.razor.cs", Templates.PageCodeBehind.GenerateSource(modelStore, metaDataDictionary)); // Updating the dialog await _statusTracking.UpdateCurrentStatusAsync(MigrationStepEnum.AspxPages, MessageTypeEnum.Information, $"The file {targetFileName}.razor.cs was copied to {targetFolder.Name}."); } } } catch (Exception unhandledError) { await _statusTracking.UpdateCurrentStatusAsync(MigrationStepEnum.AspxPages, MessageTypeEnum.Error, $"The following unhandled error occured while trying to migrate the layout files. '{unhandledError.Message}'"); } return(headerData); }
/// <summary> /// Helper method that converts Aspx Pages to Blazor pages. /// </summary> /// <param name="sourcePage">The source aspx page to be converted.</param> /// <param name="targetProject">The target blazor project to write to.</param> /// <param name="targetPagesFolder">The target visual studio project folder the converted aspx will be added to.</param> /// <param name="sourceCodeBehind">Optional parameter that provides the code behind file for the aspx page to be converted also.</param> /// <returns>Flag used to determine if the conversion was successful.</returns> private async Task ConvertAspxPage(VsDocument sourcePage, VsProject targetProject, VsProjectFolder targetPagesFolder, VsCSharpSource sourceCodeBehind = null, VsDocument sourceDocCodeBehind = null) { try { //Getting the content from the source document. var pageContent = await sourcePage.GetDocumentContentAsStringAsync(); //File.ReadAllText(result.Path); //grab the <%Page element from the source and pull it from the text. Its meta data anyway and just screws up the conversion down the line. var pageHeaderData = System.Text.RegularExpressions.Regex.Match(pageContent, @"<%@\s*[^%>]*(.*?)\s*%>").Value; if (pageHeaderData.Length > 0) { pageContent = Regex.Replace(pageContent, @"<%@\s*[^%>]*(.*?)\s*%>", string.Empty); } //Swap ASP.NET string tokens for Razor syntax (<%, <%@, <%:, <%#:, etc var targetText = RemoveASPNETSyntax(pageContent); //Convert ASP.NET into Razor syntax. **This actually presumes that any controls like <asp:ListView.. //will have an equivalent Razor component in place called <ListView.. etc var conversionData = await ReplaceAspControls(targetText); //Drop the pageHeaderData into the Dictionary for later processing by any downstream T4 factories conversionData.Add("HeaderData", pageHeaderData); //Getting the source code from the code behind file provided. var codeSource = sourceCodeBehind?.SourceCode; if ((codeSource == null) && (sourceDocCodeBehind != null)) { codeSource = await sourceDocCodeBehind.GetCSharpSourceModelAsync(); } //put the files in the target project String targetFileName = Path.GetFileNameWithoutExtension(sourcePage.Path); conversionData.Add("Namespace", $"{targetProject.DefaultNamespace}.Pages"); //Setup Page directives, using statements etc var targetWithMeta = await SetRazorPageDirectives(targetFileName, conversionData); //Adding the converted content from the aspx page to the new razor page. VsDocument success = await targetPagesFolder.AddDocumentAsync($"{targetFileName}.razor", targetWithMeta); if (success != null) { //Updating the dialog with the status the aspx page has been converted. await _statusTracking.UpdateCurrentStatusAsync(MigrationStepEnum.AspxPages, MessageTypeEnum.Information, $"Converted the aspx page to a razor page, added razor page {targetFileName}.razor"); //If we have the source code from the original aspx page add it to the razor pages folder. if (codeSource != null) { //Creating a CodeFactory model store this will be used to pass data to a T4 factory. CsModelStore modelStore = new CsModelStore(); //Adding the current class from the code behind into the model store for processing. modelStore.SetModel(codeSource.Classes.FirstOrDefault()); //Processing the T4 factory and loading the source code. var codeBehindFormattedSourceCode = Templates.PageCodeBehind.GenerateSource(modelStore, conversionData); //Calling the CodeFactory project system and adding a new code behind file and injecting the formatted code into the file. var codeBehind = await targetPagesFolder.AddDocumentAsync($"{targetFileName}.razor.cs", codeBehindFormattedSourceCode); if (codeBehind != null) { //Updating the dialog with the status the aspx page code behind has been converted. await _statusTracking.UpdateCurrentStatusAsync(MigrationStepEnum.AspxPages, MessageTypeEnum.Information, $"Converted the aspx page code behind file to a razor page code behind file, added code behind file {targetFileName}.razor.cs"); } else { //Updating the dialog with the status the aspx page code behind failed await _statusTracking.UpdateCurrentStatusAsync(MigrationStepEnum.AspxPages, MessageTypeEnum.Error, $"Failed the conversion of the aspx page code behind file to a razor page code behind file {targetFileName}.razor.cs"); } } } else { //Updating the dialog with the status the aspx page failed conversion. await _statusTracking.UpdateCurrentStatusAsync(MigrationStepEnum.AspxPages, MessageTypeEnum.Error, $"Failed the conversion of the aspx page {targetFileName}.razor. Will not convert the code behind file."); } } catch (Exception unhandledError) { await _statusTracking.UpdateCurrentStatusAsync(MigrationStepEnum.AspxPages, MessageTypeEnum.Error, $"The following unhandled error occured while trying to convert the aspx page. '{unhandledError.Message}'"); } }