2010-12-15 58 views
3

这不是一个关于如何将一系列复选框正确绑定到模型的问题属性(一个常见问题) - 我的网站完美地读取请求中的复选框值,POST或GET +查询字符串。在ASP.NET MVC中,如何使用Html.ActionLink生成重复名称('?v = 1&v = 2&v = 3')查询字符串

这是关于如何使用Html.ActionLink生成一个链接,该链接在查询字符串中正确地设置了多个复选框值。

所以我有以下型号:

public class ModelType 
{ 
    public string[] V { get; set; } 
} 

我绑定,也就是说,3个复选框中的观点,即模型我有三个可能的值(和,是的,说的组合值)。

这里是最终的HTML

<INPUT id="chk1" value="1" type="checkbox" name="V"> 
<INPUT id="chk2" value="2" type="checkbox" name="V"> 
<INPUT id="chk3" value="3" type="checkbox" name="V"> 

如果在表单提交到服务器进行检查所有三个值的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%5B%5D

现在,据我所知,这是因为链接生成器只是在数组上调用ToString();但似乎没有办法通过MVC的值,这将导致它产生?V=1&V=2&V=3

因为无论是语言让我们做的事:

new { V="1", V="2", ... } 

也RouteValueDictionary让我们做的事:

d["V"] = "1"; d["V"] = "2"; ... 

我也试过的苦肉计预加工RouteValueDictionary,这样对于每个IEnumerable<string>,我产生一个单一的字符串,每个值用逗号分隔,然后写回该字符串 - 这样查询字符串就像这样结束:?V=1%2C2%2C3

但是,当然,MVC不会自动将这样的字符串绑定到数组(您只需在数组中使用逗号就可以获得一个字符串)。所以每一个以这种方式绑定的属性都必须是自定义绑定的 - 对我来说,对于我来说,这似乎只是一些太多的箍环而已。

所以看来我被卡住了。

我错过了什么吗?我是否需要编写特定版本的ActionLink来完成我想要的功能?

任何帮助,一如既往,非常感谢。

回答

3

所以我走了,研究了这个,这是我的看法。我希望有人能够提出一个更乐观的答案,但不知何故,我认为不是。

Html.ActionLink扩展方法一路走过,它产生由(咳嗽)产生密封和(咳咳!)内部System.Web.Mvc.ParsedRoute和它的方法BindSystem.Web.Routing核心网址部件。

在这个方法(这是一个反射器上市)的尽头 - 这是怎么产生的查询字符串:

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))); 
     } 
    } 
} 

我应该指出:第一,unusedNewValuesHashSet<string>,这意味着 - 遗憾的是 - 这它只会呈现一个名称/值配对。

由于字符串值已被转义,因此您无法使用嵌入的a=b&a=c(...)字符串来填充数据字符串 - 因此,除非您替换路由框架,否则无法在Mvc中生成此类查询字符串。

结果,另一种会写这确实有点像集合数据类型以下(这是一个肮脏的实现):

public class StringCollection : List<string> 
{ 
    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派生)为首先使用默认方法的类型,然后检查结果集合是否只有一个字符串具有'|'字符在里面。如果是这样,它会对集合进行后处理,将其内容替换为单个字符串中的扩展值。

这是可怕的 - 但我现在可以想到的所有解决方案中最不讨厌的。

刚才不得不做出改变的负载使用,可能被绑定到查询字符串值的字符串的集合现有的所有模型类型...

1

最近也有类似的问题。我最终放弃了HtmlHelper/RouteValueDictionary,并从头构建了我的URL。喜欢的东西:

<a href="/Controller/Action?<%: string.Join("&", set.Select(i => "v=" + i))%>">Link</a> 

可能无法吸引大家的口味,但它为我工作。