Asp.net根据形参自动获取提交数据

作者:翅膀的初衷 来源:本站原创 发布时间:2013-12-22 查看数:61890

在Asp.Net MVC中定义Action时,要获取页面提交的参数,我们可以在方法内直接通过Request.QuestString或者Request.Form接收,也可以定义在形参中,尤为方便的是,我们甚至可以在形参中定义自定义类型(Model),不需要再 自己去new一个对象,然后判断是否存在数据,再一个一个的对属性进行赋值,极大的简化了广大码民的开发工作!

此功能其实看似很神奇,其实实现原理是很简单的。大叔在这里就给大家讲一下,如何实现这样的功能!

做这样类似的功能,我们必须用到一个.net下很强大的功能——反射,以前很多同学一听到反射,就会嚷嚷:不行不行,反射效率太低了!其实大叔说呢,这些同学一般都是要么开发才进门不久,要么呢就是本身技术功底就不杂实,就像我们老大一样,硬性规定一个可请求的地址一定要对应一个aspx页面及一个aspx.cs代码文件,他无法理解在Mvc中有些页面根本没有对应的Aspx页面的情况一样!

反射确实会造成一定的性能损耗,但是并没有我们想象中的那么恐怖,事实上我们大多数的性能瓶颈都来源于外部IO,比如数据库!而反射带来的性能损耗,很多情况下都是可以忽略不计的, 而且我们也在不知不觉中在用着反射,比如现在的各种ORM不说,Asp.Net MVC框架本身都在大量的运用反射,就算是很老的WebForm,我们的Eval也是通过反射处理的!

好,废话到此为止,下面直接进处正文!

原理如下:

1.判断请求类型,以判断数据来源,只需要考虑GET与POST即可!

2.通过反射获取方法的形参,根据参数名去Request.QueryString或者Request.Form提取值!

详细代码:

