zoukankan      html  css  js  c++  java
  • ASP.NET Core 四种方式绑定枚举值

    前言

    本节我们来讲讲在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性能优化系列暂时搁置。

  • 相关阅读:
    CF1539 VP 记录
    CF1529 VP 记录
    CF875C National Property 题解
    CF1545 比赛记录
    CF 1550 比赛记录
    CF1539E Game with Cards 题解
    CF1202F You Are Given Some Letters... 题解
    vmware Linux虚拟机挂载共享文件夹
    利用SOLR搭建企业搜索平台 之九(solr的查询语法)
    利用SOLR搭建企业搜索平台 之四(MultiCore)
  • 原文地址:https://www.cnblogs.com/ZaraNet/p/9663249.html
Copyright © 2011-2022 走看看