MVC3 Html.BeginForm - 作为RouteValueDictionary传递参数失败

8
我有一个多步设置过程,希望只在URL后附加查询字符串参数时传递相关参数。 http://localhost:6618/Account/Profile?wizard=true&cats=dogs @using( Html.BeginForm() )很好用。它产生了这样的结果:<form action="/Account/Profile?setup=true&amp;cats=dogs" method="post">也就是说,它将原始查询字符串参数传递到POST操作中,然后在Controller操作中,我可以选择哪些参数是相关的,通过添加到RouteValues和RedirectToResult来传递下一步,或者必要地添加。
但是,出于样式目的,我需要为我的表单分配一个类。
我尝试了: @using( Html.BeginForm( "Profile", "Account", args, FormMethod.Post, new { @class = "mainForm" } ) ) 它产生了以下结果:

<form action="/Account/Profile?Count=1&amp;Keys=System.Collections.Generic.Dictionary%602%2BKeyCollection%5BSystem.String%2CSystem.Object%5D&amp;Values=System.Collections.Generic.Dictionary%602%2BValueCollection%5BSystem.String%2CSystem.Object%5D" class="mainForm" method="post">

args由过滤器生成,是一个RouteValueDictionary)。规范http://msdn.microsoft.com/en-us/library/dd505151.aspx指出,您可以使用System.Web.Routing.RouteValueDictionary传递参数。

我想要的是:<form action="/Account/Profile?setup=true&amp;cats=dogs" class="mainForm" method="post">

我应该提到,我不希望像传递new {key = value}那样做,因为有相当多的逻辑来确定我将传递给下一步的内容。

这里有什么建议吗?

我被这个看似简单的任务难住了,肯定错过了什么非常明显的东西。


也许这篇其他帖子中的答案可以有所帮助?https://dev59.com/QEjSa4cB1Zd3GeqPHraB - summea
4个回答

12

args是由一个过滤器生成的,并且是一个RouteValueDictionary

这是关键点。在这种情况下,请确保您使用了BeginForm方法的正确重载版本

@using(Html.BeginForm(
    "Profile", 
    "Account",   
    args, 
    FormMethod.Post, 
    new RouteValueDictionary(new { @class = "mainForm" })
))
{
    ...
}

注意最后一个参数吗?它必须是 IDictionary<string, object> 才能起作用。

在您的示例中,被选中的是此重载。但由于您为 routeValues 参数传递了一个 RouteValueDictionary 而不是匿名对象,因此它变得混乱了。

因此,您应该将 routeValues 和 htmlAttributes 都作为字典或者都作为匿名对象。


@Darin Dimitrov,您能否检查一下我的问题,有些相似之处:https://dev59.com/tmfWa4cB1Zd3GeqPj7xf - Saeid
你的解决方案适用于我的情况,但我不明白为什么在类变量之前要使用@符号。有人能解释一下这里发生了什么吗?谢谢。 - northben
@northben,这是因为“class”是C#中的保留关键字。您可以在C#规范中了解更多信息:http://msdn.microsoft.com/en-us/library/aa664670.aspx - Darin Dimitrov

4
以下方法可行。
 @using (Html.BeginForm("Profile", "Account", new { id=122}, FormMethod.Post, new { @class = "mainForm" }))

路由值是通过对象初始化语法创建的,即 new {key = value}。

我应该提到我不想直接使用对象初始化语法,即 new {key = value},因为我的代码需要一些逻辑来确定我想要传递什么。 - Erica

0

仅是一个想法,但即使对于多步骤表单,您是否希望选择将其全部设为GET或POST?在上面的示例中,看起来您正在使用POST与表单一起进行... 但仍然试图沿途使用GET。

为什么不沿途使用隐藏的POST值(使用HTML INPUT),以免用户更轻松地更改它们的值呢?(虽然在此应用程序中可能无关紧要。这基本上只是思考食品。)


0

所以你正在使用这个重载:

http://msdn.microsoft.com/en-us/library/dd460542.aspx

能否将args转换为一个带有键和值的简单对象?我认为这可能会解决你的问题。

根据文档:

参数是通过反射来检查对象的属性来获取的。通常使用对象初始化语法来创建该对象。 - 这似乎就是正在发生的事情 - 它使用反射来获取路由字典的属性 - 属性即为键(字符串集合)和值(对象集合)

另一种选择是不使用HTML助手,而是手动创建表单标签 - 虽然这有点违背了使用HTML助手的目的。


我之前在帖子中应该提到 - 需要一些逻辑来确定我想保留/清理/添加到参数的内容。也许我应该使用自定义的HtmlHelper? - Erica
我不确定在这里使用自定义HtmlHelper有什么好处 - 逻辑必须放在某个地方。 - ek_ny

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接