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

(0)

相关推荐

  • .NET中的枚举用法浅析

    本文简单分析了.NET中的枚举用法.分享给大家供大家参考.具体分析如下: 我理解的枚举就是编程中约定的一个"可选值":例如QQ的在线状态,分别有    在线,Q我吧,隐身,忙碌等等...我觉得这就是一个枚举. 1.普通枚举 1) 实例 复制代码 代码如下: public enum UserState {  QMe,  OnLine,  OffLine     //后面省略 } ps:像上边的枚举,可以单独写在一个CS文件中. 2)普通枚举的性质 1. 互斥性 2. 每一个值都有一个数值

  • asp.net 枚举文件里面的数字绑定到DropDownList里面去

    复制代码 代码如下: public class AppEnum { public enum PointLogType : int { /// <summary> /// Email确认 /// </summary> [Description("Email确认")] Recruit = 1, //新客户激活+ /// <summary> /// 老客户回馈 /// </summary> [Description("老客户回馈&qu

  • .NET获取枚举DescriptionAttribute描述信息性能改进的多种方法

    一. DescriptionAttribute的普通使用方式 1.1 使用示例 DescriptionAttribute特性可以用到很多地方,比较常见的就是枚举,通过获取枚举上定义的描述信息在UI上显示,一个简单的枚举定义: public enum EnumGender { None, [System.ComponentModel.Description("男")] Male, [System.ComponentModel.Description("女")] Fem

  • 详解ASP.NET Core MVC四种枚举绑定方式

    前言 本节我们来讲讲在ASP.NET Core MVC又为我们提供了哪些方便,之前我们探讨过在ASP.NET MVC中下拉框绑定方式,这节我们来再来重点看看枚举绑定的方式,充分实现你所能想到的场景,满满的干货,你值得拥有. 探讨枚举绑定方式 我们首先给出要绑定的枚举类. public enum Language { JavaScript, Java, C, Python, SQL, Oracle } 枚举绑定方式一(@Html.DropDownList) 接下来我们废话少说直接进入主题. 复制代

  • 详解Spring Security 中的四种权限控制方式

    Spring Security 中对于权限控制默认已经提供了很多了,但是,一个优秀的框架必须具备良好的扩展性,恰好,Spring Security 的扩展性就非常棒,我们既可以使用 Spring Security 提供的方式做授权,也可以自定义授权逻辑.一句话,你想怎么玩都可以! 今天松哥来和大家介绍一下 Spring Security 中四种常见的权限控制方式. 表达式控制 URL 路径权限 表达式控制方法权限 使用过滤注解 动态权限 四种方式,我们分别来看.  1.表达式控制 URL 路径权

  • 详解ASP.NET Core MVC 源码学习:Routing 路由

    前言 最近打算抽时间看一下 ASP.NET Core MVC 的源码,特此把自己学习到的内容记录下来,也算是做个笔记吧. 路由作为 MVC 的基本部分,所以在学习 MVC 的其他源码之前还是先学习一下路由系统,ASP.NET Core 的路由系统相对于以前的 Mvc 变化很大,它重新整合了 Web Api 和 MVC. 路由源码地址 :Routing-dev_jb51.rar 路由(Routing)功能介绍 路由是 MVC 的一个重要组成部分,它主要负责将接收到的 Http 请求映射到具体的一个

  • 详解ASP.NET Core中配置监听URLs的五种方式

    默认情况下,ASP. NET Core应用会监听一下2个Url: http://localhost:5000 https://localhost:5001 在本篇博文中,我将展示如何使用五种不同的方式改变应用监听的URLs. 在ASP.NET Core项目启动时,有多种配置监听Url的方式,在我之前的一篇博客中,已经展示了在ASP.NET Core 1.0中如何应用不同的方式配置,在ASP.NET Core 3.x中,大部分方式还是一样的. UseUrls() - 在Program.cs配置程序

  • 详解Asp.Net Core 2.1+的视图缓存(响应缓存)

    响应缓存Razor 页与 ASP.NET 核心 2.0 中不支持. 此功能将支持ASP.NET 核心 2.1 版本. 在老的版本的MVC里面,有一种可以缓存视图的特性(OutputCache),可以保持同一个参数的请求,在N段时间内,直接从mvc的缓存中读取,不去走视图的逻辑. [OutputCache(Duration =20)]//设置过期时间为20秒 public ActionResult ExampleCacheAction() { var time=DateTime.Now.ToStr

  • 详解asp.net core 依赖注入

    前言 好久没有写微博了,因为前段时间由于家庭原因决定从工作了3年多的北京转移到上海去.依赖注入在学习net core的时候也有写过类似的东西,只是实践的较少,结果来到上海新公司系统框架涉及到了这块知识点,所以在了解完自己的项目之后决定做一些相关的总结.接下来就让我们先来了解hewi依赖注入. 什么是依赖注入 依赖注入,全称是"依赖注入到容器", 容器(IOC容器)是一个设计模式,它也是个对象,你把某个类(不管有多少依赖关系)放入这个容器中,可以"解析"出这个类的实例

  • 详解ASP.NET Core端点路由的作用原理

    端点路由(Endpoint Routing)最早出现在ASP.NET Core2.2,在ASP.NET Core3.0提升为一等公民. Endpoint Routing的动机 在端点路由出现之前,我们一般在请求处理管道的末尾,定义MVC中间件解析路由.这种方式意味着在处理管道中,MVC中间件之前的中间件将无法获得路由信息. 路由信息对于某些中间件非常有用,比如CORS.认证中间件(认证过程可能会用到路由信息). 同时端点路由提炼出端点概念,解耦路由匹配逻辑.请求分发. Endpoint Rout

  • 详解ASP.NET Core 反向代理部署知多少

    引言 最近在折腾统一认证中心,看到开源项目IdentityServer4.Admin集成了IdentityServer4和管理面板,就直接拿过来用了.在尝试Nginx部署时遇到了诸如虚拟目录映射,请求头超长.基础路径映射有误等问题,简单记录,以供后人参考. Nginx 配置路由转发 首先来看下IdentityServer4.Admin的项目结构: IdentityServer4.Admin / ├── Id4.Admin.Api # 用于提供访问Id4资源的WebApi项目 ├── Id4.Ad

  • 详解vue 路由跳转四种方式 (带参数)

    1.  router-link 1. 不带参数 <router-link :to="{name:'home'}"> <router-link :to="{path:'/home'}"> //name,path都行, 建议用name // 注意:router-link中链接如果是'/'开始就是从根路由开始,如果开始不带'/',则从当前路由开始. 2.带参数 <router-link :to="{name:'home', para

  • 详解ASP.NET Core Web Api之JWT刷新Token

    前言 如题,本节我们进入JWT最后一节内容,JWT本质上就是从身份认证服务器获取访问令牌,继而对于用户后续可访问受保护资源,但是关键问题是:访问令牌的生命周期到底设置成多久呢?见过一些使用JWT的童鞋会将JWT过期时间设置成很长,有的几个小时,有的一天,有的甚至一个月,这么做当然存在问题,如果被恶意获得访问令牌,那么可在整个生命周期中使用访问令牌,也就是说存在冒充用户身份,此时身份认证服务器当然也就是始终信任该冒牌访问令牌,若要使得冒牌访问令牌无效,唯一的方案则是修改密钥,但是如果我们这么做了,

随机推荐