例如我们将一个地址"showpost.aspx?postid=1000"重写为"posts/1000.aspx",如果这个页面中有个表单(form),那么输出到浏览器的HTML中,这个表单的action属性为<form action="showpost.aspx?postid=1000">而不是我们期望的<form action="1000.aspx">,这样就会暴露我们的真实地址,而且感觉也不爽。
我们可以通过自定义页面基类,重写默认的HtmlTextWriter方法,重写属性输出WriteAttribute(string name, string value, bool encode)方法,当输出action时,将action属性的值强制转换为当前虚URL(HttpContext.Current.Request.RawUrl,上面的1000.aspx)
最后就是让所有的页面都调用这个基类,修改一下Web.config就好了
<!-- Openlab.Controls.OLPage为页面基类,Openlab.Controls为基类所在dll -->
<pages pageBaseType="Openlab.Controls.OLPage, Openlab.Controls"/>
附页面基类完整代码(参考CS代码完成):
using System;
using System.IO;
using System.Web;
using System.Web.UI;
namespace Openlab.Controls

...{

/**//// <summary>
/// 页面基类
/// </summary>
public class OLPage : Page

...{
public OLPage()

...{
}

Render#region Render

/**//// <summary>
/// 重写默认的HtmlTextWriter方法,修改form标记中的value属性,使其值为重写的URL而不是真实URL。
/// </summary>
/// <param name="writer"></param>
protected override void Render(HtmlTextWriter writer)

...{
if (writer is System.Web.UI.Html32TextWriter)

...{
writer = new FormFixerHtml32TextWriter(writer.InnerWriter);
}
else

...{
writer = new FormFixerHtmlTextWriter(writer.InnerWriter);
}
base.Render(writer);
}
#endregion
}

FormFixers#region FormFixers

FormFixerHtml32TextWriter#region FormFixerHtml32TextWriter
internal class FormFixerHtml32TextWriter : System.Web.UI.Html32TextWriter

...{
private string _url; // 假的URL
internal FormFixerHtml32TextWriter(TextWriter writer):base(writer)

...{
_url = HttpContext.Current.Request.RawUrl;
}
public override void WriteAttribute(string name, string value, bool encode)

...{
// 如果当前输出的属性为form标记的action属性,则将其值替换为重写后的虚假URL
if (_url != null && string.Compare(name, "action", true) == 0)

...{
value = _url;
}
base.WriteAttribute(name, value, encode);
}
}
#endregion

FormFixerHtmlTextWriter#region FormFixerHtmlTextWriter
internal class FormFixerHtmlTextWriter : System.Web.UI.HtmlTextWriter

...{
private string _url;
internal FormFixerHtmlTextWriter(TextWriter writer):base(writer)

...{
_url = HttpContext.Current.Request.RawUrl;
}
public override void WriteAttribute(string name, string value, bool encode)

...{
if (_url != null && string.Compare(name, "action", true) == 0)

...{
value = _url;
}
base.WriteAttribute(name, value, encode);
}
}
#endregion
#endregion
}
re: 如何在URL重写后,form标记中的Action值也用虚拟地址? 是否测试过修改<form>后的页面中按钮提交是否有效?
评论
# re: 如何在URL重写后,form标记中的Action值也用虚拟地址?
是否测试过修改<form>后的页面中按钮提交是否有效?# re: 如何在URL重写后,form标记中的Action值也用虚拟地址?
No problem:)# re: 如何在URL重写后,form标记中的Action值也用虚拟地址?
一个很好的技术,记下来不过我一般用dotnet做的b/s程序,很少有在form中带server属性的
# www.dev-club.com 的 Action 提交还没有实现
www.dev-club.com 的 Action 提交还没有实现# re: 如何在URL重写后,form标记中的Action值也用虚拟地址?
宝玉 CS 中的留言本是怎么回事?# re: 如何在URL重写后,form标记中的Action值也用虚拟地址?
提交按钮不起作用了。这是怎么回事?
# re: 如何在URL重写后,form标记中的Action值也用虚拟地址?
CS的留言板就用了URL重写提交按钮实效可能是因为升级.net framework sp1的缘故
# re: 如何在URL重写后,form标记中的Action值也用虚拟地址?
不好意思,你这样作还不如继承Form 去掉Action属性呢# re: 如何在URL重写后,form标记中的Action值也用虚拟地址?
继承Form这样确实可以,但是改动量比较大哦这样做对aspx和ascx的代码基本没有改动
# re: 如何在URL重写后,form标记中的Action值也用虚拟地址?
我没有升级.net framework sp1但是我从CSPage继承过来的页面提交按钮就是不起作用
下载的cs source在我的本级中运行是没有问题的
# re: 如何在URL重写后,form标记中的Action值也用虚拟地址?
宝玉,是否考虑过在“cs_Groups”中添加一个ParentID字段,让分组支持无限级,还有把CS中的留言板扩展一下,比如私人留言和公共留言(只是角色问题)。我不知道为什么cs_Groups中没有ParentID字段,是我了解CS不够深还是CS中原本就没有这样的设计,增加ParentID字段对现有的几个组件可能帮助不大(有些论坛的Group支持不限级别的嵌套,CS中好像目前没有),但是扩展性就差了点,Group与Section如果看作是Categories,也只有两级。
# re: 如何在URL重写后,form标记中的Action值也用虚拟地址?
to abin :实际上支持无限分类,因为真正的分类是在Section表,Section中就有ParentIDto voodgen :
我继承这个基类,提交没有任何问题!
CS中也不会有这个问题
# re: 如何在URL重写后,form标记中的Action值也用虚拟地址?
提交按钮不起作用的原因我的原来的是Request.QueryString["id"]&Request.QueryString["tid"]
now action 没有这样的id 自然我也得不到遮样的参数
不知道宝玉如何解决遮样的问题
# re: 如何在URL重写后,form标记中的Action值也用虚拟地址?
to 宝玉 :没有想到ParentID在Section,谢谢宝玉# re: 如何在URL重写后,form标记中的Action值也用虚拟地址?
我改写的是nGallery Photo Gallery 的继承页面原来继承的是nGalleryPage : System.Web.UI.Page
现在我改写nGalleryPage : CSPage //System.Web.UI.Page
在图片的详细页面中就无法回复
# re: 如何在URL重写后,form标记中的Action值也用虚拟地址?
to voodgen: 您可以考虑在action中保留url参数,这样就照样可以获取了# re: 如何在URL重写后,form标记中的Action值也用虚拟地址?
宝玉你好吗,麻烦你了我想问一下cs的blogs如何把一个页面的具体内容提交到另外一个页面的
即使那个页面布存在
如
http://blog.joycode.com/dotey/archive/2005/03/10/45572.aspx
我看了源代码。在siteurls.config代码中是这样写的
<url name = "weblogpostId" location = "weblogs" path="{0}/archive/{1}/{2}/{3}/{4}.aspx" pattern="([\w\.-]+)/archive/(\d{4})/(\d{1,2})/(\d{1,2})/(\d+)\.aspx" vanity="post.aspx?App=$1&y=$2&m=$3&d=$4&PostID=$5" />
当然还有其他的
我知道是重写HttpHandler HttpModule但是不知道是如何实现的
能否给个提示
谢谢拉
# re: 如何在URL重写后,form标记中的Action值也用虚拟地址?
这部分市在HttpModule里面处理的,你可以看看components\components\siteurls.cs中的代码!# re: 如何在URL重写后,form标记中的Action值也用虚拟地址?
CS 数据库中除了cs_Posts 是存储提交的信息(如:一则帖子,一则Blog,Blog的一则回复,投票,相册的一则,相册的评论等)以外,还有两个辅助的表cs_Post_Categories,cs_Posts_InCategories,cs_Post_Categories表存储分类信息,原本认为信息的分类会存储在cs_Groups或者是cs_Sections中,结果都不是。在cs_Post_Categories中包括了SectionID,同时也是作为对Section下一级的扩展,这种扩展不会影响Section本身,也就是说如果改动了Section的设置,不会影响到Section下的内容,cs_Post_Categories中包含ParentID字段,可以方便的进行多级目录嵌套,从而实现目录树结构。CategoryType字段用于识别分类的类型,目前的类型有ForumPost = 1,BlogPost = 2,BlogArticle = 3,GalleryPicture = 4,CalendarEvent = 5。
cs_Posts_InCategories表只有三个字段CategoryID,PostID,SettingsID,在我的设计中信息与信息分类通常用两个表完成,如Categories表与Posts表,Posts表中给出一个字段叫CategoryID,然后对Categories中的CategoryID进行关系连接,从而得出该信息的所属类。但是这样设计无法解决一个问题:同一篇文章要在两个类中同时显示,而不重复信息在Posts表中。而利用三个表(CS中所采用的)可以很好解决这个问题,增加程序的弹性,可以单一也可以重复。CS的Blog中发表的文章就可以同时在多个分类中进行显示,原理很简单,只要在cs_Posts_InCategories中提交CategoryID,PostID的引用即可。
个人的一点分析,仅供参考用。
另外,宝玉,ApplicationType枚举与CategoryType枚举中都有Calendar = 4,CalendarEvent = 5。,是不是CS中还有新的项目要加入,而且很可能是一个类似Hotmail中日程安排类的项目?
# re: 如何在URL重写后,form标记中的Action值也用虚拟地址?
应该是有新项目加入,这点你可以到官方论坛发帖子问问:)# re: 如何在URL重写后,form标记中的Action值也用虚拟地址?
请问<pages pageBaseType="Openlab.Controls.OLPage, Openlab.Controls"/>
加在什么地方?
# re: 如何在URL重写后,form标记中的Action值也用虚拟地址?
<system.web></system.web>之间# re: 如何在URL重写后,form标记中的Action值也用虚拟地址?
宝玉 能发个完整的程序吗?我照你的代码,放进去后,没有效果呢。