C# 如何使用具有多个同名值的RouteValue

C# 如何使用具有多个同名值的RouteValue,c#,asp.net-mvc-4,routevalues,C#,Asp.net Mvc 4,Routevalues,在我的ASP.NET MVC 4应用程序中,我可以筛选多个标记。在HTML中,它如下所示: <form> <label> <input type="checkbox" name="tag" value="1">One </label> <label> <input type="checkbox" name="tag" value="2">Two </label> <lab

在我的ASP.NET MVC 4应用程序中,我可以筛选多个标记。在HTML中,它如下所示:

<form>
  <label>
    <input type="checkbox" name="tag" value="1">One
  </label>
  <label>
    <input type="checkbox" name="tag" value="2">Two
  </label>
  <label>
    <input type="checkbox" name="tag" value="3">Three
  </label>
  <input type="submit" name="action" value="Filter">
</form>
但是,调用
Url.Action
会导致序列化集合的typename,而不是实际值

如何做到这一点



MVC的标准基础设施可以处理描述为输入的多个键。难道没有标准的基础设施可以反过来处理吗?我遗漏了什么吗?

您可以通过以下方式完成:

string url = Url.Action("DoFilter", TypeHelper2.ObjectToDictionary(filter) );
TypeHelper2.ObjectToDictionary
是.NET内部方法的修改版本,可以在下面的文档中找到

改变的行为:当一个项目实现了
IEnumerable
时,对于每个项目,一个条目是
在返回的字典中使用as键创建
“Name[index]”
(索引基于0)。这是可能的,因为MVC控制器的活页夹可以处理
tag=1&tag=3
tag[0]=1&tag[1]=3
查询字符串。

一个简单但没有这么优雅的解决方案可以是:

  public ActionResult Index(AdFilter filter)
  {
     string parameters = "?";
     foreach (var item in filter.tag)
        {
            parameters += string.Format("tag={0}&", item);
        }
     //trimming the last "&"
     parameters = parameters.TrimEnd(parameters[parameters.Length - 1]);
     string url = Url.Action("DoFilter") + parameters;

  }

以上两个答案都是非常好的答案。在这方面(重定向到一个动作或生成一个URL重定向到),MVC根本不“喜欢”数组

我可以看到另外两种方法:

1) 使用TempData保存并检索数组(例如在

2) 为AdFilter编写并使用自定义模型活页夹

我自己也会选择后者——可测试且更具确定性(另外,我不知道当您进入服务器场场景时,TempData是如何工作的)

您可能要考虑的另一件事是使用一些类似于索引操作的返回值。

return View("DoFilter", new AdFilter(){tag = tag});
(这将返回Dofilter视图,同时在浏览器中维护“index”标记[0]=1&tag=2”url)

最后—感觉您接受筛选条件只是为了将其发送回浏览器,以便浏览器可以再次请求筛选结果。也许更好的选择是从一开始就将表单上的操作设置为post到“DoFilter”:

<form  method="post" action="DoFilter"> 


HTH

您可以使用接受对象的
Url.Action()
重载来生成路由参数。在内部,它通过使用反射来构建每个属性名称及其
.ToString()
值的字典

对于简单值类型,它可能是
Name=“doekman”
(变成
/DoFilter?Name=doekman
),但是对于复杂对象或集合的属性,它返回类型名(即
.ToString()
值)。没有执行递归,这是有意义的,因为查询字符串有长度限制,因此如果对复杂对象和集合执行递归,很快就会超过限制,并在集合包含大量项时抛出异常(这将创建一个非常难看的查询字符串)


因此,在回答
如何做到这一点时?
除非手动生成
RouteValueDictionary
(或编写自己的帮助程序生成查询字符串)

谢谢您的回答,但这两个答案对我来说似乎都是一种攻击。我的印象是我做错了什么。RouteValueDictionary不能处理“多个”(
,在我的例子中是同名的
)值吗?很难想象微软提出了一个不包含整个HTML表单模型的抽象……在我的例子中,我需要一个查询字符串,因为我使用了一个。(顺便说一句:我实际上对答案投了赞成票,因为这些都是很好的答案。然而,我的问题是关于MVC处理阵列的)。啊-好的-我没有从你的问题中完全理解(谢谢你的赞成票!)。本质上,如果您需要一个可点击的URL(使用寻呼机上的GET-via链接?),那么您试图复制“当表单发布到URL时”(从您的第一个示例开始),使用“仅使用基本URL获取”-这不会飞起来-MVC不会自然地处理这类事情(参见其他答案)。如果是我,我必须支持这一点,那么我肯定会创建一个自定义模型绑定器,并在导入的过程中使用它(因此您有一个PagedAdFilterModel和一个将HTTPGET分解的绑定器)。另一个选择是编写我自己的
Url.Action()
,它也可以处理
IEnumerable
Url.Action()
是否已经开源?我在GitHub上找不到它…是的(这就是我所说的创建自己的助手)。当前UrlHelper的源代码是,您可以全部下载。我不知道控制器会处理相同的查询字符串
?tag=1&tag=3
和?tag[0]=1&tag[1]=3`。内部
Url.Action
对象转换为
RouteValueDictionary
。这不是问题,因为字典的值仍然是
IEnumerable
。但是,这也是一个简单的解决方案,因为在这种转换中,您可以使用字典中的项自己的键在字典中添加项。此解决方案非常透明,只需要从MVC项目复制两个文件(一个文件略有更改)。我应该编辑这个答案吗,因为这个答案引导我找到这个解决方案?这是我做的解决方案。我也喜欢这个答案,但它有点粗糙,可能很难正确。该项需要编码,而且此代码未考虑书签。。但话说回来,它不是那么优雅,但当出现问题时,调试这段代码很容易。
<form  method="post" action="DoFilter">