本节咱们来说讲在ASP.NET Core MVC又为咱们提供了哪些方便,以前咱们探讨过在ASP.NET MVC中下拉框绑定方式,这节咱们来再来重点看看枚举绑定的方式,充分实现你所能想到的场景,满满的干货,你值得拥有。html
咱们首先给出要绑定的枚举类。性能优化
public enum Language { JavaScript, Java, C, Python, SQL, Oracle }
接下来咱们废话少说直接进入主题。mvc
ViewBag.enums = Enum.GetValues(typeof(Language)).Cast<Language>();
视图页面则是获得该ViewBag中的值。ide
@Html.DropDownList("enumList", new SelectList(ViewBag.enums), new { @class = "btn btn-success dropdown-toggle form-control" })
此时咱们须要借助强类型视图来操做,以下控制器代码性能
[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中没有此方法的实现了,具体以下:spa
因此到此咱们研究结束,此方法应该是被.net core mvc团队已经弃用,咱们继续往下看。.net
(1)单独绑定枚举线程
此时咱们去敲@Html时出现Razor视图智能提示,你会看到以下的方法,该方法应该是在ASP.NET MVC5以后和ASP.NET Core MVC中才有而且该方法的参数是一个Type类型3d
@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??????我以为不是。。。。
上述第三种方案其实已经够咱们用了,可是有时候实际状况非咱们所想象的那样,在咱们项目中对枚举类的描述是用的以下包
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性能优化系列暂时搁置。