博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
FineUIMvc随笔(3)不能忘却的回发(__doPostBack)
阅读量:5291 次
发布时间:2019-06-14

本文共 4262 字,大约阅读时间需要 14 分钟。

 声明:FineUIMvc(基础版)是免费软件,本系列文章适用于基础版。

用户反馈

 

有网友在官方论坛抛出了这么一个问题,似乎对 FineUIMvc 中的浏览器端与服务器端的交互方式很有异议。

 

这里面的关键词就是:回发!

 

似乎一提到回发(__doPostBack),就让人联想到 WebForms 中的 ViewState 和单表单提交,因为回发时会把页面上所有控件的 ViewState 一股脑的提交到后台,无疑加重了网络的上行数据量。从此 回发 这一名词给人的印象就很晦涩了。

 

真的是这样吗?我们分别来比较 WebForms、ASP.NET MVC、以及FineUIMvc中的回发,来探索其中的联系和差异。

 

WebForms中的回发(__doPostBack)

每位经历过 ASP.NET WebForms 的开发人员都不会忘记这个字符串:__doPostBack,因为它出现在你写的每一个 .aspx 页面的浏览器源代码中:

 

在 WebForms 中,整个页面就是一个表单,所以早期的微软工程师大摇大摆的定义了一个全局变量:

var theForm = document.forms['form1'];

 

__doPostBack 函数则是对页面上这个唯一的表单提交( theForm.submit),传入的 eventTarget 和 eventArgument 分别用来标识本次回发的触发控件以及回发参数。

 

这些都没啥,关键是页面上永远都有一个 ViewState 隐藏字段:

 

这里面存放了页面上所有控件的状态信息,比如下拉列表的数据,表格的数据,输入框的数据等等,所有这个字段一般会比较大,导致上传的数据量动辄就有20K~1000K。在网络有限的情况下会非常影响性能,从而给人了臃肿的印象。

 

比如在 FineUI(开源版)中一个包含表格的页面:

http://fineui.com/demo/iframe/grid_iframe.aspx

页面回发时,请求的数据量就达到 19802 bytes = 19K

 

 

ASP.NET MVC中的回发(BegionForm)

在 ASP.NET MVC 中,我们可以定义多个表单,从而自行控制需要提交的表单,以及表单中字段。也就是只提交我们需要的数据,这样不仅灵活而且上传数据量不会很大。

在 MVC 的其他文档中,你可能很少会看到 回发 这个字眼,很多是这样描述的:提交某个表单到控制器的某个操作方法,或者说发起一个 HTTP POST 请求。其实这些都对应于 WebForms 中的回发字眼,只不过操作的表单和表单字段不同而已。本质上还是一样的。

在我之前写MVC系列教程中有一个典型的回发过程:

@using (Html.BeginForm()){    @Html.AntiForgeryToken()    

所学专业: @Html.DropDownList("Major", ViewBag.MajorList as IEnumerable

, "全部") 姓名: @Html.TextBox("Name")

}

 

通过 Html.BeginForm 辅助方法来生成一个表单,这个表单会提交到当前页面对应的控制器方法,默认使用 POST 请求,生成到页面的HTML结构类似:

 

表格里面,明确定义了两个表单字段,分别是 Major 和 Name,以及一个提交按钮(type=submit)。

 

对应的后台控制器方法类似:

