• 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性能优化系列暂时搁置。

  • 相关阅读:
    2 安装部署flume
    1 flume快速入门——十分钟学会flume
    3、剑指offer-数组——数组中重复的数字
    3.kafka安装配置
    2、剑指offer-字符串——替换空格
    1、剑指offer-数组——二维数组中的查找
    JVM虚拟机垃圾回收(GC)算法及优缺点
    Exception in thread "main" java.lang.NoClassDefFoundError: com/google/common/collect/ImmutableMap
    LeetCode 617. 合并二叉树 Java
    Linux命令大全
  • 原文地址:https://www.cnblogs.com/ZaraNet/p/9663249.html
Copyright © 2020-2023  润新知