【问题标题】:How does an asp.net MVC model generate input names?asp.net MVC 模型如何生成输入名称?
【发布时间】:2011-07-19 14:50:53
【问题描述】:

在带有 Razor 标记的 MVC 中的 EditorFor 视图中,如果你这样做:

@Html.TextBox("")

HTML 带有正确的模型输入名称,如下所示:

<input id="usr_Roles" name="usr.Roles" type="text" value="">

“usr.Roles”名称来自此 EditorFor 行:

@Html.EditorFor(modelItem => usr.Roles, "RoleList") 

不幸的是,我正在尝试生成一组名为“usr.Roles”的复选框。由于 MVC 呈现复选框的方式,我不能使用 Html.Checkbox。我可以像这样手动生成它们:

@foreach (string roleName in Roles.GetAllRoles())
{
    string checkboxId = "checkbox_" + roleName;
    <input type="checkbox" name="usr.Roles" id="@checkboxId" value="@roleName" @Html.Raw(Model.Contains(roleName) ? "checked" : "") />
    <label for="@checkboxId">@roleName</label>
} 

上述方法有效,但这只是因为我手动将“usr.Roles”指定为复选框名称。

我的问题是:在对象和属性的迷宫中,@Html.TextBox 对象在哪里找到“usr.Roles”“usr-Roles”字符串?我可以自己找到它并在复选框中使用它吗?

【问题讨论】:

    标签: asp.net-mvc-3 razor


    【解决方案1】:

    我不知道你到底为什么想要手动生成复选框的 ID 和名称,而不是简单地使用 Html.CheckBoxFor 帮助器为你完成所有这些,但如果你有一些原因,这里是如何:

    @{
        var name = ViewData.TemplateInfo.GetFullHtmlFieldName("");
    }
    
    @foreach (string roleName in Roles.GetAllRoles())
    {
        string checkboxId = "checkbox_" + roleName;
        <input type="checkbox" name="@name" id="@checkboxId" value="@roleName" @Html.Raw(Model.Contains(roleName) ? "checked" : "") />
        <label for="@checkboxId">@roleName</label>
    } 
    

    显然,这里显示的内容纯粹是出于某些教育目的。我真的会避免这样的怪物,并简单地使用 Html 助手和编辑器模板。在您看来,令我震惊的另一件事是以下代码行:Roles.GetAllRoles()。就好像您的视图正在查询数据。这是视图应该做的最后一件事。控制器负责查询数据、填充视图模型并将此视图模型传递给视图,以便它简单地显示数据。

    所以让我们尝试详细说明您的示例。据我了解,您正在尝试显示每个角色的复选框列表,以便用户可以选择它们。

    与往常一样,您从表达视图要求的视图模型开始:

    public class MyViewModel
    {
        public IEnumerable<RoleViewModel> Roles { get; set; }
    }
    
    public class RoleViewModel
    {
        public string RoleName { get; set; }
        public bool Selected { get; set; }
    }
    

    然后你编写一个控制器动作来查询你的数据并填充视图模型:

    public ActionResult Index()
    {
        var roles = Roles.GetAllRoles();
        var model = new MyViewModel
        {
            Roles = roles.Select(role => new RoleViewModel
            {
                RoleName = role,
                Selected = ??????
            })
        };
        return View(model);
    }
    

    那么你将有一个Index.cshtml 视图:

    @model MyViewModel
    @Html.EditorFor(x => x.Roles)
    

    以及将为角色集合的每个元素呈现的相应编辑器模板 (~/View/Shared/EditorTemplates/RoleViewModel.cshtml):

    @model RoleViewModel
    @Html.CheckBoxFor(x => x.Selected)
    @Html.LabelFor(x => x.Selected, Model.RoleName)
    

    视图中不再有foreach 循环,不再有带有名称和ID 的丑陋黑客,不再从视图中提取数据。

    【讨论】:

    • 要回答您的原始问题,CheckBoxFor 方法仅在复选框用于生成布尔值时才有效。该代码甚至生成一个隐藏字段以确保始终为复选框返回一个值。我正在尝试返回一个 List,所以这根本行不通。
    • @Dave, List&lt;string&gt;?从复选框?唔。在我展示的示例中,您可以简单地将角色名称添加为编辑器模板中的隐藏字段,在您的后期控制器操作中,您将获得IEnumerable&lt;RoleViewModel&gt;,其中当然将包含角色名称的整个列表以及一个是否被检查。
    • 是的,你所描述的绝对看起来像是做我想要完成的事情的“正确”方式。但你甚至回答了我最初的问题,尽管它有缺陷。谢谢!
    • 如果你很好奇,List 的原因是默认的 RoleManager 将数组作为添加角色的参数,所以我想我不妨从模型中的数组开始。我想我会按照你的方式重做。如果我要使用 MVC,我不妨正确使用它。
    【解决方案2】:

    据我所知,您想从模型中生成属性名称, 我建议你使用方法:

    ExpressionHelper.GetExpressionText
    

    来自 System.Web.Mvc 程序集

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-12-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-09-18
      • 1970-01-01
      相关资源
      最近更新 更多