[HttpPost][ValidateAntiForgeryToken]public ActionResult Index(string Major, string Name){    // ...    return View(students.ToList());}

 

在这个过程中,虽然我们可以控制要提交的表单,以及提交哪些参数,但这个过程还是整个页面提交。

 

而 FineUIMvc 中,我们不仅不需要定义表单(只需要告诉FineUIMvc需要提交哪些参数即可),而且所有的提交都是AJAX过程。

 

FineUIMvc中的回发(OnClick、OnPageIndexChanged)

FineUIMvc中将对控制器方法的调用放到每个具体的控件中, 对应于 FineUI(开源版)中控件的事件。

无参数回发

按钮的点击事件:

@(F.Button()    .OnClick(Url.Action("btnHello_Click"))    .ID("btnHello")    .Text("点击弹出对话框"))

这样就将按钮的客户端点击事件(click)和服务器端控制器的方法(btnHello_Click)关联起来,而且命名也和WebForms中的一模一样,是不是倍感亲切。

 

仔细观察下这个 HTTP 请求,我们就能知道这个客户端点击事件将去向何方:

 

从这张图上,我们有如下收获:

  1. Basic是区域名称(Area),Hello是当前控制器名称
  2. btnHello_Click是点击按钮时对应的控制器方法
  3. 请求方法是 POST
  4. X-Requested-Width: XMLHttpRequest,表明当前请求是AJAX

再来看下HTTP请求正文数据:

 

只要一个防止跨站请求伪造(CSRF)的参数_RequestVerificationToken,再无其他参数。

对应的控制器方法:

[HttpPost][ValidateAntiForgeryToken]public ActionResult btnHello_Click(){    Alert.Show("你好 FineUIMvc!", MessageBoxIcon.Warning);    return UIHelper.Result();}

 

因为在这个过程中,后台无需参数,所以前台也没必要传入任何数据。这样一个AJAX回发过程就非常干净,不像之前的WebForms一样,需要传递一堆参数了。

 

带参数回发

来看下表格的数据库分页事件,在数据库分页时后台C#代码需要知道两个参数:

1. 当前的页码

2. 表格中用到了哪些数据库字段,即使熟练的WebForms开发人员可能也不会意识到这一点,因为在WebForms中后台能够知道控件的所有参数,而MVC中回发时,你对表格的任何参数一无所知,所有你需要的参数都需要通过前台传入

 

FineUIMvc对于带参数的回发回发进行了深度优化,你根本无需自己通过JavaScript来获取这些参数(当然你也可以这么做,只要你愿意),而是指定表格的ID即可:

@(F.Grid()    .EnableCheckBoxSelect(true)    .Width(850)    .ShowHeader(true)    .ShowBorder(true)    .EnableCollapse(true)    .Title("表格")    .ID("Grid1")    .DataIDField("Id")    .DataTextField("Name")    .AllowPaging(true)    .PageSize(5)    .IsDatabasePaging(true)    .OnPageIndexChanged(Url.Action("Grid1_PageIndexChanged"), "Grid1")    .Columns(        F.RowNumberField(),        F.RenderField()            .HeaderText("姓名")            .DataField("Name")            .Width(80),        ....    )    .RecordCount(ViewBag.Grid1RecordCount)    .DataSource(ViewBag.Grid1DataSource))

 

注意 OnPageIndexChanged 的第二个参数,这样在发起对控制器方法(Grid1_PageIndexChanged)的POST请求时,会自动附加所需的参数:

 

对应的控制器方法:

[HttpPost][ValidateAntiForgeryToken]public ActionResult Grid1_PageIndexChanged(JArray Grid1_fields, int Grid1_pageIndex){    var grid1 = UIHelper.Grid("Grid1");    var recordCount = DataSourceUtil.GetTotalCount();    // 1.设置总项数(数据库分页回发时,如果总记录数不变,可以不设置RecordCount)    grid1.RecordCount(recordCount);    // 2.获取当前分页数据    var dataSource = DataSourceUtil.GetPagedDataTable(pageIndex: Grid1_pageIndex, pageSize: 5, recordCount: recordCount);    grid1.DataSource(dataSource, Grid1_fields);    return UIHelper.Result();}

 

小结

WebForms中的回发由于需要附加上ViewState而略显臃肿;

ASP.NET MVC原生的回发需要借助Html.BeginForm辅助方法来生成单独的表单,并把需要提交的参数放置到表单中,回发过程是整个页面提交;

FineUIMvc对回发过程进行深度优化,无需创建表单,只需要提供需要回发的参数,而且回发过程是AJAX的。对于部分控件比如表单和表格,甚至不需要指定回发参数,只需要设置控件ID即可,非常方便。

 

如果你还对WebForms中的回发念念不忘,那就无需忘却。 

 

转载于:https://www.cnblogs.com/sanshi/p/6491388.html

你可能感兴趣的文章
C#预处理器命令
查看>>
苹果手表:大方向和谷歌一样,硬件分道扬镳
查看>>
ccf 出现次数最多的数
查看>>
单例模式
查看>>
Competing Consumers Pattern (竞争消费者模式)
查看>>
HDUOJ ------1398
查看>>
cf--------(div1)1A. Theatre Square
查看>>
Android面试收集录15 Android Bitmap压缩策略
查看>>
Tomcat 报错的解决方法:The APR based Apache Tomcat Native library which allows optimal
查看>>
最长公共子串问题(LCS)
查看>>
TortoiseSVN is locked in another working copy
查看>>
PHP魔术方法之__call与__callStatic方法
查看>>
ubuntu 安装后的配置
查看>>
Html学习_简易个人网页制作
查看>>
angular中ng-bind指令小案例
查看>>
jqery总结
查看>>
Lodop获取客户端主网卡ip地址是0.0.0.0
查看>>
VSCODE更改文件时,提示:EACCES: permission denied的解决办法(mac电脑系统)
查看>>
web前端之路,js的一些好书(摘自聂微东 )
查看>>
【模板】对拍程序
查看>>