详解ASP.NET Core MVC四种枚举绑定方式
前言
本节我们来讲讲在asp.net core mvc又为我们提供了哪些方便,之前我们探讨过在asp.net mvc中下拉框绑定方式,这节我们来再来重点看看枚举绑定的方式,充分实现你所能想到的场景,满满的干货,你值得拥有。
探讨枚举绑定方式
我们首先给出要绑定的枚举类。
public enum language { javascript, java, c, python, sql, oracle }
枚举绑定方式一(@html.dropdownlist)
接下来我们废话少说直接进入主题。
viewbag.enums = enum.getvalues(typeof(language)).cast<language>();
视图页面则是得到该viewbag中的值。
@html.dropdownlist("enumlist", new selectlist(viewbag.enums), new { @class = "btn btn-success dropdown-toggle form-control" })
绑定方式二(@html.enumdropdownlistfor)
此时我们需要借助强类型视图来操作,如下控制器代码
[httpget] public iactionresult get() { var test = new testviewmodel(); return view(test); }
然后视图代码:
@html.enumdropdownlistfor(model => model.language, htmlattributes: new { @class = "form-control" })
然后你会发现在asp.net core mvc中没有此方法的实现了,具体如下:
所以到此我们研究结束,此方法应该是被.net core mvc团队已经弃用,我们继续往下看。
*枚举绑定方式三(html.getenumselectlist)
(1)单独绑定枚举
此时我们去敲@html时出现razor视图智能提示,你会看到如下的方法,该方法应该是在asp.net mvc5之后和asp.net core mvc中才有并且该方法的参数是一个type类型
@html.getenumselectlist()
那么此时我们的视图代码就演变成了如下所示。
@{ layout = null; } <!doctype html> @using webapplication1.enums <html> <head> <meta name="viewport" content="width=device-width" /> <title>index</title> </head> <body> @html.getenumselectlist(typeof(language)) </body> </html>
oh,shit,返回的是selectlistitem,看来没用对,最终尝试搞出了下面的方法
@{ layout = null; } <!doctype html> @using webapplication1.enums <html> <head> <meta name="viewport" content="width=device-width" /> <title>index</title> </head> <body> <select asp-items="@html.getenumselectlist(typeof(language))"></select> </body> </html>
这才是我们最终想要的,我们完全不需要借助强类型视图来实现,有专门针对枚举的方法,简单粗暴,但是要记住千万别再select上加上 asp-for="" 选项,否则会出现如下错误,这个没在研究了,估计和强类型视图绑定有关
虽然上述是.net core提供给我们最好的方案,确实很好,但是我们实际要的效果不是这样,我们来举一个实际场景,比如如下枚举类。
public enum paystatus { create, waitpay, waitconfirm, successed, failed, nopay }
如上显示的是支付的若干状态,当在视图上显示时总不能实现create,waitpay,waitconfirm等吧,谁懂呢,我们想要的是该枚举的描述信息,结果就演变成了如下这样。
public enum paystatus { [display(name = "新建")] create, [display(name = "等待支付")] waitpay, [display(name = "等待支付确认")] waitconfirm, [display(name = "支付成功")] successed, [display(name = "支付失败")] failed, [display(name = "无需支付")] nopay }
此时我们依然借助上述方法来实现,如下只是修改一下枚举类型即可。
<select asp-items="@html.getenumselectlist(typeof(paystatus))"></select>
.net core mvc还是强大的很啦,这样还能解析出来,上述我们是通过直接绑定枚举来实现,要是通过强类型视图呢,我们来看下:
(2)强类型视图绑定枚举
public class testviewmodel { public paystatus paystatus { get; set; } }
该方法有两个重载,如下:一个用来单独绑定枚举,一个用来绑定强类型视图上的枚举类型
// // 摘要: // returns a select list for the given enumtype. // // 参数: // enumtype: // system.type to generate a select list for. // // 返回结果: // an system.collections.generic.ienumerable`1 containing the select list for the // given enumtype. // // 异常: // t:system.argumentexception: // thrown if enumtype is not an system.enum or if it has a system.flagsattribute. ienumerable<selectlistitem> getenumselectlist(type enumtype); // // 摘要: // returns a select list for the given tenum. // // 类型参数: // tenum: // type to generate a select list for. // // 返回结果: // an system.collections.generic.ienumerable`1 containing the select list for the // given tenum. // // 异常: // t:system.argumentexception: // thrown if tenum is not an system.enum or if it has a system.flagsattribute. ienumerable<selectlistitem> getenumselectlist<tenum>() where tenum : struct;
上述居然还报错了,还是一意孤行,最终也没错误啊,如下,郁闷。
当然我们也可以在此基础上在视图上追加一个默认选项,如下:
<select asp-items="html.getenumselectlist<paystatus>()"> <option>---no specified----</option> </select>
当添加中文时,你会惊讶结果乱码了,这难道是bug么。
<select asp-items="html.getenumselectlist<paystatus>()"> <option>---"请选择"----</option> </select>
不知是何缘故,求解决这个问题,bug??????我觉得不是。。。。
枚举绑定方式四(taghelper)
上述第三种方案其实已经够我们用了,但是有时候实际情况非我们所想象的那样,在我们项目中对枚举类的描述是用的如下包
system.componentmodel.primitives
所以此时枚举就变成了如下这样:
public enum paystatus { [description("新建")] create, [description("等待支付")] waitpay, [description("等待支付确认")] waitconfirm, [description("支付成功")] successed, [description("支付失败")] failed, [description("无需支付")] nopay }
当利用displayname特性时此时是和视图相结合了的,所以razor引擎能够解析出来但是变成description特性肯定就不好使,如下:
接下来我们只能够自定义获取descriptionattribute中的值,我们通过taghelper来实现,如此对于枚举我们不再有任何限制,随心所欲。首选我们需要获取上述特性并取到其值并添加到selectlistitem中,形成一个集合,代码如下:
public list<selectlistitem> getenumselectlistitem() { var list = new list<selectlistitem>(); var typeinfo = value.gettype().gettypeinfo(); var enumvalues = typeinfo.getenumvalues(); foreach (var value in enumvalues) { memberinfo memberinfo = typeinfo.getmember(value.tostring()).first(); var descriptionattribute = memberinfo.getcustomattribute<descriptionattribute>(); list.add(new selectlistitem() { text = descriptionattribute.description, value = value.tostring() }); } return list; }
接下来我们取出遍历上述集合中的值并添加到select中,最终代码如下:
public class enumstaghelper : taghelper { public enum value { get; set; } public override void process(taghelpercontext context, taghelperoutput output) { var list = getenumselectlistitem(); output.content.appendhtml("<select>"); foreach (var item in list) { if (item.value != null) output.content.appendhtml($"<option value='{item.value}'>{item.text}</option>"); else output.content.appendhtml($"<option>{item.text}</option>"); } output.content.appendhtml("<select/>"); } }
最后就是在视图中进行调用了,如下:
@using webapplication1.enums @addtaghelper *, webapplication1 <html> <head> <meta name="viewport" charset="utf-8" /> <title>index</title> </head> <body> <enums value="@paystatus.create"></enums> </body> </html>
一切都是那么简单,你get了没有。
总结
本节详细介绍了在asp.net core mvc中如何绑定枚举的几种方式,枚举要一个好的描述从而显的更有意义,若你是利用displayname特性,那就用内置的吧,内部自动会进行解析,若是利用description特性则可以利用上述taghelper来实现,你喜欢哪种用哪种,接下来我将继续利用周末时间更新线程系列文章,也有可能会包括.net core文章,关于sql server性能优化系列暂时搁置。
上一篇: Android中mvp模式使用实例详解
下一篇: Android跨应用启动实例详解