王朝网络
分享
 
 
 

再谈使用UrlRewrite时修改form的action属性问题

王朝other·作者佚名  2008-06-09
宽屏版  字体: |||超大  

虽然我一般属于只看不写的人,但距上一篇post竟然相隔一年多,不得不感慨时间真是快得恐怖啊……

最近创业,开展了一个Web 2.0项目,之前对Ajax、Url重写技术还有所谓的XHTML+CSS+DIV只停留在理论阶段,现在有机会付诸实践了,结果在玩UrlRewrite的时候就遇到了必然会遇到的ASP.NET的HttpForm自动将真实页面地址赋给action属性的问题。

网上Google了一下,解决办法就三种,添加客户端Java脚本,重载HttpForm或者Page类

老赵这篇帖子说明了添加客户端脚本以及重载HttpForm类的方法:http://www.cnblogs.com/JeffreyZhao/archive/2006/12/27/604373.html

而马哥(我恨用辈分称呼当网名的同志……下次我改名叫干爹,嘿嘿)这篇则说明了重载Page的方法:http://www.cnblogs.com/kaima/archive/2006/12/27/604758.html

UrlRewrite本身就有隐藏服务器处理细节的作用,这一部分要交给客户端来做感觉很别扭,所以用Java脚本的方案很快就被我否决了。

重载HttpForm类也被我否决了,通过Reflector查看代码,HttpForm的RenderAtttributes方法还包含处理客户端OnSubmit事件的代码,相当多的Web控件依赖这部分功能,去掉后就会破坏框架结构。MSDN竟然教大家用这种方法,果然MSDN还是一个需要去怀疑的东西。

马哥介绍的方法比较合理,但是我认为重载Page类也是在一般情况下应该避免的行为,一个是决定哪个页用新Page类哪页不用比较麻烦,如果为了省却麻烦,那么在web.config里设置pageBaseType属性也行,但是整个网站的页面都要过一下这个类也不太符合创业用网站的细节要求。

是不是有更好的办法呢?还真的有,是我今天在研究 ASP.NET CSS Friendly Adapters 的时候醒悟的。

这个解决方案基于上面马哥的方案修改,不过前提是必须有.NET 2.0的支持。

.NET 2.0框架给ASP.NET增加了几个特殊目录,其中有一个最容易被忽视的App_Browsers目录,这里是用来存放浏览器定义文件的,相关说明可以参考MSDN:http://msdn2.microsoft.com/zh-cn/library/ms228122(VS.80).aspx

在网站根目录创建App_Browsers目录,在里面建立一个新的文件起名 RewriteForm.browser ,其内容如下:

<browsers>

<browser refID="Default">

<controlAdapters>

<adapter controlType="System.Web.UI.HtmlControls.HtmlForm"

adapterType="Kuang.HtmlFormAdapter" />

</controlAdapters>

</browser>

</browsers>

其中,browser节的 refID="Default" 属性是表示扩展系统原有的Default.browser文件(位于 %windir%\Microsoft.NET\Framework\v2.0.50727\CONFIG\Browsers ),Default.browser 是全部浏览器定义的根,具体细节请参考MSDN说明。

Adapter的意思是适配器,在.NET领域表示在两个对象之间进行协调的对象,例如ADO.NET中众所周知的SqlDataAdapter类就是在SqlCommand和DataSet之间协调的Adapter。

ASP.NET 2.0带来了ControlAdapter的概念,意思是位于System.Web.UI.Control对象和ASP.NET之间的Adapter,同时也有PageAdapter,用于处理System.Web.UI.Page对象。

ControlAdapter并没有什么特殊的功能,只不过和重载Page类的方法相比较,前者提供了重载Web控件Render方法的能力而又不需要继承该控件,并且可以只针对特定的控件例如这里的HtmlForm类。而在马哥的方法中,如果有别的控件也用了action属性,就会被错误的改写。在 RewriteForm.browser 文件中,通过 <adapter controlType="System.Web.UI.HtmlControls.HtmlForm" adapterType="Kuang.HtmlFormAdapter" /> 这行,我指定了要重载HtmlForm类,并且提供了我自定义的ControlAdapter类的类型 Kuang.HtmlFormAdapter。

下面这个是自定义的ControlAdapter类的代码:

using System;

using System.Web.UI.Adapters;

namespace Kuang {

public class HtmlFormAdapter : ControlAdapter {

protected override void Render(System.Web.UI.HtmlTextWriter writer) {

base.Render(new FormRewriteTextWriter(writer));

}

}

}

和重载Page类的手段一样,这段代码也引用了一个自定义的 HtmlTextWriter 类,以下是该类的实现代码,我自己做了一定的修改:

using System;

using System.IO;

using System.Web;

using System.Web.UI;

namespace Kuang {

public class FormRewriteTextWriter : HtmlTextWriter {

public FormRewriteTextWriter(TextWriter writer) : base(writer) {

if(writer is HtmlTextWriter)

this.InnerWriter = (writer as HtmlTextWriter).InnerWriter;

else

this.InnerWriter = writer;

}

public override void WriteAttribute(string name, string value, bool fEncode) {

HttpContext context = HttpContext.Current;

object rewroteAlready = context.Items["FormActionRewroteAlready"];

if(name == "action" && rewroteAlready == null) {

value = context.Request.RawUrl;

context.Items["FormActionRewroteAlready"] = new object();

}

base.WriteAttribute(name, value, fEncode);

}

}

}

把以上两段代码放入到网站的App_Code目录下,就大功告成了,这个方法一个特别的优点是,不需要改动原来网站的任何代码,连 web.config 都不用改。

大家可以尝试一下,欢迎交流心得。

BTW:老赵提到的UpdatePanel和Form并存是不能提交第二次的问题,我没有遇到过,难道是因为我的UpdatePanel是嵌在Form里面的而不是Form嵌在UpdatePanel里面的缘故?

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
>>返回首页<<
推荐阅读
 
 
频道精选
 
静静地坐在废墟上,四周的荒凉一望无际,忽然觉得,凄凉也很美
© 2005- 王朝网络 版权所有