:::: {#highlighter_795673 .syntaxhighlighter .csharp} ::: toolbar ?{.toolbar_item .command_help .help} :::

+--------------------------------------+---------------------------------------------------------------------------------+ | ::: {.line .number1 .index0 .alt2} | :::::::::::::::::::::::::::::::::::::::: container | | 1 | ::: {.line .number1 .index0 .alt2} | | ::: |         {.csharp .spaces}MethodInfo m = GetMethod(action, type);{.csharp | | | .plain}//获取方法信息{.csharp .comments} | | ::: {.line .number2 .index1 .alt1} | ::: | | 2 | | | ::: | ::: {.line .number2 .index1 .alt1} | | |         {.csharp .spaces}ParameterInfo[] info = m.GetParameters();{.csharp | | ::: {.line .number3 .index2 .alt2} | .plain}//获取参数列表{.csharp .comments} | | 3 | ::: | | ::: | | | | ::: {.line .number3 .index2 .alt2} | | ::: {.line .number4 .index3 .alt1} |         {.csharp .spaces}NameValueCollection collection;{.csharp .plain} | | 4 | ::: | | ::: | | | | ::: {.line .number4 .index3 .alt1} | | ::: {.line .number5 .index4 .alt2} |         {.csharp .spaces}if{.csharp | | 5 | .keyword} (Request.HttpMethod.ToUpper() == {.csharp .plain}"POST"{.csharp | | ::: | .string}){.csharp .plain} | | | ::: | | ::: {.line .number6 .index5 .alt1} | | | 6 | ::: {.line .number5 .index4 .alt2} | | ::: |         {.csharp .spaces}{{.csharp .plain} | | | ::: | | ::: {.line .number7 .index6 .alt2} | | | 7 | ::: {.line .number6 .index5 .alt1} | | ::: |             {.csharp .spaces}collection = Request.Form;{.csharp | | | .plain}//如果是POST请求,则从Request.Form取值{.csharp .comments} | | ::: {.line .number8 .index7 .alt1} | ::: | | 8 | | | ::: | ::: {.line .number7 .index6 .alt2} | | |         {.csharp .spaces}}{.csharp .plain} | | ::: {.line .number9 .index8 .alt2} | ::: | | 9 | | | ::: | ::: {.line .number8 .index7 .alt1} | | |         {.csharp .spaces}else{.csharp .keyword} | | ::: {.line .number10 .index9 .alt1} | ::: | | 10 | | | ::: | ::: {.line .number9 .index8 .alt2} | | |         {.csharp .spaces}{{.csharp .plain} | | ::: {.line .number11 .index10 .alt2} | ::: | | 11 | | | ::: | ::: {.line .number10 .index9 .alt1} | | |             {.csharp .spaces}collection = Request.QueryString;{.csharp | | ::: {.line .number12 .index11 .alt1} | .plain}//GET请求的话,从Request.QueryString取值{.csharp .comments} | | 12 | ::: | | ::: | | | | ::: {.line .number11 .index10 .alt2} | | ::: {.line .number13 .index12 .alt2} |         {.csharp .spaces}}{.csharp .plain} | | 13 | ::: | | ::: | | | | ::: {.line .number12 .index11 .alt1} | | ::: {.line .number14 .index13 .alt1} |   | | 14 | ::: | | ::: | | | | ::: {.line .number13 .index12 .alt2} | | ::: {.line .number15 .index14 .alt2} |   | | 15 | ::: | | ::: | | | | ::: {.line .number14 .index13 .alt1} | | ::: {.line .number16 .index15 .alt1} |         {.csharp .spaces}object{.csharp | | 16 | .keyword}[] value = newobject[info.Length];{.csharp .plain}//实参{.csharp | | ::: | .comments} | | | ::: | | ::: {.line .number17 .index16 .alt2} | | | 17 | ::: {.line .number15 .index14 .alt2} | | ::: |         {.csharp .spaces}for{.csharp .keyword} ({.csharp | | | .plain}int{.csharp .keyword} i = 0; i < info.Length; i++){.csharp .plain} | | ::: {.line .number18 .index17 .alt1} | ::: | | 18 | | | ::: | ::: {.line .number16 .index15 .alt1} | | |         {.csharp .spaces}{{.csharp .plain} | | ::: {.line .number19 .index18 .alt2} | ::: | | 19 | | | ::: | ::: {.line .number17 .index16 .alt2} | | |   | | ::: {.line .number20 .index19 .alt1} | ::: | | 20 | | | ::: | ::: {.line .number18 .index17 .alt1} | | |             {.csharp .spaces}if{.csharp | | ::: {.line .number21 .index20 .alt2} | .keyword} (IsSystemBaseType(info[i].ParameterType.FullName)) {.csharp | | 21 | .plain}//此处判断是否系统基本类型{.csharp .comments} | | ::: | ::: | | | | | ::: {.line .number22 .index21 .alt1} | ::: {.line .number19 .index18 .alt2} | | 22 |             {.csharp .spaces}{{.csharp .plain} | | ::: | ::: | | | | | ::: {.line .number23 .index22 .alt2} | ::: {.line .number20 .index19 .alt1} | | 23 |                 {.csharp .spaces}object{.csharp | | ::: | .keyword} val = collection[info[i].Name];{.csharp | | | .plain}//是基本类型,直接从集合中取值{.csharp .comments} | | ::: {.line .number24 .index23 .alt1} | ::: | | 24 | | | ::: | ::: {.line .number21 .index20 .alt2} | | |                 {.csharp .spaces}if{.csharp .keyword} (val != {.csharp | | ::: {.line .number25 .index24 .alt2} | .plain}null{.csharp .keyword}){.csharp .plain}//参数不为空{.csharp | | 25 | .comments} | | ::: | ::: | | | | | ::: {.line .number26 .index25 .alt1} | ::: {.line .number22 .index21 .alt1} | | 26 |                 {.csharp .spaces}{{.csharp .plain} | | ::: | ::: | | | | | ::: {.line .number27 .index26 .alt2} | ::: {.line .number23 .index22 .alt2} | | 27 |                     {.csharp | | ::: | .spaces}value[i] = Convert.ChangeType(val, info[i].ParameterType);{.csharp | | | .plain}//进行类型转换{.csharp .comments} | | ::: {.line .number28 .index27 .alt1} | ::: | | 28 | | | ::: | ::: {.line .number24 .index23 .alt1} | | |                 {.csharp .spaces}}{.csharp .plain} | | ::: {.line .number29 .index28 .alt2} | ::: | | 29 | | | ::: | ::: {.line .number25 .index24 .alt2} | | |                 {.csharp .spaces}else{.csharp .keyword} | | ::: {.line .number30 .index29 .alt1} | ::: | | 30 | | | ::: | ::: {.line .number26 .index25 .alt1} | | |                 {.csharp .spaces}{{.csharp .plain} | | ::: {.line .number31 .index30 .alt2} | ::: | | 31 | | | ::: | ::: {.line .number27 .index26 .alt2} | | |                     {.csharp | | ::: {.line .number32 .index31 .alt1} | .spaces}value[i] = info[i].DefaultValue;{.csharp | | 32 | .plain}//参数为空,则取默认值{.csharp .comments} | | ::: | ::: | | | | | ::: {.line .number33 .index32 .alt2} | ::: {.line .number28 .index27 .alt1} | | 33 |                 {.csharp .spaces}}{.csharp .plain} | | ::: | ::: | | | | | ::: {.line .number34 .index33 .alt1} | ::: {.line .number29 .index28 .alt2} | | 34 |   | | ::: | ::: | | | | | ::: {.line .number35 .index34 .alt2} | ::: {.line .number30 .index29 .alt1} | | 35 |             {.csharp .spaces}}{.csharp .plain} | | ::: | ::: | | | | | ::: {.line .number36 .index35 .alt1} | ::: {.line .number31 .index30 .alt2} | | 36 |             {.csharp .spaces}else{.csharp .keyword} | | ::: | ::: | | | | | ::: {.line .number37 .index36 .alt2} | ::: {.line .number32 .index31 .alt1} | | 37 |             {.csharp .spaces}{{.csharp .plain} | | ::: | ::: | | | | | | ::: {.line .number33 .index32 .alt2} | | |                 {.csharp | | | .spaces}value[i] = PopulateEntity(info[i].ParameterType, collection);{.csharp | | | .plain}//自定义实体处理,还可以判断是否数组类型{.csharp .comments} | | | ::: | | | | | | ::: {.line .number34 .index33 .alt1} | | |   | | | ::: | | | | | | ::: {.line .number35 .index34 .alt2} | | |             {.csharp .spaces}}{.csharp .plain} | | | ::: | | | | | | ::: {.line .number36 .index35 .alt1} | | |   | | | ::: | | | | | | ::: {.line .number37 .index36 .alt2} | | |         {.csharp .spaces}}{.csharp .plain} | | | ::: | | | :::::::::::::::::::::::::::::::::::::::: | +--------------------------------------+---------------------------------------------------------------------------------+ ::::

自定义的实体的赋值也差不多,先通过反射获取实体的属性,再通过属性名去提取值

:::: {#highlighter_110336 .syntaxhighlighter .csharp} ::: toolbar ?{.toolbar_item .command_help .help} :::

+--------------------------------------+--------------------------------------------------------------------------------------------------------------------------------+ | ::: {.line .number1 .index0 .alt2} | :::::::::::::::::::::::::::::: container | | 1 | ::: {.line .number1 .index0 .alt2} | | ::: |     {.csharp .spaces}public{.csharp .keyword} object{.csharp | | | .keyword} PopulateEntity(Type type, System.Collections.Specialized.NameValueCollection collection){.csharp .plain} | | ::: {.line .number2 .index1 .alt1} | ::: | | 2 | | | ::: | ::: {.line .number2 .index1 .alt1} | | |     {.csharp .spaces}{{.csharp .plain} | | ::: {.line .number3 .index2 .alt2} | ::: | | 3 | | | ::: | ::: {.line .number3 .index2 .alt2} | | |         {.csharp .spaces}object{.csharp .keyword} entity = Activator.CreateInstance(type);{.csharp | | ::: {.line .number4 .index3 .alt1} | .plain}//根据类型创建实例{.csharp .comments} | | 4 | ::: | | ::: | | | | ::: {.line .number4 .index3 .alt1} | | ::: {.line .number5 .index4 .alt2} |         {.csharp .spaces}PropertyInfo[] propertys = type.GetProperties();{.csharp .plain}//获取所有属性{.csharp | | 5 | .comments} | | ::: | ::: | | | | | ::: {.line .number6 .index5 .alt1} | ::: {.line .number5 .index4 .alt2} | | 6 |         {.csharp .spaces}foreach{.csharp .keyword} (PropertyInfo item {.csharp .plain}in{.csharp | | ::: | .keyword} propertys){.csharp .plain}//循环赋值{.csharp .comments} | | | ::: | | ::: {.line .number7 .index6 .alt2} | | | 7 | ::: {.line .number6 .index5 .alt1} | | ::: |         {.csharp .spaces}{{.csharp .plain} | | | ::: | | ::: {.line .number8 .index7 .alt1} | | | 8 | ::: {.line .number7 .index6 .alt2} | | ::: |             {.csharp .spaces}if{.csharp .keyword} (IsSystemBaseType(item.PropertyType.FullName)){.csharp .plain} | | | ::: | | ::: {.line .number9 .index8 .alt2} | | | 9 | ::: {.line .number8 .index7 .alt1} | | ::: |             {.csharp .spaces}{{.csharp .plain} | | | ::: | | ::: {.line .number10 .index9 .alt1} | | | 10 | ::: {.line .number9 .index8 .alt2} | | ::: |                 {.csharp .spaces}if{.csharp .keyword} (collection[item.Name] != {.csharp .plain}null{.csharp | | | .keyword}){.csharp .plain} | | ::: {.line .number11 .index10 .alt2} | ::: | | 11 | | | ::: | ::: {.line .number10 .index9 .alt1} | | |                 {.csharp .spaces}{{.csharp .plain} | | ::: {.line .number12 .index11 .alt1} | ::: | | 12 | | | ::: | ::: {.line .number11 .index10 .alt2} | | |                     {.csharp .spaces}if{.csharp .keyword} (item.PropertyType.IsValueType && {.csharp | | ::: {.line .number13 .index12 .alt2} | .plain}string{.csharp .keyword}.IsNullOrEmpty(collection[item.Name])) {.csharp .plain}//值类型,不能为Empty{.csharp | | 13 | .comments} | | ::: | ::: | | | | | ::: {.line .number14 .index13 .alt1} | ::: {.line .number12 .index11 .alt1} | | 14 |                     {.csharp .spaces}{{.csharp .plain} | | ::: | ::: | | | | | ::: {.line .number15 .index14 .alt2} | ::: {.line .number13 .index12 .alt2} | | 15 |   | | ::: | ::: | | | | | ::: {.line .number16 .index15 .alt1} | ::: {.line .number14 .index13 .alt1} | | 16 |                     {.csharp .spaces}}{.csharp .plain} | | ::: | ::: | | | | | ::: {.line .number17 .index16 .alt2} | ::: {.line .number15 .index14 .alt2} | | 17 |                     {.csharp .spaces}else{.csharp .keyword} | | ::: | ::: | | | | | ::: {.line .number18 .index17 .alt1} | ::: {.line .number16 .index15 .alt1} | | 18 |                     {.csharp .spaces}{{.csharp .plain} | | ::: | ::: | | | | | ::: {.line .number19 .index18 .alt2} | ::: {.line .number17 .index16 .alt2} | | 19 |                         {.csharp | | ::: | .spaces}item.SetValue(entity, Convert.ChangeType(collection[item.Name], item.PropertyType), {.csharp .plain}null{.csharp | | | .keyword});{.csharp .plain} | | ::: {.line .number20 .index19 .alt1} | ::: | | 20 | | | ::: | ::: {.line .number18 .index17 .alt1} | | |                     {.csharp .spaces}}{.csharp .plain} | | ::: {.line .number21 .index20 .alt2} | ::: | | 21 | | | ::: | ::: {.line .number19 .index18 .alt2} | | |                 {.csharp .spaces}}{.csharp .plain} | | ::: {.line .number22 .index21 .alt1} | ::: | | 22 | | | ::: | ::: {.line .number20 .index19 .alt1} | | |             {.csharp .spaces}}{.csharp .plain} | | ::: {.line .number23 .index22 .alt2} | ::: | | 23 | | | ::: | ::: {.line .number21 .index20 .alt2} | | |             {.csharp .spaces}else{.csharp .keyword} | | ::: {.line .number24 .index23 .alt1} | ::: | | 24 | | | ::: | ::: {.line .number22 .index21 .alt1} | | |             {.csharp .spaces}{{.csharp .plain} | | ::: {.line .number25 .index24 .alt2} | ::: | | 25 | | | ::: | ::: {.line .number23 .index22 .alt2} | | |                 {.csharp | | ::: {.line .number26 .index25 .alt1} | .spaces}item.SetValue(entity, Convert.ChangeType(PopulateEntity(item.PropertyType, collection), item.PropertyType), {.csharp | | 26 | .plain}null{.csharp .keyword});{.csharp .plain} | | ::: | ::: | | | | | ::: {.line .number27 .index26 .alt2} | ::: {.line .number24 .index23 .alt1} | | 27 |             {.csharp .spaces}}{.csharp .plain} | | ::: | ::: | | | | | | ::: {.line .number25 .index24 .alt2} | | |         {.csharp .spaces}}{.csharp .plain} | | | ::: | | | | | | ::: {.line .number26 .index25 .alt1} | | |         {.csharp .spaces}return{.csharp .keyword} entity;{.csharp .plain} | | | ::: | | | | | | ::: {.line .number27 .index26 .alt2} | | |     {.csharp .spaces}}{.csharp .plain} | | | ::: | | | :::::::::::::::::::::::::::::: | +--------------------------------------+--------------------------------------------------------------------------------------------------------------------------------+ ::::

这里面没有判断数组的处理,如果需要处理数组,只要将取出来的值使用英文逗号","分隔即可(因为浏览器提交同个参数多个值时会自动以逗号分隔)!

原理并不复杂,在Asp.Net MVC中有很多类似功能,包括整个的框架,很有多结构都很巧妙和有趣,但是真正的原理却都是很简单的!

另外喜欢.net 开发的朋友,欢迎加入本人的.net技术交流QQ群: 5089240