Asp.net mvc 用一个ASP.NETMVC下拉菜单编辑两个值的好方法是什么?
记录由其Asp.net mvc 用一个ASP.NETMVC下拉菜单编辑两个值的好方法是什么?,asp.net-mvc,asp.net-mvc-3,model-binding,hidden-field,html.dropdownlistfor,Asp.net Mvc,Asp.net Mvc 3,Model Binding,Hidden Field,Html.dropdownlistfor,记录由其种类和记录ID唯一标识 我有一组要显示为下拉列表的记录,提交时我希望获得SelectedKind和SelectedRecordId,以便进一步处理 问题是,我希望单独处理这些值,但应该只有一个下拉列表 这样做的最佳实践是什么 我的建议是: 选择1 用字符串填充下拉列表,如“Kind\u RecordId”,并设置一个JavaScript更改处理程序,该处理程序将解析字符串并设置隐藏字段值。 然而,我不太喜欢在不同的地方有字符串操作逻辑的想法(在填充下拉列表时在控制器中,在解析值时在视图中
种类
和记录ID
唯一标识
我有一组要显示为下拉列表的记录,提交时我希望获得SelectedKind
和SelectedRecordId
,以便进一步处理
问题是,我希望单独处理这些值,但应该只有一个下拉列表这样做的最佳实践是什么 我的建议是: 选择1 用字符串填充下拉列表,如
“Kind\u RecordId”
,并设置一个JavaScript更改处理程序,该处理程序将解析字符串并设置隐藏字段值。
然而,我不太喜欢在不同的地方有字符串操作逻辑的想法(在填充下拉列表时在控制器中,在解析值时在视图中)。我是否应该将SelectItem
填充逻辑也移动到视图中,并将业务对象保留在视图模型中
它还让我感到不安的是,在禁用JavaScript的罕见情况下,用户根本无法使用表单
选择2
在我的表单模型中公开一个唯一的“Kind\u RecordId”
类字符串属性,并让模型通过控制器的强类型访问器属性对其进行解析(或填充)?
这似乎是一个更好的方法,但我不完全确定。我认为好的是它将保持视图模型中所有的解析/级联逻辑,并且当JavaScript不可用时它不会失败。
社区思想非常受欢迎。一个优雅的方法是创建自己的类,并创建一个单独的类,将
类
和记录ID
作为属性。您需要使用属性为类指定模型绑定器,然后才能将该类用作操作方法参数
[ModelBinder (typeof (RecordIdentityBinder))]
public class RecordIdentity
{
// Your types may be different
public RecordKind Kind { get; set; }
public int RecordId { get; set; }
//TODO: replace this with your formatting algorithm
public override string ToString ()
{
return string.Format ("{0}_{1}", Kind, RecordId);
}
//TODO: replace this with your parsing algorithm
public static RecordIdentity Parse (string s)
{
string[] fragments = s.Split('_');
if (fragments.Length != 2)
return null;
// Your object creation may be different
return new MessagePartyIdentity {
Kind = (RecordKind) Enum.Parse (typeof (RecordKind), fragments [0]),
PartyID = int.Parse (fragments [1])
};
}
}
public class RecordIdentityBinder : IModelBinder
{
public object BindModel (ControllerContext controllerContext, ModelBindingContext bindingContext)
{
string key = bindingContext.ModelName;
ValueProviderResult value = bindingContext.ValueProvider.GetValue (key);
if (value == null || string.IsNullOrEmpty (value.AttemptedValue))
return null;
return RecordIdentity.Parse (value.AttemptedValue);
}
}
public class MyController : Controller
{
// ?identity=Foo_42 will become RecordIdentity { Kind = RecordKind.Foo, RecordId = 42 }
public ActionResult DoSomethingWith (RecordIdentity selectedIdentity)
{
// ...
}
}
在视图模板代码中,需要使用复合属性调用Html.DropDownListFor()
:
@Html.DropDownListFor(m => m.SelectedIdentity, Model.RowList)
对于行列表
中的每个值或您称之为数据源的任何值,确保SelectListItem
的值
属性设置为您的类“ToString()
输出。
在Html.DropDownListFor
中指定的对象的RecordIdentity
类型属性的名称应与操作参数名称匹配。否则,您需要在的Prefix
属性中指定下拉名称,如下所示:
另请注意,如果希望RecordIdentity
成为表单模型的属性,或者希望接受作为动作方法参数的任何类,则该方法也会起作用。绑定器将以任何方式调用
通过采用这种方法,您可以使单个类负责格式化和解析,这在很大程度上是不可见的,并且提供了对实际字段的抽象。然而,我需要注意的是,这样的问题也可能是由糟糕的数据库或业务实体组织造成的。也许更好的解决方案是为列出的每个项提供其唯一的本机密钥。我认为最好定义一个具有2个属性的新类。类似于:
public class KindRecordItem {
public int Id {get; set;}
public string Kind {get; set;}
public int RecordId {get; set;}
public string Text {get; set;}
}
将所有有效/合法的种类和recordId组合生成一个集合,将该集合传递给视图,并在下拉列表中显示显示文本
<%= Html.DropDownListFor(m => m.SelectedKindRecordItem,
new SelectList(Model.KindRecordItems, "Id", "Text"),
new SelectListItem { Value = "0", Text = "Please select an option" }) %>
m.SelectedKindRecordItem,
新建SelectList(Model.KindRecordItems、“Id”、“文本”),
新建SelectListItem{Value=“0”,Text=“请选择一个选项”})%>
在控制器中,SelectedKindRecordItem将是一个唯一的ID,您可以查找该ID以查找要处理的种类和记录ID
Id可以生成为Kind和RecordId的散列或任何其他方法以使其唯一。那么用户将从Kind和RecordId的任意组合中进行选择吗?也就是说,如果有3种类型和4个记录ID,他们可以从12个下拉项中选择?不,根本不会有两个不同的列表。你可以把它看作一个复合键,这就是我的意思。1个下拉列表,包含12项。它是每种类型和记录ID的组合在一个下拉列表中。正确吗?不。更接近真实世界:用户可以向其他用户或商店发送消息。因此,实体ID将有一个属性,实体种类将有一个属性。这并不过分,因为还有其他类型的实体可以接收消息,而且它们都有自己的表。用户可以为
To
字段选择任何目标用户/商店/任何东西,但是让用户手动选择种类和ID没有任何意义。我的意思是可以有6个选项,例如4个用户和2个商店。或5个商店和一个用户。或者他们都可以是用户。。这取决于数据库中的数据。这从来不是“每种组合”类型的事情。谢谢你的输入。这看起来是一个很酷的方法,所以我会尝试一下,让你知道。至于实体组织,这些实体实际上来自不同的表,它们只有在非常特定的情况下才有意义。这就是为什么我决定用这样的“复合键”来描述它们。我不确定BindModel方法的代码是否正确工作,但如果您执行所有其他建议操作来激活此绑定器,您可以在创建的基础结构上调试它,并告诉我,如果有什么不正确的地方。这是一个完美的解决方案,非常感谢。我刚刚用100%工作代码和一个小的添加更新了你的答案。你能检查一下Bind
属性部分的正确性吗?我试图提供一个真实的示例,但我不是100%正确。@gaearon,好的,我今天将检查它是否完全可靠,但模型绑定机制仅基于通过POST传递的表单集合的名称和值。如果您使用props和另一个参数名绑定简单类,它将成功填充,因为
<%= Html.DropDownListFor(m => m.SelectedKindRecordItem,
new SelectList(Model.KindRecordItems, "Id", "Text"),
new SelectListItem { Value = "0", Text = "Please select an option" }) %>