在 MVC 5.1 中处理枚举






4.86/5 (36投票s)
了解如何在 Asp.Net MVC 5.1 中处理枚举下拉列表
引言
如果您正在阅读这篇文章,我敢打赌您至少有一次去 #stackoverflow 寻找解决您遇到的难题的方法。前几天,我在 #stackoverflow 上浏览时,注意到不少开发人员在处理 Asp.Net MVC 中的枚举时经常遇到困难,他们的代码量不足以将枚举转换为下拉列表。这个问题已经存在很多年了。显然,聪明的开发人员并没有袖手旁观。他们找到了处理这个问题的不同方法,而这些方法通常并不容易遵循。
随着 MVC 5.1 于 2014 年 2 月 27 日发布,终于有了视图中的枚举支持。老式的做法仍然适用且可用,并且可以在网上找到大量的相关资源,但不推荐,因为新方法更简单。我不会讨论旧的方法,而是专注于实现我们目标的新方法。
软件要求
您将需要以下任何一项:
- Visual Studio 2012:下载适用于 Visual Studio 2012 的 ASP.NET 和 Web 工具 2013.1。
- Visual Studio 2013:下载 Visual Studio 2013 更新 1。需要此更新才能编辑 ASP.NET MVC 5.1 Razor 视图。
现在,您已经拥有了这些工具,让我们开始创建一个 Asp.Net Web 应用程序。为了演示枚举支持,我们将构建一个简单的学生注册表单,其中我们期望一个下拉框显示性别、国家等信息供人们选择。最初,为了演示目的,我已经创建了以下架构。您可以从这里下载整个源代码文件。

Gender 枚举非常简单,它包含 Male 和 Female,定义如下:
public enum Gender
{
Male,
Female
}
枚举列表中添加了 5 个国家。Country 枚举定义如下:
public enum Country
{
Australia,
Bangladesh,
England,
France,
Usa
}
学生实体 [POCO(普通 C# 对象)类] 看起来是这样的:
public class Student
{
public int Id { get; set; }
public String Name { get; set; }
public Gender Gender { get; set; }
public Country Country { get; set; }
}
目前,如果我们仅依靠脚手架来完成繁重的工作并生成一些视图,那么您最终会得到这样的结果:

如果您以前从未处理过枚举,这个视图可能会让您感到恐慌,您可能会说:
“嘿,等等,脚手架不起作用!它没有正确渲染视图”
现在您可能想检查脚手架为视图生成的代码,这里是:
<div class="form-group">
@Html.LabelFor(model => model.Gender, new { @class = "control-label col-md-2" })
<div class="col-md-10">
@Html.EditorFor(model => model.Gender)
@Html.ValidationMessageFor(model => model.Gender)
</div>
<div class="form-group">
@Html.LabelFor(model => model.Country, new { @class = "control-label col-md-2" })
<div class="col-md-10">
@Html.EditorFor(model => model.Country)
@Html.ValidationMessageFor(model => model.Country)
</div>
</div>
一切看起来都很正常,对吧?您在正确的位置使用了 EditorFor() 编辑器扩展,并且数据也正确传递了。那么问题出在哪里呢?好吧,实际上 EditorFor() 不知道如何渲染枚举,所以它使用默认设置并为枚举渲染一个文本框。
不要恐慌!我们很快就会处理这个问题。但首先,请通过 NuGet 更新Microsoft ASP.NET MVC。否则您将找不到我们将用于解决问题的扩展方法。
@*@Html.EditorFor(model => model.Gender)*@
@Html.EnumDropDownListFor(model=>model.Gender)
在这里,我们使用了新的 EnumDropDownListFor() 扩展方法。实现与 EditorFor() 扩展相同。万岁!一行代码就解决了问题。

现在,让我们稍微扩展一下场景。如果我们想在 enumdropdowlist 中显示特殊字符/符号空格怎么办?我们知道枚举不支持空格/特殊字符,所以我们可以使用Display Attribute。在以下场景中,我们使用 [Display(Name="United States")] 来显示“United States”,而不是显示“Usa”。
public enum Country
{
Australia,
Bangladesh,
England,
France,
[Display(Name="United States")]
Usa
}
这是视图。您可以看到 EnumDropDownList 中显示“United States”。
注意:此时,如果您创建一个新学生并从 EnumDropDownList 中选择值,当您重新访问以查看您刚刚保存的内容时,您会发现列表中显示的不是“United States”,而是“Usa”。如果您还不明白我的意思,请看下图。

而这正是我们可能不想显示的内容。为了解决这个问题,我们可以使用某种模板机制。
我们将提供枚举模板,重要的是将其放在正确的文件夹中,因为我们希望所有枚举默认都使用此模板。这是我们将为显示场景创建部分视图的位置/Shared/DisplayTemplates ,请确保将其命名为enum.cshtml。文件层次结构如下图所示:

在 Enum.cshtml 中复制以下代码,您就完成了!
@model Enum
@if (EnumHelper.IsValidForEnumHelper(ViewData.ModelMetadata))
{
// Display Enum using same names (from [Display] attributes) as in editors
string displayName = null;
foreach (SelectListItem item in EnumHelper.GetSelectList(ViewData.ModelMetadata, (Enum)Model))
{
if (item.Selected)
{
displayName = item.Text ?? item.Value;
}
}
// Handle the unexpected case that nothing is selected
if (String.IsNullOrEmpty(displayName))
{
if (Model == null)
{
displayName = String.Empty;
}
else
{
displayName = Model.ToString();
}
}
@Html.DisplayTextFor(model => displayName)
}
else
{
// This Enum type is not supported. Fall back to the text.
@Html.DisplayTextFor(model => model)
}
再次运行应用程序,您将在屏幕上找到您久违的解决方案:)
如果您还记得,我们对脚手架生成的代码做了一些更改。如果您正在处理一个大型应用程序,其中几乎每个视图都处理枚举值,那么在多个地方进行更改可能会很困难且耗时。在这种情况下,我倾向于编写 EditorTemplates,以便脚手架生成的代码能够顺利运行,而无需进行任何修改。
这是我们将为显示场景创建部分视图的位置/Shared/EditorTemplates,请确保将其命名为enum.cshtml。文件层次结构如下图所示:
在 Enum.cshtml 中复制以下代码,您就可以使用脚手架生成的代码了。
@model Enum
@if (EnumHelper.IsValidForEnumHelper(ViewData.ModelMetadata))
{
@Html.EnumDropDownListFor(model => model, htmlAttributes: new { @class = "form-control" })
}
else
{
@Html.TextBoxFor(model => model, htmlAttributes: new { @class = "form-control" })
}
这就是您在 MVC5 中处理枚举所需了解的一切。希望这篇文章对您有所帮助 :) 。
附加资源