Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/facebook/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Asp.net mvc 用于将Web表单视图引擎标记转换为Razor视图引擎标记的工具_Asp.net Mvc - Fatal编程技术网

Asp.net mvc 用于将Web表单视图引擎标记转换为Razor视图引擎标记的工具

Asp.net mvc 用于将Web表单视图引擎标记转换为Razor视图引擎标记的工具,asp.net-mvc,Asp.net Mvc,是否(或将)存在一个将WebForm视图引擎标记(aspx)转换为Razor视图引擎标记(cshtml)的工具?下面是我编写的一个简单控制台应用程序,用于将WebForms视图转换为Razor。不幸的是,它不是防弹的。我用这个转换了大约20个视图,我发现对于简单视图,它的正确率是100%,但是当视图变得非常复杂时,转换的正确率只有80%。即使是在80%的情况下,这仍然比手工从头开始要好 这个转换工具中有些东西可能与我设计WebForms视图的方式有关,因此我对其进行了注释,以便您可以删除或自定义

是否(或将)存在一个将WebForm视图引擎标记(aspx)转换为Razor视图引擎标记(cshtml)的工具?

下面是我编写的一个简单控制台应用程序,用于将WebForms视图转换为Razor。不幸的是,它不是防弹的。我用这个转换了大约20个视图,我发现对于简单视图,它的正确率是100%,但是当视图变得非常复杂时,转换的正确率只有80%。即使是在80%的情况下,这仍然比手工从头开始要好

这个转换工具中有些东西可能与我设计WebForms视图的方式有关,因此我对其进行了注释,以便您可以删除或自定义它

您可以通过执行console应用程序并传入文件夹路径或文件路径来使用它。如果传入一个文件夹,它将转换该文件夹中的所有.aspx和.ascx文件(但不会递归到子文件夹)。如果传入文件路径,它将仅转换该文件。转换完成后,它将创建一个与.aspx或.ascx文件同名的新.cshtml文件

警告:如果您已经有一个与要转换的.aspx/.ascx文件同名的.cshtml文件,则此应用程序将在完成.aspx/.ascx转换后覆盖.cshtml文件

使用风险自负。使用此工具之前,请确保备份所有内容

注意:如果您的aspx/ascx文件被标记为“只读”,您将收到一个错误,因为控制台应用程序将无法打开它。确保在所有要转换的aspx/ascx文件上关闭只读标志

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);
        }
    }
}
类程序{
私有只读静态字符串razorExtension=“.cshtml”;
///用法:RazorConverter.exe“C:\Files”或RazorConverter.exe“C:\Files\MyFile.aspx”
静态void Main(字符串[]参数){
如果(参数长度<1)
抛出新ArgumentException(“缺少文件或文件夹路径”);
字符串路径=args[0];
List convertedFiles=新列表();
Regex webFormsExtension=新的Regex(“.aspx$|.ascx$”;
if(目录存在(路径)){
foreach(目录.GetFiles(路径“*.aspx”)中的var文件){
var outputFile=webFormsExtension.Replace(文件,razorExtension);
转换器(文件、输出文件);
convertedFiles.Add(文件);
}
foreach(目录.GetFiles(路径“*.ascx”)中的var文件){
var outputFile=webFormsExtension.Replace(文件,razorExtension);
转换器(文件、输出文件);
convertedFiles.Add(文件);
}
}else if(File.Exists(path)){
var match=webFormsExtension.match(路径);
如果(匹配成功){
convertorazor(路径,webFormsExtension.Replace(路径,razorExtension));
convertedFiles.Add(路径);
}否则{
抛出新ArgumentException(String.Format(“{0}文件不是WebForms视图”,路径));
}
}否则{
抛出新的ArgumentException(String.Format(“{0}不存在”,路径));
}
WriteLine(String.Format(“以下{0}文件已转换:”,convertedFiles.Count));
foreach(convertedFiles中的var文件){
Console.WriteLine(文件);
}
}
私有静态void convertorazor(字符串输入文件、字符串输出文件){
//已知错误:直接向响应写入任何内容时(HTML帮助程序除外(例如HTML.RenderPartial或HTML.RenderAction)),
//此转换器将无法正确生成标记。例如:
//将正确转换为@{Html.RenderPartial(“LogOnUserControl”);}
//但是
//将错误地转换为@MyCustom(“Foo”);
字符串视图;
使用(FileStream fs=newfilestream(inputFile,FileMode.Open))
使用(StreamReader sr=新StreamReader(fs)){
视图=sr.ReadToEnd();
}
//转换评论
Regex commentBegin=新的Regex(“”);
视图=commentBegin.Replace(视图“@*”);
视图=commentEnd.Replace(视图,“*@”);
//转换模型

Regex model=new Regex(“(?我们也面临着将大量WebForms视图转换为Razor的问题。猜猜看,我们还想出了一个工具:


它还依赖于正则表达式(其中相当多)为了理解WebForms的庞然大物,就像JohnnyO的工具一样。我们的工具可能会涉及更多的情况,但不要相信我的话,而是在一些视图上尝试它。

ReSharper的用户可能会投票选择一个功能,自动从aspx转换为cshtml。ReSharper将为双方都提供AST表示,因此他们可以(理论上)在不需要正则表达式的情况下完成非常健壮的it工作


感谢这个有用的工具。我发现的一个问题是,我的服务器注释在转换过程中被删除了。如果能将它们转换成
@*.*.*
语法就好了。Telerik的解决方案与Codeplex上的这个项目相比如何?