27 votes

Outil pour convertir le balisage du moteur de vue WebForm en balisage du moteur de vue Razor

Existe-t-il (ou existera-t-il) un outil pour convertir le balisage du moteur de vue WebForm (aspx) en balisage du moteur de vue Razor (cshtml)?

36voto

Tsvetomir Tsonev Points 42030

Nous avons également été confrontés au problème de la conversion de nombreuses vues WebForms en Razor. Et devinez quoi, nous avons également mis au point un outil:

https://github.com/telerik/razor-converter

Il s'appuie également sur des expressions rationnelles (et pas mal d'entre elles) pour donner un sens au mumbo-jumbo WebForms, un peu comme l'outil de JohnnyO. Le nôtre pourrait couvrir quelques cas supplémentaires, mais ne me croyez pas sur parole et essayez-le à la place sur quelques vues.

10voto

Johnny Oshika Points 15580

Voici une simple Application de Console que j'ai écrit pour convertir les Formulaires web vues de Rasoir. Malheureusement, ce n'est pas l'épreuve des balles. J'ai converti environ 20 vues avec cela, et je suis la recherche que pour de simples points de vue, il est 100% correct, mais quand la vue est vraiment compliqué, la conversion n'est que d'environ 80% de réponses correctes. Même à 80%, c'est toujours mieux que d'avoir à recommencer depuis le début par la main.

Il y a certaines choses dans cet outil de conversion qui peuvent être spécifiques à la façon dont j'ai conçu mon WebForms vues, donc j'ai commenté il de sorte que vous pouvez le supprimer ou de le modifier.

Vous pouvez l'utiliser, par l'exécution de l'application console et en le passant dans un chemin d'accès au dossier ou le chemin du fichier. Si vous passez dans un dossier, il vous permet de convertir tous .aspx et .ascx fichiers dans le dossier (mais il ne sera pas recurse en sous-dossiers). Si vous passez dans un chemin de fichier, il suffira de convertir ce fichier. Une fois que c'est fait avec de la conversion, il va créer un nouveau .cshtml fichier avec le même nom que le .aspx ou .fichier ascx.

AVERTISSEMENT: Si vous possédez déjà un .cshtml fichier avec le même nom que le .aspx/.fichier ascx que vous tentez de convertir, cette application permet de remplacer l' .cshtml fichier lorsqu'il termine le .aspx/.ascx de conversion.

UTILISEZ À VOS PROPRES RISQUES. ASSUREZ-VOUS DE TOUT SAUVEGARDER AVANT D'UTILISER CET OUTIL.

Remarque: si votre aspx/fichier ascx est marqué en "lecture seule", vous obtiendrez une erreur car l'application de console ne sera pas en mesure de l'ouvrir. Assurez-vous que la lecture seule drapeau est désactivée sur tous aspx / ascx les fichiers que vous voulez convertir.

class Program {
    private readonly static string razorExtension = ".cshtml";

    /// <summary>Usage: RazorConverter.exe  "C:\Files" or RazorConverter.exe  "C:\Files\MyFile.aspx"</summary>
    static void Main(string[] args) {

        if (args.Length < 1)
            throw new ArgumentException("File or folder path is missing.");
        string path = args[0];

        List<string> convertedFiles = new List<string>();
        Regex webFormsExtension = new Regex(".aspx$|.ascx$");
        if (Directory.Exists(path)) {
            foreach (var file in Directory.GetFiles(path, "*.aspx")) {
                var outputFile = webFormsExtension.Replace(file, razorExtension);
                ConvertToRazor(file, outputFile);
                convertedFiles.Add(file);
            }

            foreach (var file in Directory.GetFiles(path, "*.ascx")) {
                var outputFile = webFormsExtension.Replace(file, razorExtension);
                ConvertToRazor(file, outputFile);
                convertedFiles.Add(file);
            }
        } else if (File.Exists(path)) {
            var match = webFormsExtension.Match(path);
            if (match.Success) {
                ConvertToRazor(path, webFormsExtension.Replace(path, razorExtension));
                convertedFiles.Add(path);
            } else {
                throw new ArgumentException(String.Format("{0} file isn't a WebForms view", path));
            }
        } else {
            throw new ArgumentException(String.Format("{0} doesn't exist", path));
        }

        Console.WriteLine(String.Format("The following {0} files were converted:", convertedFiles.Count));
        foreach (var file in convertedFiles) {
            Console.WriteLine(file);
            }
    }

