问题
I have a multi-step setup process where I would like to pass query string arguments appended to the URL only if they are relevant.
http://localhost:6618/Account/Profile?wizard=true&cats=dogs
@using( Html.BeginForm() )
worked great. It yielded: <form action="/Account/Profile?setup=true&cats=dogs" method="post">
i.e. it passed into the POST action any of the original query string parameters, and then in that Controller action I could chose which ones were relevant to pass to my next step, or necessary to add, by adding to the RouteValues and a RedirectToResult.
However, I need to assign a class to my form for styling purposes.
I tried:
@using( Html.BeginForm( "Profile", "Account", args, FormMethod.Post, new { @class = "mainForm" } ) )
which yields:
<form action="/Account/Profile?Count=1&Keys=System.Collections.Generic.Dictionary%602%2BKeyCollection%5BSystem.String%2CSystem.Object%5D&Values=System.Collections.Generic.Dictionary%602%2BValueCollection%5BSystem.String%2CSystem.Object%5D" class="mainForm" method="post">
(args
was generated by a filter, and is a RouteValueDictionary). The specification http://msdn.microsoft.com/en-us/library/dd505151.aspx indicates that you can pass arguments with a System.Web.Routing.RouteValueDictionary.
What I want is <form action="/Account/Profile?setup=true&cats=dogs" class="mainForm" method="post">
I should mention I would prefer not to do something like passing in new {key = value}
instead, since there is a fair amount of logic to determine what I will be passing along to the next step.
Any suggestions on what to do here?
I am stymied by this seemingly simple task, and am surely missing something terribly obvious.
回答1:
args was generated by a filter, and is a RouteValueDictionary
That's the key point here. In this case make sure you are using the correct overload of the BeginForm method:
@using(Html.BeginForm(
"Profile",
"Account",
args,
FormMethod.Post,
new RouteValueDictionary(new { @class = "mainForm" })
))
{
...
}
Notice the last argument? It must be an IDictionary<string, object>
for this to work.
In your example it is this overload that gets picked up. But since you are passing a RouteValueDictionary
for the routeValues parameter instead of an anonymous object it gets messed up.
So, you should either have both routeValues and htmlAttributes as dictionaries or both as anonymous objects.
回答2:
Following will work.
@using (Html.BeginForm("Profile", "Account", new { id=122}, FormMethod.Post, new { @class = "mainForm" }))
the route value is created by object initialize syntax i.e new {key = value}
回答3:
So you're using this overload:
http://msdn.microsoft.com/en-us/library/dd460542.aspx
Is it possible to make args a simple object with keys and values? I think that might solve your problem.
According to docs:
The parameters are retrieved through reflection by examining the properties of the object. This object is typically created by using object initializer syntax. - this seems to be what is happening-- it's using reflections to get the properties of route dictionary- the properties being keys (collection of string) and values (collection of objects)
Another option would be to not use the html helper and create the form tag manually-- although that would kind of defeat the purpose of having the html helpers.
回答4:
Just a thought, but, even for a multi-step form, wouldn't you want to either choose to make it all GET or POST? In the example above... it looks like you are using POST with the form... but still trying to use GET along the way.
Why not just use hidden POST values (using HTML INPUTs,) along the way?
Otherwise, users could more-easily change the values, right? (Though, that might not matter in this application. And this is mostly just food for thought.)
来源:https://stackoverflow.com/questions/9028288/mvc3-html-beginform-passing-arguments-as-routevaluedictionary-fails