【问题标题】:MVC RadioButtonFor ConfusionMVC 单选按钮混淆
【发布时间】:2016-08-12 12:02:13
【问题描述】:

我正在观看一个教程视频,https://www.youtube.com/watch?v=04RY04uKq2s,但我只是不明白 RadioButtonFor 发生了什么。

基本上,这家伙创建了一个 Company 类:

public class Company
{

    public string SelectedDepartment {get; set;}


    public List<Department> Departments
    {
        get
        {
            SampleDBContext db = new SampleDBContext();
            return db.Departments.ToList();
        }
    }
}

`

好的,很简单。他这里使用了EntityFramework,它已经生成了SampleDBContext类。

然后他有一个很简单的Index ActionMethod:

[HttpGet]
public ActionResult Index()
{
    Company company = new Company();
    return View();
}

此 [HttpGet] 的强类型视图:

@using (Html.BeginForm())
{
foreach (var department in Model.Departments)
{
    @Html.RadioButtonFor(m => m.SelectedDepartment, department.Id, (department.IsSelected.HasValue && department.IsSelected.Value) ? new (@checked = "checked")} : null
    @department.Name
}

<input type="submit" value="Submit" />[Resulting View][1]

最后是这个 HttpPost ActionMethod:

[HttpPost]
public string Index(Company company)
{
    if(string.IsNullOrEmpty(company.SelectedDepartment)
    {
        return "You selected nothing";
    }
    else
    {
        return "You selected department id: " + company.SelectedDepartment;
    }

好的,哇。数据库有 3 列,Id、Name 和 IsSelected(位类型)。

所以, 1..人力资源..1 2..工资单..NULL 3..IT..NULL

长篇大论?我希望不是。每件作品都非常直截了当。

现在回答我的问题:

(1)RadioButtonFor()如何使用(m=>m.SelectedDepartment)?如题,为什么 [HttpPost] 方法会检查它的字符串是空还是空?

(2)当你在方法中打印出company.SelectedDepartment的值时,你就得到了ID。这项任务在哪里进行?

【问题讨论】:

  • 这段代码大部分都是废话或不好的做法,包括在类中访问数据库,在 GET 方法中初始化一个新对象但不将其返回给视图,以及在RadioButtonFor() 用于方法(它的值 SelectedDepartment 决定选择什么,它应该只是 @Html.RadioButtonFor(m =&gt; m.SelectedDepartment, department.Id))。
  • 第一个参数是你绑定到的属性(SelectedDepartment),第二个参数是value(在这种情况下是department.Id)所以当你选择说第二个单选按钮时例如5 的值,然后在您提交时5 绑定到SelectedDepartment
  • @StephenMuecke 我意识到这不是最佳实践。这些教程实际上只是演示性的。显然,多层方法更好。
  • @StephenMuecke 是的,现在正在清理。

标签: c# asp.net-mvc


【解决方案1】:

你分享的代码没有遵循通用的约定,真的没有多大意义。

以下是解决示例问题的更传统方法:

公司模式

public class Company
{
    public int CompanyId {get; set;}
    public string SelectedDepartment {get; set;}
    public List<Department> DepartmentsList {get; set;}
}

部门模型

public class Department
{
    public int DepartmentId {get; set;}
    public string DepartmentName {get; set;}
}

查看

@model CompanyNamespace.Company

@using(Html.BeginForm())
{
    @Html.HiddenFor(model => model.CompanyId)

    foreach (Department department in Model.DepartmentsList)
    {
        @Html.LabelFor(model => modelItem.department)
        @Html.RadioButtonFor(model => modelItem.SelectedDepartment, department.DepartmentName)
    }

    <input type="submit" value="Submit" />
}

控制器

SampleDBContext db = new SampleDBContext();

[HttpGet]
public ActionResult Index()
{
    Company company = new Company();

    company.SelectedDepartment = null;
    company.DepartmentList = db.Departments.ToList();

    return View("Index", company);
}

[HttpPost]
public ActionResult Index(Company company)
{
    if (!ModelState.IsValid)
    {
        return BadRequest(ModelState);
    }

    db.Companies.Add(company);
    db.SaveChanges();

    return RedirectToAction("Index")
}

数据库示例

+-----------+
| Companies |
+-----------+
+-----------------+--------------------------------+
| CompanyId (Int) | SelectedDepartment (VarChar20) |
+-----------------+--------------------------------+
| 1               | Clothing Department            |
| 2               | Electronics Department         |
| 3               | Furniture Department           |
+-----------------+--------------------------------+

+-------------+
| Departments |
+-------------+
+--------------------+----------------------------+
| DepartmentId (Int) | DepartmentName (VarChar20) |
+--------------------+----------------------------+
| 1                  | Clothing Department        |
| 2                  | Electronics Department     |
| 3                  | Furniture Department       |
| 4                  | Hardware Department        |
+--------------------+----------------------------+

回答您的问题...

"model => modelItem.SelectedDepartment" 是一个 lamda 表达式。表达式表示“此单选按钮将代表模型的 SelectedDepartment 字段”。

由于视图中的所有单选按钮都代表模式中的同一个 SelectedDepartment 字段,因此一次只能选择一个单选按钮。

所选单选按钮的值,在我们的例子中是“department.DepartmentName”,将是发送回模型(和数据库)的值。

请注意,我们控件中的 http post 方法不再返回字符串。为了查看对数据的更改,您必须直接查看数据库。

【讨论】:

    【解决方案2】:

    在您的视图代码中,缺少视图使用的实际模型的定义。你可以通过添加@model CompanyNamespace.Company来做到这一点。

    1. m =&gt; m.SelectedDepartment 是一个选择模型属性的 lambda,您可以在 Post 操作中检查该属性以检索用户选择的单选按钮的 value。如果用户没有选择任何单选按钮,则该值为null(或通常为default(T),在本例中为default(string) = null),因此是 Post 操作中的 if 条件。

    2. RadioButtonFor 的第二个参数指定每个单选按钮的值。由于在您的情况下是 department.Id,因此每个生成的单选按钮的值都是部门的 Id。

    至于代码,正如其他人已经在对您的答案的评论中指出的那样,我真的不建议您使用您发布的方法,并且可能切换到其他一些资源来学习 MVC。 IIRC,asp.net 上也有同样易于理解的教程。

    编辑: 当您提交表单时,请求被路由到以[HttpPost] 装饰的操作,并且模型绑定器通过尝试将复杂对象的参数名称或属性与 Post 数据匹配,将发布的数据绑定到您的方法的参数(或多个参数) .因此,当用户选择某个单选按钮时,它的值(取自 RadioButtonFor 调用指定的department.Id)被分配给company.SelectedDepartment 属性。

    扩展模型绑定的编辑受到@Jaquez answer 的启发,试图提供更完整的描述,当我后来比较两者时(在这被 OP 选为答案之后),它在我看来,它最终 - 在很大程度上 - 作为@Jaquez答案的那部分的重述。我认为提及这一点是公平的。

    【讨论】:

    • 是的,有一些东西没有点击我。我只是忽略了 POST 方法正在捕获 m => m.SelectedDepartment。该属性不在 Department 的类中,这使事情变得不太清楚。
    • 我还建议您在浏览器中查看实际生成的 HTML,并可能稍微玩一下视图代码,看看它是如何变化的 - 这样您可以获得一个很好的主意RadioButtonFor(和其他 HtmlHelper 方法)究竟做了什么。
    • 我确实检查了 HTML,但在这种情况下它并没有太大帮助,因为每个名称/值都设置了相同的字符串。这些@Html..For Helpers 乍一看非常令人困惑。 lambda 表达式似乎并没有让事情变得更容易。我不得不深入挖掘以了解匿名方法、委托、隐式数据类型等的要点。难道他们不能简化这种语法吗?
    • 我其实很喜欢 HtmlHelper 方法的语法。尽管我完全理解,如果您之前在 C# 中没有过多地使用 lambda,那么一开始它可能看起来很混乱。在 ASP.NET Core MVC(又名 MVC 6)中,forms 的语法发生了很大变化,生成的视图标记更接近实际生成的 HTML,我认为您可能会更喜欢它。如果您刚开始使用 MVC,那么为什么不从当前最新版本开始呢? ASP.NET Core MVC 处于稳定发布版本。
    • 很好的答案。我忽略了我的一些细节,这更加彻底。
    【解决方案3】:

    需要检查 null 或空字符串,因为单选按钮的值仅在选择按钮时才包含在 POST 中。复选框也是如此,并且是 Web 标准本身的一部分,而不是 MVC。

    company.SelectDepartment 的值是在 MVC 框架获取提交的值并使用它来实例化 (POST) Index 方法参数类型的新实例时分配的。这是通过将提交数据中的属性名称与参数类型的属性名称匹配来完成的。通过使用带有类型模型的 RadioButtonFor 辅助方法,您可以保证单选按钮的名称和提交的值的名称与 Index 方法所需的类型相匹配。

    【讨论】:

    • 谢谢。我不知道为什么这让我大吃一惊。这种 View 语法的一点点确实是丑陋的代码。一个视图中基本上有 3 种“语言”?我不知道我是否喜欢它。
    • 确实,这可能有点令人困惑。正如上面提到的@davke,使用 ASP.NET Core MVC 确实会变得更好。
    猜你喜欢
    • 1970-01-01
    • 2012-08-01
    • 1970-01-01
    • 1970-01-01
    • 2012-06-04
    • 2018-05-16
    • 2016-05-15
    • 2012-07-24
    • 2010-12-28
    相关资源
    最近更新 更多