UpdatePanel与UrlRewrite

2016-02-19 21:50 3 1 收藏

图老师小编精心整理的UpdatePanel与UrlRewrite希望大家喜欢,觉得好的亲们记得收藏起来哦!您的支持就是小编更新的动力~

【 tulaoshi.com - Web开发 】

  今天收到邮件,被问及为什么UpdatePanel如果结合了UrlRewrite就会出现问题。一开始我不以为然,由于我也曾经在UrlRewrite时使用过UpdatePanel,没有出现过问题。但是收到对方打包的代码后,发现这个问题的确重现了,如果直接访问目标页面就不会有任何问题。因为当时在公司,没有仔细地去研出错的原因。在回家的路上,脑子里一遍一遍地模拟着UpdatePanel的实现过程,却没有察觉到有任何不妥。最后还是忍不住,坐在公交车上的时候就打开笔记本,仔细的寻找问题所在。公交车实在晃得厉害,还好最终在我呕吐之前找到了问题,刚才的思考还是棋差一着。

   
  重现问题:

  现在我将重现那个问题。在原来的代码中使用了NBear的UrlRewriteModule,为了简单起见,我使用了最普通的UrlRewrite的做法来得到相同的效果,尽量避免有些朋友(包括我)因为不熟悉NBear而妨碍文章内容的理解。

  首先,新建一个ASP.NET AJAX Enabled Web Site。创建一个文件~/SubFolder/Target.aspx,内容如下:

  ~/SubFolder/Target.aspx
  html xmlns="http://www.w3.org/1999/xhtml"
  head runat="server"
      titleTarget Page/title
  /head
  body
      form id="form1" runat="server"
          asp:ScriptManager ID="ScriptManager1" runat="server"
          /asp:ScriptManager
         
          asp:UpdatePanel ID="UpdatePanel1" runat="server"
              ContentTemplate
                  %= DateTime.Now.ToString() %
                  asp:Button ID="Button1" runat="server" Text="Refresh" /
              /ContentTemplate
          /asp:UpdatePanel
      /form
  /body
  /html
   

  然后再创建一个Global.asax,提供Application_BeginRequest方法,在其中实现Url Rewrite,如下:

  Global.asax中Application_BeginRequest方法
  void Application_BeginRequest(object sender, EventArgs e)
  {
      HttpContext context = (sender as HttpApplication).Context;
      if (context.Request.Path.Contains("Source.aspx"))
      {
          context.RewritePath("SubFolder/Target.aspx", false);
      }
  }
   

