作者:狠心狼fd | 来源:互联网 | 2023-09-03 12:14
这不是关于如何正确地将一系列复选框绑定到模型属性的问题(一个常见问题)-我的网站可以完美地从请求(POST或GET查询字符串)中读取复选框值.这是关于如何使用Html.Action
这不是关于如何正确地将一系列复选框绑定到模型属性的问题(一个常见问题)-我的网站可以完美地从请求(POST或GET查询字符串)中读取复选框值.
这是关于如何使用Html.ActionLink生成一个链接,该链接可正确格式化查询字符串中的多个复选框值.
所以我有以下模型:
public class ModelType { public string[] V { get; set; } }
我将三个复选框绑定到视图中的该模型,因为我有三个可能的值(是的,这些值的组合).
这是最终的HTML
如果在将表单作为GET提交到服务器时检查所有三个值,则生成的查询字符串当然为?V = 1& V = 2& V = 3.
模型绑定的工作很漂亮,并且一切都很顺利.
但是,假设我想产生一个指向相同动作的链接,传递一个匿名类型或RouteValueDictionary来产生相同的查询字符串.逻辑表明您将执行以下操作:
版本1:将ModelType实例作为视图上的模型:
<%= Html.ActionLink("Test link", null /* action name */, new { V = Model.V }) %>
版本2:直接将’V’成员初始化为数组:
<%= Html.ActionLink("Test link", null /* action name */, new { V = new string[] { "1", "2", "3" } }) %>
[在这个问题上,我说的是RouteValueDictionary,因为在两种情况下,这两种匿名类型在链接生成发生之前都变成了匿名类型.]
在这两种情况下,生成的查询字符串如下:?V = System.String [].
现在,我知道这是因为链接生成器只是在数组上调用ToString().但是似乎无法传递MVC一个会导致其生成?V = 1& V = 2& V = 3的值.
由于两种语言都不允许我们这样做:
new { V="1", V="2", ... }
RouteValueDictionary也无法让我们执行以下操作:
d["V"] = "1"; d["V"] = "2"; ...
我还尝试了对RouteValueDictionary进行预处理的绝望措施,以便为每个IEnumerable生成一个字符串,每个值均用逗号分隔,然后将该字符串写回-这样查询字符串就结束了像这样:?V = 1,2,3.
但是,当然,MVC不会自动将这样的字符串绑定到数组(您只需在数组中得到一个字符串,其中包含逗号即可);因此,将以这种方式绑定的每个属性都必须进行自定义绑定-对我而言,这似乎有点麻烦了.
所以看来我被卡住了.
我想念什么吗?我需要编写要执行的特殊版本的ActionLink吗?
一如既往的任何帮助,我们将不胜感激.
解决方法:
所以我已经去研究了,这是我的观点.我希望有人能提出一个更乐观的答案,但我认为不可以.
完全遵循Html.ActionLink扩展方法,它产生的核心URL是由(咳嗽)密封和(咳嗽!)内部类System.Web.Mvc.ParsedRoute生成的,并且该方法绑定在System.Web中路由组装.
在此方法的最后(这是一个Reflector列表)-这是它生成查询字符串的方式:
if (unusedNewValues.Count > 0) { bool flag5 = true; foreach (string str2 in unusedNewValues) { object obj5; if (acceptedValues.TryGetValue(str2, out obj5)) { builder.Append(flag5 ? '?' : '&'); flag5 = false; builder.Append(Uri.EscapeDataString(str2)); builder.Append('='); builder.Append(Uri.EscapeDataString( Convert.ToString(obj5, CultureInfo.InvariantCulture))); } } }
我首先要提到的是,unusedNewValues是一个HashSet.不幸的是,这意味着它只会呈现一个名称/值配对.
您不能用嵌入的a = b& a = c(…)字符串来伪造数据字符串,因为字符串值已转义-因此,除非替换路由框架,否则根本无法在Mvc中生成此类查询字符串.
结果,一种替代方法是编写一个收集数据类型,该数据类型将执行以下操作(这是一个肮脏的实现):
public class StringCollection : List { public override string ToString() { //use the pipe character as a delimiter - but this doesn't work //if the strings being carried around ccould naturally contain '|'! return string.Join("|", this.ToArray()); } }
然后为首先使用默认方法的类型实现一个自定义模型绑定程序(派生自DefaultModelBinder),然后检查所得集合是否仅包含一个带有’|’的字符串.里面的字符.如果是这样,它将对集合进行后处理,将其内容替换为来自单个字符串的扩展值.
这很可怕-但我目前能想到的所有解决方案中最讨厌的就是.
刚才必须对我所有现有的模型类型进行大量更改,这些模型类型使用可能绑定到查询字符串值的字符串集合…