Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

MVC3 Html.BeginForm - passing arguments as RouteValueDictionary fails

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&amp;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&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 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&amp;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.

like image 548
Erica Avatar asked Jan 27 '12 02:01

Erica


2 Answers

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.

like image 69
Darin Dimitrov Avatar answered Jan 02 '23 16:01

Darin Dimitrov


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}

like image 31
Usama Khalil Avatar answered Jan 02 '23 16:01

Usama Khalil