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