多提交按钮的表单
用过Asp.net WebForms框架的人可能都写过这样的页面:一个页面中包含多个服务端按钮。处理方式嘛,也很简单:在每个按钮的事件处理器写上相应的代码就完事了,根本不用我们想太多。
不过,对于不理解这背后处理过程的开发人员来说,当他们转到MVC框架下,可能会被卡住:MVC框架中可没有按钮事件!即使用不用MVC框架,用ashx通用处理器的方式,也会遇到这种问题,怎么办?
对于这个问题,本文将站在HTML角度给出二个最根本的解决办法。
方法1:根据【成功控件】定义,我们设置按钮的name,在服务端用name来区分哪个按钮的提交:
HTML代码
服务端处理代码
方法2:我将二个按钮的name设置为相同的值(根据前面的成功控件规则,只有被点击的按钮才会提交),在服务端判断value,示例代码如下:
当然了,解决这个问题的方法很多,我们还可以在提交前修改form.action属性。对于MVC来说,可能有些人会选择使用Filter的方式来处理。最终选择哪种方法,可根据各自喜好来选择。
我可能更喜欢直接使用Ajax提交到一个具体的URL,这样也很直观,在服务端也就不用这些判断了。接着往下看吧。
上传文件的表单
前面我说到“数据的编码”提到了form.enctype,这个属性正是上传表单与普通表单的区别,请看以下示例代码:
我将上传2个小文件:
我们再来看看当我点击提交按钮时,浏览器发送的请求是个什么样子的:
注意我用红色边框框出来的部分,以及请求体中的内容。此时请求头Content-Type的值发生了改变,而且还多了一个叫boundary的参数,它将告诉服务端:请求体的内容以这个标记来分开。 并且,请求体中每个分隔标记会单独占一行,且具体内容为:”–” + boundary,最后结束的分隔符的内容为:”–” + boundary + “–” 也是独占一行。从图片中我们还可以发现,在请求体的每段数据前,还有一块描述信息。
具体这些内容是如何生成的,可以参考本文后面的实现代码。
再来看看在服务端如何读取上传的文件。
或者
二种方法都行,前者更能体现控件的name与服务端读取的关系,后者在多文件上传时有更好的扩展性。
安全问题:注意,上面示例代码中,这样的写法是极不安全的。正确的做法应该是:重新生成一个随机的文件名,而且最好能对文件内容检查,例如,如果是图片,可以调用.net的一些图形类打开文件,然后”另存”文件。总之,在安全问题面前只有一个原则:不要相信用户的输入,一定要检查或者转换。