我有以下问题:我正在使用的系统最重要的功能之一是搜索页面。在此页面中,我有一些选项,例如每页记录、开始日期、结束日期和有问题的选项:类型。一个人必须有可能选择多种类型(大多数时候,所有类型都会被选择)。为了实现这一目标,我创建了以下内容:
<div>
<label>Eventos:</label>
<div>
@Html.ListBox("events", Model.Events, new { style = "width: 100%" })
</div>
</div>
它创建一个列表框,我可以在其中选择多个选项,提交表单时,我的查询字符串将如下所示:
/5?period=9&events=1&events=3&recordsPerPage=10
可以看到创建了两个事件(这是我之前讨论的类型)。此页面的操作方法采用 List
作为其参数之一,它表示两个事件
值。当我想将其与 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)
问题是它是一个字典,这使得我第二次设置routeValues["events"]
的值删除之前的值。
你们知道如何使用它吗?
I have the following problem: one of the system I'm working in most important features is a search page. In this page I have some options, like records per page, starting date, ending date, and the problematic one: type. One must have the possibility to choose more than one type (most of the time, all of them will be selected). To make that work, i created the following:
<div>
<label>Eventos:</label>
<div>
@Html.ListBox("events", Model.Events, new { style = "width: 100%" })
</div>
</div>
It creates a listbox where I can choose more than one option, and when the form is submited, my query string will look like this:
/5?period=9&events=1&events=3&recordsPerPage=10
There it is possible to see that two events (which is the type I was talking before) are created. The action method to this page takes a List<long>
as one of its arguments, which represents that two events
values. The problem begins when I want to use that with MVC Contrib. Their pager works just fine, but as I was requested, I created another pager, which displays links to five pages after and before the one the user is at. To do this, in a part of my code I have to do the following (which is very similar to the MVC Contrib pager, that works):
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;
}
And then:
@Html.ActionLink(page.ToString(), action, controller, GetRoute(page), null)
The problem is that it is a Dictionary, which makes the second time I set the value for routeValues["events"]
erase the previous.
Do you guys have any idea on how to work with it?
发布评论
评论(3)
非常好的问题。不幸的是,使用
Html.ActionLink
帮助器生成具有多个同名查询字符串参数的 url 并不容易。因此,我可以看到两种可能的解决方案:为
long[]
编写一个自定义模型绑定器,它能够解析逗号分隔的值。这样您就可以保留GetRoute
方法,该方法将生成以下网址:period=9&events=1%2C3&recordsPerPage=10&page=5
。您将在
Application_Start
中注册:然后以下控制器操作将能够理解前面的 URL:
手动生成此锚点:
Very good question. Unfortunately it is not easy to generate an url which has multiple query string parameters with the same name using the
Html.ActionLink
helper. So I can see two possible solutions:Write a custom model binder for
long[]
that is capable of parsing a comma separated values. This way you can keep yourGetRoute
method which will generate the following url:period=9&events=1%2C3&recordsPerPage=10&page=5
.which you will register in
Application_Start
:and then the following controller action will be able to understand the previous URL:
Manually generate this anchor:
尝试查看 WinTellect 的 PowerCollections,允许您创建 MultiDictionary,仍然不能有重复的键,但是您可以每个键有多个值。
Try looking at WinTellect's PowerCollections, allows you to create a MultiDictionary, still can't have duplicate keys, but you can have multiple values per key.
您应该编写以routeValue 集合为目标的扩展方法,或者始终将您的Event 参数转换为列表的自定义模型绑定器。如果您始终将事件视为一个列表,那么只需一个通常长度为 1 的列表就可以缓解您面临的大多数问题。
此时您将仅与列表界面进行交互。然后,您可以编写一个自定义绑定器,以允许您直接将其正确放入路由中,或者您可以将列表解压回查询字符串中。有一个基于此的软件项目,称为 Unbinder,用于将对象解压缩为属性/值对,您可以在查询中轻松使用字符串或其他目的。
You should write either extension methods that target the routeValue collection or a custom model binder that transforms your Event parameter into a list always. If you view Event always being a list, just a commonly length 1 list will alleviate most of the problems you face.
At this point you will just interact with a list interface. You could then write a custom binder to allow you to directly place that into the route correctly or you could unpack the list back into the query string. There's a software project based on this called Unbinder for unpacking objects into property/value pairs that you can easily use in query strings or other purposes.