问题描述:
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 voidPreSendRequestHeadersHandler(objectsender, EventArgs args) {
HttpApplication application =(HttpApplication)sender;
HttpResponse response =application.Response;

if(response.StatusCode == 302) {
        // .
}
}

我们就照葫芦画瓢自己实现一个ExtAspNet.ScriptModule:

public classScriptModule : IHttpModule
{

private voidPreSendRequestHeadersHandler(objectsender, EventArgs args)
{
HttpApplication application =(HttpApplication)sender;
HttpResponse response =application.Response;

if(response.StatusCode == 302)
{
            if(ResourceManager.IsExtAspNetAjaxPostBack2(application.Request))
{
                stringredirectLocation =response.RedirectLocation;
List<HttpCookie>cookies = newList<HttpCookie>(response.Cookies.Count);
                for(inti = 0; i <response.Cookies.Count; i++)
{
cookies.Add(response.Cookies[i]);
}

response.ClearContent();
response.ClearHeaders();
                for(inti = 0; i <cookies.Count; i++)
{
response.AppendCookie(cookies[i]);
}
response.Cache.SetCacheability(HttpCacheability.NoCache);
response.ContentType = "text/plain";
response.Write(String.Format("window.location.href='{0}';", redirectLocation));
}
}
}

#regionIHttpModule 成员

public voidDispose()
{

}

public voidInit(HttpApplication context)
{
context.PreSendRequestHeaders += newEventHandler(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 voidButton1_Click(objectsender, EventArgs e)
{
FormsAuthentication.RedirectFromLoginPage("AccountID", false);
}

3. 主页面放置一个按钮,并在Page_Load时删除登录凭证:

protected voidPage_Load(objectsender, EventArgs e)
{
FormsAuthentication.SignOut();
}
protected voidButton1_Click(objectsender, EventArgs e)
{
    //nothing
}

4. 点击此按钮时跳转到登录页面。

enjoy coding.

本文章示例源代码

注:请从SVN下载最新ExtAspNet源代码。

ExtAspNet应用技巧(三) - 302与Asp.Net Ajax相关推荐

  1. 技巧/诀窍:在ASP.NET中重写URL(转)

    [原文地址]Tip/Trick: Url Rewriting with ASP.NET [原文发表日期] Monday, February 26, 2007 9:27 PM 经常有人请我指导应该如何动 ...

  2. 技巧/诀窍:在ASP.NET中重写URL

    [原文地址]Tip/Trick: Url Rewriting with ASP.NET [原文发表日期] Monday, February 26, 2007 9:27 PM 经常有人请我指导应该如何动 ...

  3. 转: 技巧/诀窍:在ASP.NET中重写URL

    转: http://blog.joycode.com/scottgu/archive/2007/03/01/94004.aspx [原文地址]Tip/Trick: Url Rewriting with ...

  4. Linux Shell常用技巧(三) sed

    Linux Shell常用技巧(三) sed 八.流编辑器sed 8.1 sed简介 sed是stream editor的缩写,一种流编辑器,它一次处理一行内容.处理时,把当前处理的行存储在临时缓冲区 ...

  5. ASP.NET AJAX Advance Tips Tricks (11) 三种方法动态创建Tooltip

    前言 如何动态创建提示框(Tooltip)是ASP.NET Forum里的常见问题之一,在做技术支持时,我曾在英文博客上总结过ASP.NET和ASP.NET AJAX环境下如何动态创建提示框的三种常见 ...

  6. 79. Leetcode 871. 最低加油次数 (堆-技巧三-事后小诸葛)

    技巧三 - 事后小诸葛这个技巧指的是:当从左到右遍历的时候,我们是不知道右边是什么的,需要等到你到了右边之后才知道.如果想知道右边是什么,一种简单的方式是遍历两次,第一次遍历将数据记录下来,当第二次遍 ...

  7. 百万数据查询优化技巧三十则,新增5条

    百万数据查询优化技巧三十则 1.对查询进行优化,应尽量避免全表扫描,首先应考虑在 where 及 order by 涉及的列上建立索引. 2.应尽量避免在 where 子句中对字段进行 null 值判 ...

  8. 工作效率提升技巧三:做事的心态

    上升高度的东西,很多人都不喜欢.比如道理.原理.思考.态度,等等. 有时候,最没用的东西是这些上升高度的东西.有时候,最有用的东西也是这些上升高度的东西. 今天,我们就从上升高度中的"心态& ...

  9. 说话技巧三步曲--摘自《所谓高情商 就是会说话》之七个突破口

    从上篇文章 说话技巧三步曲--摘自<所谓高情商 就是会说话>   中大家发现了吧,一个最关键的步骤就是第二部,怎么揣摩对方的心理,并且找到突破口. 佐佐木圭一给我们总结了七个突破点 1. ...

最新文章

  1. Numpy关于数组的基本使用
  2. Twitter-Snowflake,64位自增ID算法详解
  3. docker centos7 chrome 安装并且支持局域网远程调试
  4. “互联网+”促传统企业三大转型
  5. LruCache在美团DSP系统中的应用演进
  6. Webpack 4.X 从入门到精通 - 第三方库(六)
  7. linux 交叉编译 makefile,简单谈谈Makefile和交叉编译工具链
  8. 由梵歌企划策划承办的方正科技总裁签售会(武汉站)圆满结束!
  9. Scintilla 开源库使用-如何设置页边背景色和前景色
  10. 行列式与矩阵的初等变换总结
  11. 微信小程序 —— 自定义picker选择器弹窗内容
  12. java web工程中如何添加图片_java web中如何添加图片
  13. PS各个工具的字母快捷键和英文全名
  14. 苏东坡有一句“八风吹不动,独坐紫金台“ 人生智慧
  15. SeasonJoe学长的考研日记
  16. 计算机专业120分,【哈尔滨工业大学,专业课120分】跟你唠点真情实感。
  17. 大屏h5互动小程序游戏又出圈啦 鱿鱼游戏跳一跳玩出了新高度
  18. 【题解】[CQOI2009] 循环赛
  19. KSM与KVM CPU、内存控制
  20. intellij idea 2016 注册码

热门文章

  1. 今日可抢回程火车票,实测两款GitHub开源抢票插件,所有坑我们都帮你踩过了...
  2. GAN和PS合体会怎样?东京大学图像增强新研究:无需配对图像,增强效果还可解释...
  3. 第一家科创板IPO的AI公司:年净利1.58亿,华为小米背后功臣,北大物理系校友创办...
  4. GraphQL 01--- GraphQL 介绍及资源总结
  5. Dubbo发展史谁知道?
  6. Springboot - -web应用开发-Servlets, Filters, listeners
  7. 深度学习专家Karpathy加入特斯拉,或将负责自动驾驶视觉研究
  8. Brocade光纤交换机FOS升级
  9. Win8.1 “运行”在Ipad Mini上
  10. 解决GNS3桥接本地网卡后无法跟本地网卡通信的故障。