url重写,一般都是先配置重写规则如:
virtualUrl="^~/(\d+).html"
toUrl = "~/Default.aspx?ID=$1"
这样就能通过访问/100.html重写到实际的default.aspx?id=100的地址。
然后在页面中这样写: <a href="/100.html"> 而不是原先的<a href="default.aspx?id=100">
假如要修改重写的地址,责要修改所有页面的重写链接,以及重写规则。很是麻烦!
--------------问题来了:
上面输出url的两个a瞄,一个是重写的,一个是未重写的实际地址。 如何自动切换,最笨的方法可能用if(重写==true)就输出/100.html,否则是默认的,在每一个a超连接上进行判断输出,这样很累。
能否通过一个方法自动反射出想要的链接呢, 如<a href="<%=getUrl("default.aspx?id=100") %>"> ,这个getUrl(string)的方法去读取规则,反射出virtualUrl地址,这样以后只需要修改重写规则,页面就会自动输出新的规则地址,无需再修改每个页面的超链接。还可以通过判断切换输出,如没开启重写,直接原样返回输出。
想要这个getUrl(string)的方法代码,不要非常详细,大致能实现即可。谢谢
因为getUrl传入的是实际url地址,而在规则里面toUrl的数据不是正则格式,只是匹配格式。这个可能有点难度,还得有点性能。 再谢!
// 我大概的写写,里面关键的集合匹配以及构造虚拟url的代码不知道怎样写了
// 希望高手帮忙. 或提供下其他的思路
public static getUrl(string originalUrl)
{
if(systemIsUrlRewrite)
{
foreach(reurl in reurls)//遍历重写的正则集合
{
if(originalUrl 匹配 reurl.toUrl)
{
return build_virtualUrl(reurl,originalUrl);
//如果集合中有此url的重写规则,就输出此源url的虚拟url,也得用正则吧?
}
}
}
else
{
return originalUrl;//系统没开启url重写,直接返回原始url
}
}
明天.NET 老大, 谢谢你的代码思路,我改写了下, 脑子还有点乱, 现在是完全可以反置那些"正规"的规则了,也就是虚拟url和实际url匹配组要相等. 遇到不相等的恐怕还得加一个循环去折腾. 我觉得在反转替换的时候可以直接在正则遍历时进行,正好减少一个循环. 我再清理下头绪,添加个循环处理"不规则"的规则,应该还是3个循环.
这是我改后的: 恳请斧正
再次修改====改为3个循环, 简单测试支持复杂的规则匹配,不限定规则组次序. 想了想或许只有2个循环也能解决 用到使用只需要解决字符转义了.
protected void Page_Load(object sender, EventArgs e)
{
UrlRewriteRoute test = new UrlRewriteRoute();
//test.VirtualPath = @"~/ 数字(\d+) / 字符(\w+) / 字母([a-zA-Z]*) - 无厘头(.*) \.html";
//test.ToUrl = @"~/1.aspx? 字母=$3 字符=$2 无厘头=$4 数字=$1";
test.VirtualPath = @"~/([a-zA-Z]*)\/(.[0-9]*[a-zA-Z]*)/([0-9]*)/(\w+)/([a-zA-Z]*)\.aspx";
test.ToUrl = @"~/WebPage/$1/$2.aspx?classid=$2;page=$3;keys=$4";
var result = ReverseRoute(test);
Response.Write(test.VirtualPath + "<br/>" + test.ToUrl + "<br/><br/>");
Response.Write(result.VirtualPath + "<br/>" + result.ToUrl + "<br/>");
}
public static UrlRewriteRoute ReverseRoute(UrlRewriteRoute route)
{
UrlRewriteRoute result = new UrlRewriteRoute();
string New_toUrl = route.VirtualPath; //反转定义
string New_virtualUrl = route.ToUrl;
List<string> virtualList = new List<string>();
MatchCollection virtualMatch = Regex.Matches(route.VirtualPath, @"(\(.+?\))");
//先遍历出来转存到List ,List输出内容后倒置成位置索引
foreach (Match m in virtualMatch)
{
virtualList.Add(m.Groups[1].Value);
}
Regex tourlReg = new Regex(@"\$(\d+)");
int i = 1;
foreach (Match m in tourlReg.Matches(route.ToUrl))
{
int GroupNum = Convert.ToInt32(m.Groups[1].Value);
if (virtualList.Count >= GroupNum)
{
New_virtualUrl = New_virtualUrl.Replace(m.Value, string.Format("{0}", virtualList[GroupNum - 1]));
virtualList[GroupNum - 1] = "$"+i.ToString(); //将虚拟Url的索引位置倒置进去 也就是当前索引
i++;
}
}
int k = 0;
foreach (Match matGroup in virtualMatch)
{
//这里的遍历和预存virtualList是一样的,为了能够对应索引位置
//替换相同索引位置的规则匹配组为新的虚拟匹配组位置索引,已经基本支持更复杂的规则匹配
New_toUrl = New_toUrl.Replace(matGroup.Value, virtualList[k]);
k++;
}
result.ToUrl = New_toUrl;
result.VirtualPath = New_virtualUrl; //这里还要解决字符转义问题
return result;
}
public class UrlRewriteRoute
{
public string VirtualPath { get; set; }
public string ToUrl { get; set; }
}
建议可以采用Mvc那种RouteTable模式。
如:<% this.MakeUrl(new {RewriteName="default",Id=100})%> (MakeUrl自己实现对page的扩展)
当然这个UrlWrite你需要重新一下了,需要RewriteName标记区分不同的路由,通过读取配置路由生成实际路径,是否采用重写也简单啦。
------------------------
代码很简单,做一点语法分析,不知道对不对:)
附加代码:
public static void Main()
{
UrlRewriteRoute route = new UrlRewriteRoute() { VirtualPath=@"^~/(\w+)/(\d+)/(\d+)",ToUrl=@"~/default.aspx?domain=$1&id=$2&page=$3"};
var result= ReverseRoute(route);
Console.WriteLine(result.VirtualPath + Environment.NewLine + result.ToUrl + Environment.NewLine);
Console.ReadLine();
}
public static UrlRewriteRoute ReverseRoute(UrlRewriteRoute route)
{
UrlRewriteRoute result = new UrlRewriteRoute();
List<List<char>> regs = new List<List<char>>();
bool flag=false;
List<char> reg=new List<char>();
foreach (char c in route.VirtualPath)
{
if (c == '(')
{
flag = true;
reg=new List<char>();
continue;
}
if (c == ')')
{
flag = false;
regs.Add(reg);
continue;
}
if (flag)
{
reg.Add(c);
}
}
//得到正则
string[] regstrs = regs.Select(p => new String(p.ToArray())).ToArray();
string virtualPath = route.ToUrl;
Regex replaceReg = new Regex(@"\$(\d+)");
List<string> matchList = new List<string>();
foreach (Match m in replaceReg.Matches(route.ToUrl))
{
matchList.Add(m.Value);
}
string[] matchstrs=matchList.ToArray();
//VirtualPath -> ToUrl
foreach (string s in matchstrs)
{
int i=Convert.ToInt32(s.TrimStart('$'));
if (regstrs.Length >= i)
{
virtualPath = virtualPath.Replace("$" + i.ToString(),string.Format("({0})", regstrs[i - 1]));
}
}
//ToUrl->VirtualPath 这个简单只需要按顺序$1,$2```
List<char> to = new List<char>();
int index=0;
foreach (char c in route.VirtualPath)
{
if (c == '(')
{
flag = true;
continue;
}
if (c == ')')
{
flag = false;
index++;
to.AddRange("$" + index.ToString());
continue;
}
if (!flag)
{
to.Add(c);
}
}
result.ToUrl = new String(to.ToArray());
result.VirtualPath = virtualPath;
return result;
}
public class UrlRewriteRoute
{
public string VirtualPath { get; set; }
public string ToUrl { get; set; }
}