我的项目是参考 Cuyahoga-1.52 的模块设计直接在.net 2.0 上实现的,包括 UrlRewrite。原来在iis环境下一直都有正常运行。但是移植到linux/mono后,url rewrite后的 form action 不能正常工作了。
(原文链接 http://ddbiz.com/?p=226)
举个例子,如下面类似请求:
url: http://a.b.c/xxxxx/A_0_0_1.html
被解析为
(http://a.b.c/)xxxxx/A.aspx?a=0&b=0&c=1
其中 xxxxx 是某一个模块,在iis/.net2.0的环境中,转换后的 form action 为:
...
<form action="A.aspx?a=0&b=0&c=1" ...>
...
而在 mono 的输出页面中,form action 变成了:
...
<form action="xxxxx/A.aspx?a=0&b=0&c=1" ...>
...
这里 form action 使用了相对路径,这样就造成 A.aspx 上的 button 之类的 postback 指向了
http://a.b.c/xxxxx/xxxxx/A.aspx
这显然是错误的,因为 A.aspx 是在~/xxxxx/下的。开始以为是mono的移植有问题,后来仔细研究 Cuyahoga 的rewrite实现,发现其在实现rewriteurl时,采用了如下方式:
...
// 2. extract pathinfo
int pathInfoSlashPos = rewritePath.IndexOf("aspx/") + 4;
if (pathInfoSlashPos > 3)
{
pathInfo = rewritePath.Substring(pathInfoSlashPos);
rewritePath = rewritePath.Substring(0, pathInfoSlashPos);
}
...
this._currentContext.RewritePath(path, pathInfo, querystring);
...
也就是说,Context.RewritePath 使用的是3个变量的函数,MSDN 说:
instance.RewritePath(filePath, pathInfo, queryString)
C#
public void RewritePath (
string filePath,
string pathInfo,
string queryString
)
参数
filePath 内部重写路径。
pathInfo 资源的附加路径信息。
queryString 请求查询字符串。
备注
filePath 参数不包含 pathInfo 参数内容。对于 URL Http://www.microsoft.com/virdir/page.html/tail,filePath 参数为 Http://www.microsoft.com/virdir/page.html,pathInfo 参数为尾部。
看上去 pathInfo 可以用来指定模块路径,从而修正 mono 在 <form action 的写法。于是我就修改了对于 pathInfo 的检验:
...
// 2. extract pathinfo
pathInfo = urlm.PathInfo;
if (pathInfo != null )
{
int pathInfoSlashPos = rewritePath.IndexOf(pathInfo) + pathInfo.Length + 1;
if (pathInfoSlashPos < rewritePath.Length)
{
rewritePath = rewritePath.Substring(pathInfoSlashPos);
}
}
...
其中 urlm 是UrlMapping的一个对象,他的记载内容和 Cuyahoga 在 Web.config 中 <UrlMappings>...</>的定义类似,只是人为的增加了 PathInfo 的指向,调整后的页面在 mono 下终于可以正确解析了。