如何在ASP.NET MVC 3中处理每个键的多个值?

我有以下问题:我在最重要的function中工作的系统之一是搜索页面。 在这个页面中,我有一些选项,如每页记录,开始日期,结束日期和有问题的一个:类型。 必须有可能选择多种类型(大多数时候,所有这些都将被选中)。 为了完成这项工作,我创建了以下内容:

@Html.ListBox("events", Model.Events, new { style = "width: 100%" })

它创建了一个列表框,我可以在其中选择多个选项,当表单被提交时,我的查询字符串将如下所示:

/ 10?周期= 9&事件= 1&事件= 3&recordsPerPage = 10

在那里可以看到创建了两个事件(这是我以前说过的类型)。 此页面的操作方法将List作为其参数之一,表示两个events值。 当我想在MVC Contrib中使用它时,问题就开始了。 他们的寻呼机工作得很好,但正如我所要求的那样,我创建了另一个寻呼机,它显示了用户所在之前和之后五个页面的链接。 为此,在我的代码的一部分中,我必须执行以下操作(这与MVC Contrib寻呼机非常相似,有效):

 public RouteValueDictionary GetRoute(int page) { var routeValues = new RouteValueDictionary(); foreach (var key in Context.Request.QueryString.AllKeys.Where(key => key != null)) { routeValues[key] = Context.Request.QueryString[key]; } routeValues["page"] = page; return routeValues; } 

然后:

 @Html.ActionLink(page.ToString(), action, controller, GetRoute(page), null) 

问题是它是一个Dictionary,它第二次设置routeValues["events"]擦除前一个。

你们对如何使用它有什么想法吗?

非常好的问题。 不幸的是,使用Html.ActionLink助手生成具有多个具有相同名称的查询字符串参数的URL并不容易。 所以我可以看到两种可能的解决方案

  1. long[]编写一个自定义模型绑定器,它能够解析逗号分隔值。 这样您就可以保留GetRoute方法,该方法将生成以下url: period=9&events=1%2C3&recordsPerPage=10&page=5

     public class CommaSeparatedLongArrayModelBinder : DefaultModelBinder { public override object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext) { var values = bindingContext.ValueProvider.GetValue(bindingContext.ModelName); if (values != null && !string.IsNullOrEmpty(values.AttemptedValue)) { // TODO: A minimum of error handling would be nice here return values.AttemptedValue.Split(',').Select(x => long.Parse(x)).ToArray(); } return base.BindModel(controllerContext, bindingContext); } } 

    您将在Application_Start注册:

     ModelBinders.Binders.Add(typeof(long[]), new CommaSeparatedLongArrayModelBinder()); 

    然后以下控制器操作将能够理解以前的URL:

     public ActionResult Foo(long[] events, int page, int period, int recordsPerPage) { ... } 
  2. 手动生成此锚点:

     abc 

尝试查看WinTellect的PowerCollections ,允许您创建MultiDictionary,仍然不能有重复的键,但每个键可以有多个值。

您应该编写以routeValue集合为目标的扩展方法,或者始终编写将Event参数转换为列表的自定义模型绑定器。 如果您将“事件”始终视为列表,则只需通常长度为1的列表即可缓解您遇到的大多数问题。

此时,您将只与列表界面进行交互。 然后,您可以编写自定义绑定器以允许您直接将其放入路径中,或者您可以将列表解压缩回查询字符串。 有一个基于这个名为Unbinder的软件项目,用于将对象解包为属性/值对,您可以在查询字符串或其他目的中轻松使用它们。