======================================================
注:本文源代码点此下载
======================================================
闪存
首页
新随笔
联系
管理
订阅
随笔- 167
文章- 0
评论- 1936
extaspnet应用技巧(三) - 302与asp.net ajax
问题描述:
mgzhenhong网友提到这样的问题,并给出了示例:
1. web.config启用forms authentication。
authentication mode="forms">
forms name=".test" loginurl="~/login.aspx" timeout="20" protection="all">forms>
authentication>
authorization>
deny users="?"/>
authorization>
2. 登录页面(login.aspx)放置一个按钮,点击按钮时模拟登录:
protected void button1_click(object sender, eventargs e)
{
formsauthentication.setauthcookie("accountid", false);
pagecontext.redirect("~/default.aspx");
}
3. 主页面放置一个按钮,并在page_load时删除登录凭证:
protected void page_load(object sender, eventargs e)
{
formsauthentication.signout();
}
protected void button1_click(object sender, eventargs e)
{
// nothing
}
4. 点击此按钮时应该会跳转到登录页面,但是由于使用了extaspnet出错了:
问题分析:
首先从firebug提供的信息,我们知道在点击default.aspx页面的按钮时的确发出了两次请求,第一次返回的是 302 found,
第二次是重定向的登录页面。
这就使我想起了以前使用 response.redirect 的错误,和这个一模一样。以前我们的解决办法是告诉大家,以后不要使用response.redirect了,
使用我们extaspnet提供的方法 pagecontext.redirect ,但是现在似乎绕不过去了,有理由相信 asp.net 的form authentication内部调用了
response.redirect 函数,我们可能去修改asp.net的实现吧。
另辟蹊径:
既然绕不过 302 found 的响应,我们何不来支持它,不过诡异的是在extaspnet的ajax请求代码中:
ext.ajax.request({
url: document.location.href,
params: serializeform(theform.id),
success: _ajaxsuccess,
failure: _ajaxfailure
});
两次的http请求变成了一次,并且在回调函数(_ajaxsuccess)中观察状态码是 200, 而不是 302。
无奈之下只好借助网络,发现了下面一篇文章:
http://extjs.com/forum/showthread.php?t=30278
最终的结论居然是:
unfortunately basex can't handle 302 as the browser preempts it.
bottom line - redirects considered harmful with extjs and other ajax frameworks.
上面一句话的重点在 preempt 单词上,我特地查了一下这个单词的意思是“vt. 优先购买(先取)”,看来 302 响应是被
浏览器无情的劫持了,xmlhttprequest看到的是一个完整的http请求响应。
看来客户端无法解决这个问题。
峰回路转:
服务器端总能有办法吧,我们可以在响应流中捕获 302 ,然后进行一定的处理再输出到浏览器。
实事上 httpmodules 就不是做这个事情的么,在我开始编码之前我偷了点懒,我们这么普遍的问题asp.net ajax应该已经实现了吧,
果然如此,在\microsoft asp.net\asp.net 2.0 ajax extensions\v1.0.61025\source\system.web.extensions\handlers\scriptmodule.cs
我看到了久违的 302 :
private void presendrequestheadershandler(object sender, eventargs args) {
httpapplication application = (httpapplication)sender;
httpresponse response = application.response;
if (response.statuscode == 302) {
// .
}
}
我们就照葫芦画瓢自己实现一个extaspnet.scriptmodule:
public class scriptmodule : ihttpmodule
{
private void presendrequestheadershandler(object sender, eventargs args)
{
httpapplication application = (httpapplication)sender;
httpresponse response = application.response;
if (response.statuscode == 302)
{
if (resourcemanager.isextaspnetajaxpostback2(application.request))
{
string redirectlocation = response.redirectlocation;
listhttpcookie> cookies = new listhttpcookie>(response.cookies.count);
for (int i = 0; iresponse.cookies.count; i++)
{
cookies.add(response.cookies[i]);
}
response.clearcontent();
response.clearheaders();
for (int i = 0; icookies.count; i++)
{
response.appendcookie(cookies[i]);
}
response.cache.setcacheability(httpcacheability.nocache);
response.contenttype = "text/plain";
response.write(string.format("window.location.href='{0}';", redirectlocation));
}
}
}
#region ihttpmodule 成员
public void dispose()
{
}
public void init(httpapplication context)
{
context.presendrequestheaders += new eventhandler(presendrequestheadershandler);
}
#endregion
}
这样一来,把以前遗留的 response.redirect 不能使用的问题也解决了,现在想跳转页面既可以使用 response.redirect
也可以使用 pagecontext.redirect, 并且和 asp.net 的form authentication 也兼容了。
=============================================================
现在我们再把这篇文章开头部分的例子重新描述一下:
1. web.config启用forms authentication。
xml version="1.0"?>
configuration>
configsections>
section name="extaspnet" type="extaspnet.configsection, extaspnet"/>
configsections>
system.web>
pages>
controls>
add assembly="extaspnet" namespace="extaspnet" tagprefix="ext"/>
controls>
pages>
httpmodules>
add name="scriptmodule" type="extaspnet.scriptmodule, extaspnet"/>
httpmodules>
authentication mode="forms">
forms name=".test" loginurl="~/login.aspx" defaulturl="~/default.aspx" timeout="20" protection="all">forms>
authentication>
authorization>
deny users="?"/>
authorization>
compilation debug="true"/>
system.web>
configuration>
2. 登录页面(login.aspx)放置一个按钮,点击按钮时模拟登录:
protected void button1_click(object sender, eventargs e)
{
formsauthentication.redirectfromloginpage("accountid", false);
}
3. 主页面放置一个按钮,并在page_load时删除登录凭证:
protected void page_load(object sender, eventargs e)
{
formsauthentication.signout();
}
protected void button1_click(object sender, eventargs e)
{
// nothing
}
4. 点击此按钮时跳转到登录页面。
enjoy coding.
绿色通道:好文要顶关注我收藏该文与我联系
posted @ 2009-07-26 17:27 三生石上 阅读(3288) 评论(5)编辑 收藏
评论
2122014
回复 引用
#1楼2009-07-26 22:11 | dangnilaoqu[未注册用户]
很好,很强大,好像速度不是很快呀,官网gird才65条数据,就加载了那么长时间
回复 引用 查看
#2楼[楼主]2009-07-26 22:30 | sanshi
引用dangnilaoqu:很好,很强大,好像速度不是很快呀,官网gird才65条数据,就加载了那么长时间
可能是网络速度的问题吧。grid的速度还好
回复 引用 查看
#3楼2009-07-27 09:46 | mgzhenhong
不错,看来我抛出一块砖,引出一片玉。 果然是302。
回复 引用 查看
#4楼[楼主]2009-07-27 09:54 | sanshi
@mgzhenhong
谢谢。
目前svn缺少scriptmodule.cs文件,是漏提交了。可以直接把本页面的scriptmodule代码保存为scriptmodule.cs即可使用。
回复 引用 查看
#5楼2011-06-10 12:29 | underwing
.net3.5中不行啊!
(经过测试,可用! 只是和net3.5 web.config 默认配置冲突,去掉冲突项就ok了)
发表评论
昵称: [登录]
主页:
邮箱:(仅博主可见)
验证码:看不清。
换一个
评论内容:
记住我的昵称和主页
-->
[使用ctrl+enter键快速提交评论]
0
1531440
rizkhfqitc4=
最新it新闻:
·android平台12月广告浏览份额51.6% 超越ios
» 更多新闻...
最新知识库文章:
======================================================
在最后,我邀请大家参加新浪APP,就是新浪免费送大家的一个空间,支持PHP+MySql,免费二级域名,免费域名绑定 这个是我邀请的地址,您通过这个链接注册即为我的好友,并获赠云豆500个,价值5元哦!短网址是http://t.cn/SXOiLh我创建的小站每天访客已经达到2000+了,每天挂广告赚50+元哦,呵呵,饭钱不愁了,\(^o^)/