    private static void ConvertToRazor(string inputFile, string outputFile) {

        // Known Bug: when writing anything directly to the response (other than for HTML helpers (e.g. Html.RenderPartial or Html.RenderAction)),
        // this Converter will not correctly generate the markup. For example:
        // <% Html.RenderPartial("LogOnUserControl"); %> will properly convert to @{ Html.RenderPartial("LogOnUserControl"); }
        // but
        // <% MyCustom("Foo"); %> will incorrectly convert to @MyCustom("Foo");

        string view;
        using (FileStream fs = new FileStream(inputFile, FileMode.Open))
        using (StreamReader sr = new StreamReader(fs)) {
            view = sr.ReadToEnd();
        }

        // Convert Comments
        Regex commentBegin = new Regex("<%--\\s*");
        Regex commentEnd = new Regex("\\s*--%>");
        view = commentBegin.Replace(view, "@*");
        view = commentEnd.Replace(view, "*@");

        // Convert Model
        Regex model = new Regex("(?<=Inherits=\"System.Web.Mvc.ViewPage<|Inherits=\"System.Web.Mvc.ViewUserControl<)(.*?)(?=>\")");
        Regex pageDeclaration = new Regex("(<%@ Page|<%@ Control).*?%>");
        Match modelMatch = model.Match(view);
        if (modelMatch.Success) {
            view = pageDeclaration.Replace(view, "@model " + modelMatch.Value);
        } else {
            view = pageDeclaration.Replace(view, String.Empty);
        }

        // TitleContent
        // I'm converting the "TitleContent" ContentPlaceHolder to View.Title because
        // that's what TitleContent was for.  You may want to ommit this.
        Regex titleContent = new Regex("<asp:Content.*?ContentPlaceHolderID=\"TitleContent\"[\\w\\W]*?</asp:Content>");
        Regex title = new Regex("(?<=<%:\\s).*?(?=\\s*%>)");
        var titleContentMatch = titleContent.Match(view);
        if (titleContentMatch.Success) {
            var titleVariable = title.Match(titleContentMatch.Value).Value;
            view = titleContent.Replace(view, "@{" + Environment.NewLine + "    View.Title = " + titleVariable + ";" + Environment.NewLine + "}");
            // find all references to the titleVariable and replace it with View.Title
            Regex titleReferences = new Regex("<%:\\s*" + titleVariable + "\\s*%>");
            view = titleReferences.Replace(view, "@View.Title");
        }

        // MainContent
        // I want the MainContent ContentPlaceholder to be rendered in @RenderBody().
        // If you want another section to be rendered in @RenderBody(), you'll want to modify this
        Regex mainContent = new Regex("<asp:Content.*?ContentPlaceHolderID=\"MainContent\"[\\w\\W]*?</asp:Content>");
        Regex mainContentBegin = new Regex("<asp:Content.*?ContentPlaceHolderID=\"MainContent\".*?\">");
        Regex mainContentEnd = new Regex("</asp:Content>");
        var mainContentMatch = mainContent.Match(view);
        if (mainContentMatch.Success) {
            view = view.Replace(mainContentMatch.Value, mainContentBegin.Replace(mainContentEnd.Replace(mainContentMatch.Value, String.Empty), String.Empty));
        }

        // Match <%= Foo %> (i.e. make sure we're not HTML encoding these)
        Regex replaceWithMvcHtmlString = new Regex("<%=\\s.*?\\s*%>"); // removed * from the first <%=\\s.*?\\s*%> here because I couldn't figure out how to do the equivalent in the positive lookbehind in mvcHtmlStringVariable
        Regex mvcHtmlStringVariable = new Regex("(?<=<%=\\s).*?(?=\\s*%>)");
        // Match <%, <%:
        Regex replaceWithAt = new Regex("<%:*\\s*");
        // Match  %>, <% (but only if there's a proceeding })
        Regex replaceWithEmpty = new Regex("\\s*%>|<%\\s*(?=})");

        var replaceWithMvcHtmlStrings = replaceWithMvcHtmlString.Matches(view);
        foreach (Match mvcString in replaceWithMvcHtmlStrings) {
            view = view.Replace(mvcString.Value, "@MvcHtmlString.Create(" + mvcHtmlStringVariable.Match(mvcString.Value).Value + ")");
            }

        view = replaceWithEmpty.Replace(view, String.Empty);
        view = replaceWithAt.Replace(view, "@");

        Regex contentPlaceholderBegin = new Regex("<asp:Content[\\w\\W]*?>");
        Regex contentPlaceholderId = new Regex("(?<=ContentPlaceHolderID=\").*?(?=\")");
        Regex contentPlaceholderEnd = new Regex("</asp:Content>");
        MatchCollection contentPlaceholders = contentPlaceholderBegin.Matches(view);
        foreach (Match cp in contentPlaceholders) {
            view = view.Replace(cp.Value, "@section " + contentPlaceholderId.Match(cp.Value).Value + " {");
        }
        view = contentPlaceholderEnd.Replace(view, "}");

        // if we have something like @Html.RenderPartial("LogOnUserControl");, replace it with @{ Html.RenderPartial("LogOnUserControl"); }
        Regex render = new Regex("@Html\\.\\S*\\(.*\\)\\S*?;");
        var renderMatches = render.Matches(view);
        foreach (Match r in renderMatches) {
            view = view.Replace(r.Value, "@{ " + r.Value.Substring(1) + " }");
        }


        using (FileStream fs = new FileStream(outputFile, FileMode.Create)) {
            byte[] bytes = Encoding.UTF8.GetBytes(view);
            fs.Write(bytes, 0, bytes.Length);
        }
    }
}

2voto

Drew Noakes Points 69288

Les utilisateurs de ReSharper peuvent souhaiter voter pour une fonctionnalité à convertir automatiquement d'aspx en cshtml. ReSharper aura une représentation AST pour les deux côtés, de sorte qu'ils pourraient (en théorie) faire un travail très robuste sans nécessiter de regex.

http://youtrack.jetbrains.net/issue/RSRP-194060

0voto

Darin Dimitrov Points 528142

Je ne connais aucun outil permettant de le faire automatiquement car le moteur de visualisation Razor est assez nouveau et toujours en version bêta. Il n'y a pas encore de support Visual Studio comme Intellisense et la coloration syntaxique.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X