(本文来源于图老师网站,更多请访问http://www.tulaoshi.com/webkaifa/)

  这样,当我们访问~/Source.aspx文件时,则会被Rewrite至~/SubFolder/Target.aspx,打开页面,一切正常:

  
  点击Refresh按钮之后,时间被更新了。然后当我们再点击按钮之后,错误发生了:“Sys.WebForms.PageRequestManagerServerErrorException: An unknown eror occurred while processing the request on the server. The status code returned from the server was: 12031”。

   

  分析问题:

  发生这个问题的原因是因为Url Rewrite更新了Form提交的地址,而UpdatePanel又将这地址的改变反映到了页面上。

  在第一次打开页面时,我们可以看到页面的源文件中form /元素的action已经不是我们访问的Source.aspx,而是Url Rewrite后的目标文件:

  form元素的action为目标页面
  ...
  form name="form1" method="post" action="SubFolder/Target.aspx" id="form1"
  ...
  /form
  ...

  还好我们使用了Partial Rendering,只要“目标”是正确的,UpdatePanel依旧能够正确地发送和获取数据,然后更新页面。因此,在点击Refresh按钮之后,页面被正确更新了。可是,我们form元素的action也变了,使用Web Development Helper和IE Dev Toolbar便一目了然:

  
  由于我们在进行异步PostBack时,直接访问了~/SubFolder/Target.aspx,因此在生成的Form对象其action值为Target.aspx。于是乎,UpdatePanel兢兢业业地将客户端form元素的action也进行了修改。这样就让我们再次提交时访问了一个不存在的页面,错误就再所难免了。

   

  解决问题:

  既然发现了问题所在,那么解决起来自然也会得心应手。我们只要在响应Sys.Application的load事件即可,它会在页面第一次加载时,以及每次Partial Rendering之后被触发,我们在这时候修改页面中form元素的action属性即可,如下:

  相应Sys.Application的load事件
  Sys.Application.add_load(function()
  {
      var form = Sys.WebForms.PageRequestManager.getInstance()._form;
      form._initialAction = form.action = window.location.href;
  });
   
  至于为什么应该这样获得页面中的form元素,_initialAction又是什么,以及为什么要设置它,就要牵涉到UpdatePanel的实现方式,在这里就不多作解释了。只要页面中放置了这么一小段代码,这个问题就被解决了。

   

  深入问题:

  造成这个问题的原因,其实就是因为在Url Rewrite之后,form元素的action并非客户端请求的地址,而是Url Rewrite的目标地址。如果我们没有使用Partial Rendering,而是使用了最传统的PostBack,虽然不会造成页面功能的破坏,但是在PostBack之后,用户就会发现地址栏的内容变了,直接变成了目标地址。这可不是我们希望看到的结果,既然Rewrite了,就把它Rewrite到底。当然,我们依然可以使用上面提到的办法,使用JavaScript来修改form元素的action,但是这个做法实在不够“美观大方”,而且用户从HTML源文件中也可以看到我们Url Rewrite的目标地址,不是吗?

  如果我们能够在服务器端设置Form的action就好了,可惜System.Web.UI.HtmlControls.HtmlForm类不允许我们这么做。不过还好,我们用的是ASP.NET,我们用的是面向对象的编程模型。于是我们“继承”System.Web.UI.HtmlControls.HtmlForm,实现一个自己的Form控件:

(本文来源于图老师网站,更多请访问http://www.tulaoshi.com/webkaifa/)

  继承HtmlForm类实现自己的From
  namespace ActionlessForm {
      public class Form : System.Web.UI.HtmlControls.HtmlForm
      {
          protected override void RenderAttributes(HtmlTextWriter writer)
          {
              writer.WriteAttribute("name", this.Name);
              base.Attributes.Remove("name");
              writer.WriteAttribute("method", this.Method);
              base.Attributes.Remove("method");
              this.Attributes.Render(writer);
              base.Attributes.Remove("action");
              if (base.ID != null)
              writer.WriteAttribute("id", base.ClientID);
          }
      }
  }
   
   

  然后我们就可以在页面中使用它了。当然,在这之前,我们需要在页面(或Web.config)里注册它:

  使用我们自己实现的Form
  %@ Register TagPrefix="skm" Namespace="ActionlessForm"
      Assembly="ActionlessForm" %
  ...
  skm:Form id="Form1" method="post" runat="server"
  ...
  /skm:Form
  ...
   

  至此,我们已经不需要在页面里编写一段“巧妙”的JavaScript了,Url Rewrite之后form元素的action问题被解决了。

  (“深入问题”参考了MSDN上一篇文章的部分内容:http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnaspp/html/urlrewriting.asp)
  http://www.cnblogs.com/JeffreyZhao/archive/2006/12/27/updatepanel_with_url_rewrite.html

来源:http://www.tulaoshi.com/n/20160219/1627275.html

延伸阅读
《骑马与砍杀:火与剑》秘籍 打开作弊模式 英文版:运行游戏 = Configure = Enables Cheats 中文版:运行游戏 = 配置 = 打开作弊模式 游戏中指定界面按以下组合键可得到对应效果: 《骑马与砍杀》专题站: 《骑马与砍杀:火与剑》r90拿满30个npc攻略 天主教: 欧洲大陆各国(法兰西,神圣罗马帝国,匈牙利公国,波兰公国) 英伦三岛(...
标签: 骑马与砍杀
《骑马与砍杀》火与剑攻略 这个版本最出彩的是剧情,骑马系列终于用上真实的城市名称跟真实的国家名称了,同时剧情有庞大的历史背景,弥补了之前系列的不足,什么时候象中世纪那样用真实的城堡村庄跟地形,那就是里程碑极的大作了! 骑砍真不愧为是经典,自己独立的小世界,自由的剧情和真实的动作,骑着战马带着兄弟飒爽在辽阔的草原!至今电...
标签: 瑜伽 养生 健康
在名人带动的效应下,瑜珈运动在这几年蔚为风潮,连美发沙龙里也出现它的踪影! 催生这套瑜伽术矿泉调息手法的,是日前亲自来台示范的黎巴tuLaoShi.com嫩裔丹麦籍、长年致力於身心疗愈艺术的瑜珈大师Elias Alouf。 简要来说,瑜伽术矿泉灵量活络的原理,就是找出自己的体质属性,搭配合适的精油芳香疗法,再加上瑜珈调息能...
《骑马与砍杀:火与剑》新手攻略 第一部份:   最近在读显克微支的《quo vadis》(君往何处去),深感写一部伟大小说,尤其写一部伟大的历史小说的不易。同样,火与剑作为骑马与砍杀这一成功游戏的最新资料片,同时又根据显氏同名小说改编,其构思、制作、发售过程也可谓艰难。   然纵观现在论坛上关于火与剑的言论,褒贬不一,或者...
《骑马与砍杀:火与剑》吐槽 最近刚玩骑马与砍杀,感觉还是满好的一款游戏 前几天刚玩的时候玩的简单难度,感觉这个游戏还蛮简单的,之后穿上黑漆铠甲后基本挂不了。战斗什么的感觉蛮简单。 结果玩了困难之后才知道,一切都是浮云。。。在火枪面前真的太浮云了。。。盗贼就会摆马车防御工事。。。20多盗贼,我50多人想去剿灭,结果步兵们还没...

经验教程

286

收藏

56
微博分享 QQ分享 QQ空间 手机页面 收藏网站 回到头部