本節咱們來說講在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性能優化系列暫時擱置。